Init
This commit is contained in:
31
DependentExtensions/cat/AllCodec.hpp
Normal file
31
DependentExtensions/cat/AllCodec.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Codec headers
|
||||
|
||||
#include <cat/codec/RangeCoder.hpp>
|
||||
50
DependentExtensions/cat/AllCommon.hpp
Normal file
50
DependentExtensions/cat/AllCommon.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Common headers
|
||||
|
||||
#include <cat/time/Clock.hpp>
|
||||
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
#include <cat/rand/MersenneTwister.hpp>
|
||||
#include <cat/rand/StdRand.hpp>
|
||||
|
||||
#include <cat/hash/MurmurHash2.hpp>
|
||||
|
||||
#include <cat/threads/Atomic.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
#include <cat/threads/RWLock.hpp>
|
||||
#include <cat/threads/Thread.hpp>
|
||||
#include <cat/threads/WaitableFlag.hpp>
|
||||
|
||||
#include <cat/math/BitMath.hpp>
|
||||
|
||||
#include <cat/port/AlignedAlloc.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
|
||||
#include <cat/lang/Strings.hpp>
|
||||
45
DependentExtensions/cat/AllCrypt.hpp
Normal file
45
DependentExtensions/cat/AllCrypt.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Crypt headers
|
||||
|
||||
#include <cat/AllMath.hpp>
|
||||
|
||||
#include <cat/crypt/symmetric/ChaCha.hpp>
|
||||
|
||||
#include <cat/crypt/hash/ICryptHash.hpp>
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/crypt/hash/HMAC_MD5.hpp>
|
||||
|
||||
#include <cat/crypt/cookie/CookieJar.hpp>
|
||||
|
||||
#include <cat/crypt/SecureCompare.hpp>
|
||||
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
#include <cat/crypt/pass/Passwords.hpp>
|
||||
81
DependentExtensions/cat/AllFramework.hpp
Normal file
81
DependentExtensions/cat/AllFramework.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Framework headers
|
||||
|
||||
#ifndef CAT_ALL_FRAMEWORK_HPP
|
||||
#define CAT_ALL_FRAMEWORK_HPP
|
||||
|
||||
#include <cat/AllCommon.hpp>
|
||||
#include <cat/AllMath.hpp>
|
||||
#include <cat/AllCrypt.hpp>
|
||||
#include <cat/AllCodec.hpp>
|
||||
#include <cat/AllTunnel.hpp>
|
||||
#include <cat/AllGraphics.hpp>
|
||||
|
||||
#include <cat/threads/ThreadPool.hpp>
|
||||
#include <cat/threads/LocklessFIFO.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
#include <cat/threads/RegionAllocator.hpp>
|
||||
|
||||
#include <cat/io/Logging.hpp>
|
||||
#include <cat/io/MMapFile.hpp>
|
||||
#include <cat/io/Settings.hpp>
|
||||
#include <cat/io/Base64.hpp>
|
||||
|
||||
#include <cat/parse/BufferStream.hpp>
|
||||
#include <cat/parse/BitStream.hpp>
|
||||
#include <cat/parse/BufferTok.hpp>
|
||||
#include <cat/parse/MessageRouter.hpp>
|
||||
|
||||
#include <cat/net/Sockets.hpp>
|
||||
|
||||
#include <cat/io/ThreadPoolFiles.hpp>
|
||||
#include <cat/net/ThreadPoolSockets.hpp>
|
||||
|
||||
#include <cat/net/DNSClient.hpp>
|
||||
|
||||
#include <cat/net/SphynxTransport.hpp>
|
||||
#include <cat/net/SphynxServer.hpp>
|
||||
#include <cat/net/SphynxClient.hpp>
|
||||
|
||||
#include <cat/db/BombayTableIndex.hpp>
|
||||
#include <cat/db/BombayTable.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Specifying a service name will set up service mode
|
||||
bool InitializeFramework(const char *settings_file, const char *service_name = 0);
|
||||
|
||||
void ShutdownFramework(bool WriteSettings = true);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_ALL_FRAMEWORK_HPP
|
||||
36
DependentExtensions/cat/AllGraphics.hpp
Normal file
36
DependentExtensions/cat/AllGraphics.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Graphics headers
|
||||
|
||||
#include <cat/AllCommon.hpp>
|
||||
|
||||
#include <cat/gfx/Scalar.hpp>
|
||||
#include <cat/gfx/Vector.hpp>
|
||||
#include <cat/gfx/Matrix.hpp>
|
||||
#include <cat/gfx/Quaternion.hpp>
|
||||
36
DependentExtensions/cat/AllMath.hpp
Normal file
36
DependentExtensions/cat/AllMath.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Math headers
|
||||
|
||||
#include <cat/AllCommon.hpp>
|
||||
|
||||
#include <cat/math/BigRTL.hpp>
|
||||
#include <cat/math/BigMontgomery.hpp>
|
||||
#include <cat/math/BigPseudoMersenne.hpp>
|
||||
#include <cat/math/BigTwistedEdwards.hpp>
|
||||
41
DependentExtensions/cat/AllTunnel.hpp
Normal file
41
DependentExtensions/cat/AllTunnel.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Include all libcat Tunnel headers
|
||||
|
||||
#include <cat/AllCrypt.hpp>
|
||||
|
||||
#include <cat/crypt/tunnel/KeyMaker.hpp>
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreementInitiator.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreementResponder.hpp>
|
||||
|
||||
#include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
|
||||
|
||||
#include <cat/crypt/tunnel/EasyHandshake.hpp>
|
||||
59
DependentExtensions/cat/Config.hpp
Normal file
59
DependentExtensions/cat/Config.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_CONFIG_HPP
|
||||
#define CAT_CONFIG_HPP
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// This definition overrides CAT_BUILD_DLL below. Neuters CAT_EXPORT macro so symbols are
|
||||
// neither exported or imported.
|
||||
//#define CAT_NEUTER_EXPORT
|
||||
|
||||
// This definition changes the meaning of the CAT_EXPORT macro on Windows. When defined,
|
||||
// the CAT_EXPORT macro will export the associated symbol. When undefined, it will import it.
|
||||
//#define CAT_BUILD_DLL
|
||||
|
||||
// If you want to remove server-side code from a binary distribution of a client program:
|
||||
//#define CAT_OMIT_SERVER_CODE
|
||||
|
||||
// If you know the endianness of your target, uncomment one of these for better performance.
|
||||
//#define __LITTLE_ENDIAN__
|
||||
//#define __BIG_ENDIAN__
|
||||
|
||||
// If you want to use faster 384-bit or 512-bit math, define this:
|
||||
//#define CAT_UNROLL_OVER_256_BITS
|
||||
|
||||
// Adjust if your architecture uses larger than 128-byte cache line
|
||||
#define CAT_DEFAULT_CACHE_LINE_SIZE 128
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_CONFIG_HPP
|
||||
113
DependentExtensions/cat/LIBCAT.README.txt
Normal file
113
DependentExtensions/cat/LIBCAT.README.txt
Normal file
@ -0,0 +1,113 @@
|
||||
___ _ _____ _ ___
|
||||
/ __\__ _| |_ \_ \__| | / __\___ _ __ ___ _ __ ___ ___ _ __
|
||||
/ / / _` | __| / /\/ _` | / / / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \
|
||||
/ /__| (_| | |_/\/ /_| (_| | / /__| (_) | | | | | | | | | | | (_) | | | |
|
||||
\____/\__,_|\__\____/ \__,_| \____/\___/|_| |_| |_|_| |_| |_|\___/|_| |_|
|
||||
|
||||
___ _ __ _ _ _ ___
|
||||
/ __\___ __| | ___ / /(_) |__ _ __ __ _ _ __ _ _ / | / _ \
|
||||
/ / / _ \ / _` |/ _ \ / / | | '_ \| '__/ _` | '__| | | | | || | | |
|
||||
/ /__| (_) | (_| | __/ / /__| | |_) | | | (_| | | | |_| | | || |_| |
|
||||
\____/\___/ \__,_|\___| \____/_|_.__/|_| \__,_|_| \__, | |_(_)___/
|
||||
|___/
|
||||
CatId Common Code Library 1.0 07/23/2009
|
||||
|
||||
|
||||
|
||||
Released under a BSD-style license
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
======================= Contact the Author =============================
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Christopher A. Taylor
|
||||
|
||||
Email: mrcatid@gmail.com
|
||||
AIM: MrCatid
|
||||
MSN: MrCatid@hotmail.com
|
||||
WWW: http://catid.org
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
=========================== What's New =================================
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Latest revisions are available in the SVN log at libcatid.googlecode.com
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
============================== TODO ====================================
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Tunnel:
|
||||
Update the documentation
|
||||
.docx and .pdfs with lots of pictures
|
||||
|
||||
Portability:
|
||||
Port the code to Mac
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
============================= History ==================================
|
||||
------------------------------------------------------------------------
|
||||
|
||||
07/23/2009 - Added switches for demo of 384-bit and 512-bit security
|
||||
Fixed 384-bit version of BigRTL::Load and BigRTL::Store
|
||||
Implemented template metaprogramming Comba Multiply
|
||||
07/22/2009 - Visual Studio 2005 version works again
|
||||
07/21/2009 - Split math code across many source files
|
||||
Reorganized the project for easier reuse
|
||||
07/20/2009 - New key agreement protocol "Tabby" is working
|
||||
New functions added to BigTwistedEdward to support it
|
||||
Added <cat/port/AlignedAlloc.hpp> to align all math regs
|
||||
Optimized 32-bit version; now twice as fast as before
|
||||
07/19/2009 - Pulled out all the old Tunnel code and rewrote it
|
||||
07/17/2009 - Added <cat/crypt/rand/Fortuna.hpp>
|
||||
07/15/2009 - Half way through writing Fortuna
|
||||
Slightly faster scalar point multiplication precomputation
|
||||
Worked on basic outline for new AKE protocol
|
||||
07/14/2009 - Implemented and tested HMAC-MD5; this is now the Tunnel MAC
|
||||
Several bug fixes
|
||||
07/13/2009 - Fixed Tunnel vulnerability to active small subgroup attack
|
||||
Fixed a bug in MrNegate()
|
||||
07/12/2009 - Added inline assembly code for MultiplyXAdd()
|
||||
Added fast timing-attack resistant modular inversion
|
||||
Optimized MrSquareRoot() with a smaller window
|
||||
07/11/2009 - All the math code is working again! Woohoo! =)
|
||||
Added <cat/crypt/SecureCompare.hpp> to replace memcmp()
|
||||
07/10/2009 - Wrote 64-bit assembly code version of Divide()
|
||||
07/09/2009 - In the middle of getting math working again
|
||||
07/07/2009 - Merged Skein256 and Skein512 into the same object
|
||||
07/02/2009 - Refactored math code; put a lot of unused code in the attic
|
||||
Added specialized 256-bit assembly code to math library
|
||||
06/25/2009 - Improved replay attack protection to 1024 bits
|
||||
06/24/2009 - Increased IV bits to 24 and moved IV code to TunnelSession
|
||||
Tunnel now has replay attack protection
|
||||
Fix: Tunnel only updates remote IV if it increased
|
||||
Split BigInt source across many files
|
||||
06/23/2009 - Tunnel uses Skein for a MAC
|
||||
Tunnel no longer requires a cookie exchange
|
||||
Removed support for SHA-2 in favor of Skein
|
||||
Added math/EndianNeutral.hpp to Common
|
||||
Added math/BitMath.hpp to Common
|
||||
Added threads/Atomic.hpp to Common
|
||||
06/20/2009 - Supports 512-bit ECC
|
||||
CookieJar now Supports IPv6 and variable-length addresses
|
||||
Put CAT_ before global macros
|
||||
Split up library into even more projects
|
||||
06/19/2009 - Now can select a bit-twiddling version of w-MOF
|
||||
06/16/2009 - Implemented Skein-256 and Skein-512 and timing tests
|
||||
06/15/2009 - Implemented SHA-512 (and SHA-384) and unit tests
|
||||
ChaCha cipher now accepts up to 384-bit keys
|
||||
Hash and PRNG objects are now implemented from an interface
|
||||
Improved lockless FIFO code with opportunistic algorithm
|
||||
Now supports 384-bit ECC
|
||||
06/14/2009 - Added <cat/crypto/Tunnel.hpp> and /docs/tunnel.pdf
|
||||
06/13/2009 - Added ChaCha::ReconstructIV
|
||||
06/12/2009 - Fixed endian neutrality of the Sha256 hash, so also ECC
|
||||
Added full handshake demo to the ECC unit test
|
||||
06/11/2009 - Split the math code off from the framework code
|
||||
06/10/2009 - Merged my code into this library for the first time
|
||||
|
||||
583
DependentExtensions/cat/Platform.hpp
Normal file
583
DependentExtensions/cat/Platform.hpp
Normal file
@ -0,0 +1,583 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_PLATFORM_HPP
|
||||
#define CAT_PLATFORM_HPP
|
||||
|
||||
#include <cat/Config.hpp>
|
||||
#include <string.h>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// Compiler ////
|
||||
|
||||
// Mac OS X additional compilation flags
|
||||
#ifdef __APPLE__
|
||||
# include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Intel C++ Compiler : Interoperates with MSVC and GCC
|
||||
#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)
|
||||
# define CAT_COMPILER_ICC
|
||||
# define CAT_FENCE_COMPILER __memory_barrier();
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Borland C++ Compiler : Compatible with MSVC syntax
|
||||
#if defined(__BORLANDC__)
|
||||
# define CAT_COMPILER_BORLAND
|
||||
# define CAT_COMPILER_COMPAT_MSVC
|
||||
# define CAT_INLINE __inline
|
||||
# define CAT_ASM_EMIT __emit__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Digital Mars C++ Compiler (previously known as Symantec C++)
|
||||
#elif defined(__DMC__) || defined(__SC__) || defined(__SYMANTECC__)
|
||||
# define CAT_COMPILER_DMARS
|
||||
# define CAT_COMPILER_COMPAT_MSVC
|
||||
# define CAT_INLINE __inline
|
||||
# define CAT_ASM_EMIT __emit__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Codeplay VectorC C++ Compiler : Compatible with GCC and MSVC syntax, prefer GCC
|
||||
#elif defined(__VECTORC__)
|
||||
# define CAT_COMPILER_CODEPLAY
|
||||
# define CAT_COMPILER_COMPAT_GCC
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Pathscale C++ Compiler : Compatible with GCC syntax
|
||||
#elif defined(__PATHSCALE__)
|
||||
# define CAT_COMPILER_PATHSCALE
|
||||
# define CAT_COMPILER_COMPAT_GCC
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Watcom C++ Compiler : Compatible with GCC and MSVC syntax, prefer GCC
|
||||
#elif defined(__WATCOMC__)
|
||||
# define CAT_COMPILER_WATCOM
|
||||
# define CAT_COMPILER_COMPAT_GCC
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SUN C++ Compiler : Compatible with GCC syntax
|
||||
#elif defined(__SUNPRO_CC)
|
||||
# define CAT_COMPILER_SUN
|
||||
# define CAT_COMPILER_COMPAT_GCC
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Metrowerks C++ Compiler : Compatible with MSVC syntax
|
||||
#elif defined(__MWERKS__)
|
||||
# define CAT_COMPILER_MWERKS
|
||||
# define CAT_COMPILER_COMPAT_MSVC
|
||||
# define CAT_INLINE inline
|
||||
# define CAT_ASM_BEGIN _asm {
|
||||
# define CAT_ASM_EMIT __emit__
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// GNU C++ Compiler
|
||||
// SN Systems ProDG C++ Compiler : Compatible with GCC
|
||||
#elif defined(__GNUC__) || defined(__APPLE_CC__) || defined(__SNC__)
|
||||
# define CAT_COMPILER_GCC
|
||||
# define CAT_COMPILER_COMPAT_GCC
|
||||
# define CAT_FASTCALL __attribute__ ((fastcall))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Microsoft Visual Studio C++ Compiler
|
||||
#elif defined(_MSC_VER)
|
||||
# define CAT_COMPILER_MSVC
|
||||
# define CAT_COMPILER_COMPAT_MSVC
|
||||
# define CAT_FASTCALL __fastcall
|
||||
|
||||
} // namespace cat
|
||||
# include <cstdlib> // Intrinsics
|
||||
# include <intrin.h> // Intrinsics
|
||||
namespace cat {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Otherwise unknown compiler
|
||||
#else
|
||||
# define CAT_COMPILER_UNKNOWN
|
||||
# define CAT_ALIGNED(n) /* no way to detect alignment syntax */
|
||||
# define CAT_PACKED /* no way to detect packing syntax */
|
||||
# define CAT_INLINE inline
|
||||
// No way to support inline assembly code here
|
||||
# define CAT_RESTRICT
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
A lot of compilers have similar syntax to MSVC or GCC,
|
||||
so for simplicity I have those two defined below, and
|
||||
any deviations are implemented with overrides above.
|
||||
*/
|
||||
|
||||
// MSVC-compatible compilers
|
||||
#if defined(CAT_COMPILER_COMPAT_MSVC)
|
||||
|
||||
#if !defined(CAT_ALIGNED)
|
||||
# define CAT_ALIGNED(n) __declspec(align(n))
|
||||
#endif
|
||||
#if !defined(CAT_PACKED)
|
||||
# define CAT_PACKED
|
||||
# define CAT_PRAGMA_PACK
|
||||
#endif
|
||||
#if !defined(CAT_INLINE)
|
||||
# define CAT_INLINE __forceinline
|
||||
#endif
|
||||
#if !defined(CAT_ASM_INTEL)
|
||||
# define CAT_ASM_INTEL
|
||||
#endif
|
||||
#if !defined(CAT_ASM_BEGIN)
|
||||
# define CAT_ASM_BEGIN __asm {
|
||||
#endif
|
||||
#if !defined(CAT_ASM_EMIT)
|
||||
# define CAT_ASM_EMIT _emit
|
||||
#endif
|
||||
#if !defined(CAT_ASM_END)
|
||||
# define CAT_ASM_END }
|
||||
#endif
|
||||
#if !defined(CAT_TLS)
|
||||
# define CAT_TLS __declspec( thread )
|
||||
#endif
|
||||
#if !defined(CAT_RESTRICT)
|
||||
# define CAT_RESTRICT __restrict
|
||||
#endif
|
||||
#if !defined(CAT_FENCE_COMPILER)
|
||||
# if defined(CAT_COMPILER_MSVC)
|
||||
# pragma intrinsic(_ReadWriteBarrier)
|
||||
# endif
|
||||
# define CAT_FENCE_COMPILER _ReadWriteBarrier();
|
||||
#endif
|
||||
#if !defined(CAT_DLL_EXPORT)
|
||||
# define CAT_DLL_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
#if !defined(CAT_DLL_IMPORT)
|
||||
# define CAT_DLL_IMPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
// GCC-compatible compilers
|
||||
#elif defined(CAT_COMPILER_COMPAT_GCC)
|
||||
|
||||
#if !defined(CAT_ALIGNED)
|
||||
# define CAT_ALIGNED(n) __attribute__ ((aligned (n)))
|
||||
#endif
|
||||
#if !defined(CAT_PACKED)
|
||||
# define CAT_PACKED __attribute__ ((packed))
|
||||
#endif
|
||||
#if !defined(CAT_INLINE)
|
||||
# define CAT_INLINE inline /* __inline__ __attribute__((always_inline)) */
|
||||
#endif
|
||||
#if !defined(CAT_ASM_ATT)
|
||||
# define CAT_ASM_ATT
|
||||
#endif
|
||||
#if !defined(CAT_ASM_BEGIN)
|
||||
# define CAT_ASM_BEGIN __asm__ __volatile__ (
|
||||
#endif
|
||||
#if !defined(CAT_ASM_EMIT)
|
||||
# define CAT_ASM_EMIT .byte
|
||||
#endif
|
||||
#if !defined(CAT_ASM_END)
|
||||
# define CAT_ASM_END );
|
||||
#endif
|
||||
#if !defined(CAT_TLS)
|
||||
# define CAT_TLS __thread
|
||||
#endif
|
||||
#if !defined(CAT_RESTRICT)
|
||||
# define CAT_RESTRICT __restrict__
|
||||
#endif
|
||||
#if !defined(CAT_FENCE_COMPILER)
|
||||
# define CAT_FENCE_COMPILER CAT_ASM_BEGIN "" ::: "memory" CAT_ASM_END
|
||||
#endif
|
||||
#if !defined(CAT_DLL_EXPORT)
|
||||
# define CAT_DLL_EXPORT __attribute__((dllexport))
|
||||
#endif
|
||||
#if !defined(CAT_DLL_IMPORT)
|
||||
# define CAT_DLL_IMPORT __attribute__((dllimport))
|
||||
#endif
|
||||
|
||||
#endif // CAT_COMPILER_COMPAT_*
|
||||
|
||||
|
||||
//// Debug Flag ////
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
# if defined(_DEBUG)
|
||||
# define CAT_DEBUG
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# if !defined(NDEBUG)
|
||||
# define CAT_DEBUG
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//// Instruction Set Architecture ////
|
||||
|
||||
#if defined(__powerpc__) || defined(__ppc__) || defined(_POWER) || defined(_M_PPC) || \
|
||||
defined(_M_MPPC) || defined(__POWERPC) || defined(powerpc) || defined(__ppc64__) || \
|
||||
defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3) || defined(__POWERPC__)
|
||||
# define CAT_ISA_PPC
|
||||
|
||||
#elif defined(__i386__) || defined(i386) || defined(intel) || defined(_M_IX86) || \
|
||||
defined(__ia64) || defined(__ia64__) || defined(__x86_64) || defined(_M_IA64) || \
|
||||
defined(_M_X64)
|
||||
# define CAT_ISA_X86
|
||||
|
||||
#elif defined(TARGET_CPU_ARM)
|
||||
# define CAT_ISA_ARM
|
||||
|
||||
#elif defined(__mips__)
|
||||
# define CAT_ISA_MIPS
|
||||
|
||||
#elif defined(__ALPHA__)
|
||||
# define CAT_ISA_ALPHA
|
||||
|
||||
#else
|
||||
# define CAT_ISA_UNKNOWN
|
||||
#endif
|
||||
|
||||
|
||||
//// Endianness ////
|
||||
|
||||
// Okay -- Technically IA64 and PPC can switch endianness with an MSR bit
|
||||
// flip, but come on no one does that! ...Right?
|
||||
// If it's not right, make sure that one of the first two flags are defined.
|
||||
#if defined(__LITTLE_ENDIAN__)
|
||||
# define CAT_ENDIAN_LITTLE
|
||||
#elif defined(__BIG_ENDIAN__)
|
||||
# define CAT_ENDIAN_BIG
|
||||
#elif defined(CAT_ISA_X86)
|
||||
# define CAT_ENDIAN_LITTLE
|
||||
#elif defined(CAT_ISA_PPC)
|
||||
# define CAT_ENDIAN_BIG
|
||||
#else
|
||||
# define CAT_ENDIAN_UNKNOWN /* Must be detected at runtime */
|
||||
#endif
|
||||
|
||||
|
||||
//// Word Size ////
|
||||
|
||||
#if defined(_LP64) || defined(__LP64__) || defined(__arch64__) || \
|
||||
defined(_WIN64) || defined(_M_X64) || defined(__ia64) || \
|
||||
defined(__ia64__) || defined(__x86_64) || defined(_M_IA64) || \
|
||||
defined(__mips64)
|
||||
|
||||
# define CAT_WORD_64
|
||||
|
||||
// 64-bit MSVC does not support inline assembly
|
||||
# if defined(CAT_COMPILER_MSVC)
|
||||
# undef CAT_ASM_INTEL
|
||||
# endif
|
||||
|
||||
#else // Assuming 32-bit otherwise!
|
||||
|
||||
# define CAT_WORD_32
|
||||
|
||||
#endif
|
||||
|
||||
// __fastcall calling convention is rarely supported, and doesn't make sense for 64-bit targets
|
||||
#if !defined(CAT_FASTCALL)
|
||||
# define CAT_FASTCALL
|
||||
#elif !defined(CAT_ISA_X86) || defined(CAT_WORD_64)
|
||||
# undef CAT_FASTCALL
|
||||
# define CAT_FASTCALL
|
||||
#endif
|
||||
|
||||
|
||||
//// Operating System ////
|
||||
|
||||
#if defined(__APPLE__) && defined(TARGET_OS_IPHONE)
|
||||
# define CAT_OS_IPHONE
|
||||
# define CAT_OS_APPLE
|
||||
|
||||
#elif defined(__APPLE__) && (defined(__MACH__) || defined(__DARWIN__))
|
||||
# define CAT_OS_OSX
|
||||
# define CAT_OS_APPLE
|
||||
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
# define CAT_OS_BSD
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__)
|
||||
# define CAT_OS_LINUX
|
||||
|
||||
#elif defined(_WIN32_WCE)
|
||||
# define CAT_OS_WINDOWS_CE
|
||||
# define CAT_OS_WINDOWS /* Also defined */
|
||||
|
||||
#elif defined(_WIN32)
|
||||
# define CAT_OS_WINDOWS
|
||||
|
||||
#elif defined(_XBOX) || defined(_X360)
|
||||
# define CAT_OS_XBOX
|
||||
|
||||
#elif defined(_PS3) || defined(__PS3__) || defined(SN_TARGET_PS3)
|
||||
# define CAT_OS_PS3
|
||||
|
||||
#elif defined(__OS2__)
|
||||
# define CAT_OS_OS2
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
# define CAT_OS_APPLE
|
||||
|
||||
#else
|
||||
# define CAT_OS_UNKNOWN
|
||||
#endif
|
||||
|
||||
// Detect CYGWIN environment
|
||||
#if defined(__CYGWIN__) || defined(__CYGWIN32__)
|
||||
# define CAT_CYGWIN
|
||||
#endif
|
||||
|
||||
// DLL import/export macros based on OS
|
||||
#if defined(CAT_OS_WINDOWS) || defined(CAT_CYGWIN)
|
||||
|
||||
# if defined(CAT_NEUTER_EXPORT)
|
||||
# define CAT_EXPORT /* Do not import or export any symbols */
|
||||
# elif defined(CAT_BUILD_DLL)
|
||||
# define CAT_EXPORT CAT_DLL_EXPORT /* Implementing a DLL so export this symbol */
|
||||
# else
|
||||
# define CAT_EXPORT CAT_DLL_IMPORT /* Using a DLL so import this symbol, faster on Windows */
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# undef CAT_DLL_EXPORT
|
||||
# undef CAT_DLL_IMPORT
|
||||
# define CAT_DLL_EXPORT
|
||||
# define CAT_DLL_IMPORT
|
||||
# define CAT_EXPORT
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//// Basic types ////
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
// MSVC does not ship with stdint.h (C99 standard...)
|
||||
typedef unsigned __int8 u8;
|
||||
typedef signed __int8 s8;
|
||||
typedef unsigned __int16 u16;
|
||||
typedef signed __int16 s16;
|
||||
typedef unsigned __int32 u32;
|
||||
typedef signed __int32 s32;
|
||||
typedef unsigned __int64 u64;
|
||||
typedef signed __int64 s64;
|
||||
|
||||
#else
|
||||
|
||||
} // namespace cat
|
||||
#include <stdint.h>
|
||||
namespace cat {
|
||||
|
||||
// All other compilers use this
|
||||
typedef uint8_t u8;
|
||||
typedef int8_t s8;
|
||||
typedef uint16_t u16;
|
||||
typedef int16_t s16;
|
||||
typedef uint32_t u32;
|
||||
typedef int32_t s32;
|
||||
typedef uint64_t u64;
|
||||
typedef int64_t s64;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CAT_COMPILER_GCC) && defined(CAT_WORD_64)
|
||||
|
||||
// GCC also adds 128-bit types :D
|
||||
typedef __uint128_t u128;
|
||||
typedef __int128_t s128;
|
||||
|
||||
#endif
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
union Float32 {
|
||||
float f;
|
||||
u32 i;
|
||||
|
||||
Float32(float n) { f = n; }
|
||||
Float32(u32 n) { i = n; }
|
||||
};
|
||||
|
||||
|
||||
//// String and buffer macros ////
|
||||
|
||||
// Same as strncpy() in all ways except that the result is guaranteed to
|
||||
// be a nul-terminated C string
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
# define CAT_STRNCPY(dest, src, size) { strncpy_s(dest, size, src, size); (dest)[(size)-1] = '\0'; }
|
||||
#else
|
||||
# define CAT_STRNCPY(dest, src, size) { strncpy(dest, src, size); (dest)[(size)-1] = '\0'; }
|
||||
#endif
|
||||
|
||||
// Because memory clearing is a frequent operation
|
||||
#define CAT_CLR(dest, size) memset(dest, 0, size)
|
||||
|
||||
// Works for arrays, also
|
||||
#define CAT_OBJCLR(object) memset((void*)&(object), 0, sizeof(object))
|
||||
|
||||
// Stringize
|
||||
#define CAT_STRINGIZE(X) DO_CAT_STRINGIZE(X)
|
||||
#define DO_CAT_STRINGIZE(X) #X
|
||||
|
||||
// Variable-length data trailing a struct
|
||||
template<typename T> CAT_INLINE u8 *GetTrailingBytes(T *t) { return reinterpret_cast<u8*>( t ) + sizeof(T); }
|
||||
|
||||
// Bounds
|
||||
template<typename T> CAT_INLINE T BoundMin(const T &minimum, const T &x)
|
||||
{
|
||||
if (x < minimum) return minimum;
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T> CAT_INLINE T BoundMax(const T &maximum, const T &x)
|
||||
{
|
||||
if (x > maximum) return maximum;
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T> CAT_INLINE T Bound(const T &minimum, const T &maximum, const T &x)
|
||||
{
|
||||
if (x < minimum) return minimum;
|
||||
if (x > maximum) return maximum;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
//// Miscellaneous bitwise macros ////
|
||||
|
||||
#define CAT_BITCLRHI8(reg, count) ((u8)((u8)(reg) << (count)) >> (count)) /* sets to zero a number of high bits in a byte */
|
||||
#define CAT_BITCLRLO8(reg, count) ((u8)((u8)(reg) >> (count)) << (count)) /* sets to zero a number of low bits in a byte */
|
||||
#define CAT_BITCLRHI16(reg, count) ((u16)((u16)(reg) << (count)) >> (count)) /* sets to zero a number of high bits in a 16-bit word */
|
||||
#define CAT_BITCLRLO16(reg, count) ((u16)((u16)(reg) >> (count)) << (count)) /* sets to zero a number of low bits in a 16-bit word */
|
||||
#define CAT_BITCLRHI32(reg, count) ((u32)((u32)(reg) << (count)) >> (count)) /* sets to zero a number of high bits in a 32-bit word */
|
||||
#define CAT_BITCLRLO32(reg, count) ((u32)((u32)(reg) >> (count)) << (count)) /* sets to zero a number of low bits in a 32-bit word */
|
||||
|
||||
|
||||
//// Integer macros ////
|
||||
|
||||
#define CAT_AT_LEAST_2_BITS(n) ( (n) & ((n) - 1) )
|
||||
#define CAT_LEAST_SIGNIFICANT_BIT(n) ( (n) & (u32)(-(s32)(n)) ) /* 0 -> 0 */
|
||||
#define CAT_IS_POWER_OF_2(n) ( n && !CAT_AT_LEAST_2_BITS(n) )
|
||||
|
||||
// Safely take the average of two numbers without possibility of overflow
|
||||
#define CAT_SAFE_AVERAGE(A, B) (((A) & (B)) + (((A) ^ (B)) >> 1))
|
||||
|
||||
// Bump 'n' to the next unit of 'width'
|
||||
// 0=CAT_CEIL_UNIT(0, 16), 1=CAT_CEIL_UNIT(1, 16), 1=CAT_CEIL_UNIT(16, 16), 2=CAT_CEIL_UNIT(17, 16)
|
||||
#define CAT_CEIL_UNIT(n, width) ( ( (n) + (width) - 1 ) / (width) )
|
||||
// 0=CAT_CEIL(0, 16), 16=CAT_CEIL(1, 16), 16=CAT_CEIL(16, 16), 32=CAT_CEIL(17, 16)
|
||||
#define CAT_CEIL(n, width) ( CAT_CEIL_UNIT(n, width) * (width) )
|
||||
|
||||
|
||||
//// Rotation macros ////
|
||||
|
||||
#define CAT_ROL8(n, r) ( ((u8)(n) << (r)) | ((u8)(n) >> ( 8 - (r))) ) /* only works for u8 */
|
||||
#define CAT_ROR8(n, r) ( ((u8)(n) >> (r)) | ((u8)(n) << ( 8 - (r))) ) /* only works for u8 */
|
||||
#define CAT_ROL16(n, r) ( ((u16)(n) << (r)) | ((u16)(n) >> (16 - (r))) ) /* only works for u16 */
|
||||
#define CAT_ROR16(n, r) ( ((u16)(n) >> (r)) | ((u16)(n) << (16 - (r))) ) /* only works for u16 */
|
||||
#define CAT_ROL32(n, r) ( ((u32)(n) << (r)) | ((u32)(n) >> (32 - (r))) ) /* only works for u32 */
|
||||
#define CAT_ROR32(n, r) ( ((u32)(n) >> (r)) | ((u32)(n) << (32 - (r))) ) /* only works for u32 */
|
||||
#define CAT_ROL64(n, r) ( ((u64)(n) << (r)) | ((u64)(n) >> (64 - (r))) ) /* only works for u64 */
|
||||
#define CAT_ROR64(n, r) ( ((u64)(n) >> (r)) | ((u64)(n) << (64 - (r))) ) /* only works for u64 */
|
||||
|
||||
|
||||
//// Byte-order swapping ////
|
||||
|
||||
#define CAT_BOSWAP16(n) CAT_ROL16(n, 8)
|
||||
#define CAT_BOSWAP32(n) ( (CAT_ROL32(n, 8) & 0x00ff00ff) | (CAT_ROL32(n, 24) & 0xff00ff00) )
|
||||
#define CAT_BOSWAP64(n) ( ((u64)CAT_BOSWAP32((u32)n) << 32) | CAT_BOSWAP32((u32)(n >> 32)) )
|
||||
|
||||
|
||||
//// Intrinsics ////
|
||||
|
||||
#if defined(CAT_OS_WINDOWS_CE)
|
||||
|
||||
#pragma intrinsic(_lrotl)
|
||||
#pragma intrinsic(_lrotr)
|
||||
|
||||
#undef CAT_ROL32
|
||||
#undef CAT_ROR32
|
||||
|
||||
#define CAT_ROL32(n, r) _lrotl(n, r)
|
||||
#define CAT_ROR32(n, r) _lrotr(n, r)
|
||||
|
||||
#elif defined(CAT_COMPILER_MSVC)
|
||||
|
||||
#pragma intrinsic(_rotl)
|
||||
#pragma intrinsic(_rotr)
|
||||
#pragma intrinsic(_rotl64)
|
||||
#pragma intrinsic(_rotr64)
|
||||
#pragma intrinsic(_byteswap_ushort)
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#pragma intrinsic(_BitScanReverse)
|
||||
#pragma intrinsic(__emulu)
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
#pragma intrinsic(_interlockedbittestandset)
|
||||
#pragma intrinsic(_interlockedbittestandreset)
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
#pragma intrinsic(__rdtsc)
|
||||
#pragma intrinsic(_umul128)
|
||||
#pragma intrinsic(_BitScanForward64)
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#pragma intrinsic(_InterlockedCompareExchange128)
|
||||
#else
|
||||
#pragma intrinsic(_InterlockedCompareExchange64)
|
||||
#endif
|
||||
|
||||
#undef CAT_ROL32
|
||||
#undef CAT_ROR32
|
||||
#undef CAT_ROL64
|
||||
#undef CAT_ROR64
|
||||
#undef CAT_BOSWAP16
|
||||
#undef CAT_BOSWAP32
|
||||
#undef CAT_BOSWAP64
|
||||
|
||||
#define CAT_ROL32(n, r) _rotl(n, r)
|
||||
#define CAT_ROR32(n, r) _rotr(n, r)
|
||||
#define CAT_ROL64(n, r) _rotl64(n, r)
|
||||
#define CAT_ROR64(n, r) _rotr64(n, r)
|
||||
#define CAT_BOSWAP16(n) _byteswap_ushort(n)
|
||||
#define CAT_BOSWAP32(n) _byteswap_ulong(n)
|
||||
#define CAT_BOSWAP64(n) _byteswap_uint64(n)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_PLATFORM_HPP
|
||||
80
DependentExtensions/cat/Singleton.hpp
Normal file
80
DependentExtensions/cat/Singleton.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SINGLETON_HPP
|
||||
#define CAT_SINGLETON_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Derived class should define the constructor using this macro:
|
||||
#define CAT_SINGLETON(subclass) \
|
||||
private: \
|
||||
friend class Singleton<subclass>; \
|
||||
subclass()
|
||||
|
||||
|
||||
//// Singleton
|
||||
|
||||
template<class T> class Singleton
|
||||
{
|
||||
protected:
|
||||
Singleton<T>() {}
|
||||
Singleton<T>(Singleton<T> &) {}
|
||||
Singleton<T> &operator=(Singleton<T> &) {}
|
||||
|
||||
public:
|
||||
static T *ii;
|
||||
|
||||
public:
|
||||
CAT_INLINE static T *ref()
|
||||
{
|
||||
if (ii) return ii;
|
||||
return ii = new T;
|
||||
}
|
||||
CAT_INLINE static void deallocate()
|
||||
{
|
||||
if (ii)
|
||||
{
|
||||
delete ii;
|
||||
ii = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~Singleton() {}
|
||||
};
|
||||
|
||||
// TODO: I'm actually not 100% sure this always works
|
||||
template<class T> T *Singleton<T>::ii = 0;
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SINGLETON_HPP
|
||||
56
DependentExtensions/cat/asm/big_x64_asm.hpp
Normal file
56
DependentExtensions/cat/asm/big_x64_asm.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Forward declaration for assembly routines in big_x64_*.asm
|
||||
|
||||
#ifndef CAT_BIG_X64_ASM_HPP
|
||||
#define CAT_BIG_X64_ASM_HPP
|
||||
|
||||
#include <cat/math/Legs.hpp>
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
extern "C" void bpm_add_4(Leg modulus_c, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
extern "C" void bpm_sub_4(Leg modulus_c, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
extern "C" void bpm_mul_4(Leg modulus_c, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
extern "C" void bpm_mulx_4(Leg modulus_c, const Leg *in_a, Leg in_b, Leg *out);
|
||||
extern "C" void bpm_sqr_4(Leg modulus_c, const Leg *in, Leg *out);
|
||||
|
||||
extern "C" Leg divide64_x(Leg legs, const Leg *in_a, const Leg in_b, Leg *out_q);
|
||||
extern "C" Leg modulus64_x(Leg legs, const Leg *in_a, const Leg in_b);
|
||||
extern "C" void divide64_core(Leg A_used, Leg A_overflow, const Leg *A, Leg B_used, const Leg *B, Leg *Q);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_WORD_64
|
||||
|
||||
#endif // CAT_BIG_X64_ASM_HPP
|
||||
1194
DependentExtensions/cat/codec/ChatText.stats
Normal file
1194
DependentExtensions/cat/codec/ChatText.stats
Normal file
File diff suppressed because it is too large
Load Diff
219
DependentExtensions/cat/codec/RangeCoder.hpp
Normal file
219
DependentExtensions/cat/codec/RangeCoder.hpp
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_RANGE_CODER_HPP
|
||||
#define CAT_RANGE_CODER_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <ostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
TextStatsCollector
|
||||
|
||||
Collects order-1 statistics of the text given one character at a time.
|
||||
Order-1 statistics include the likelihood of a character given the previous one.
|
||||
|
||||
This is intended to be used on a large sample of text (of unlimited length)
|
||||
to come up with statistics that most text should follow. When the resulting
|
||||
table is used with a range coder, compression should be reliably achieved,
|
||||
though a bit should be allocated for the case where the result of the coder
|
||||
would be longer than encoding with uniform ranges, like if someone enters "ZZZZ".
|
||||
|
||||
The RangeEncoder class has a text compressor based on the output of this class.
|
||||
|
||||
I opted for a static table because this is to be run on a network server
|
||||
where many clients are connected. The memory needed for this type of
|
||||
compression does not increase with the number of clients.
|
||||
*/
|
||||
class TextStatsCollector
|
||||
{
|
||||
u32 last, total, frequencies[256][256];
|
||||
u8 seen[256];
|
||||
|
||||
public:
|
||||
TextStatsCollector();
|
||||
|
||||
public:
|
||||
// Record a character occurance
|
||||
// 0 = end of line, so next character counts towards initial character frequency
|
||||
void Tally(u8 x);
|
||||
|
||||
#if defined(CAT_PRAGMA_PACK)
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
struct TableFormat
|
||||
{
|
||||
// MurmurHash2 of remainder, with seed = 0
|
||||
u32 hash;
|
||||
|
||||
// Total symbols in the table <= 256
|
||||
u16 total;
|
||||
|
||||
// Fraction of a byte represented by total, scaled from [0, 2^15]
|
||||
u16 log2total;
|
||||
|
||||
// ASCII character code -> Table index map
|
||||
u8 char2index[256];
|
||||
|
||||
// Table index -> ASCII character code map
|
||||
u8 index2char[256];
|
||||
|
||||
/*
|
||||
Start of frequency table
|
||||
|
||||
The first 32 entries are used for reverse lookup (freq->symbol):
|
||||
GET_SYMBOL_LUT() will get this address:
|
||||
frequencies[0..15] = array of 16 bytes creating a lookup table (LUT) given
|
||||
the high 4 bits of the frequency, for the low range
|
||||
frequencies[16..31] = array of 16 bytes creating a lookup table (LUT) given
|
||||
the high 4 bits of the frequency, for the high range
|
||||
|
||||
GET_SYMBOL_BASE() will get this address:
|
||||
frequencies[32] = cumulative frequency for (last=0, this=1) out of 2^16 trials
|
||||
frequencies[33] = cumulative frequency for (last=0, this=2) out of 2^16 trials
|
||||
frequencies[34] = ...
|
||||
|
||||
Note: (0, 0) is implicitly zero, and (0, TOTAL) is implicitly 2^16
|
||||
So these tables don't include those implicit entries.
|
||||
*/
|
||||
u16 frequencies[1];
|
||||
} CAT_PACKED;
|
||||
|
||||
#if defined(CAT_PRAGMA_PACK)
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Returns code that creates a table in the above format
|
||||
bool GenerateMinimalStaticTable(const char *TableName, std::ostream &osout);
|
||||
|
||||
// Check for errors in the in-memory version of the table that was generated
|
||||
static bool VerifyTableIntegrity(const TableFormat *table);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Range Encoder
|
||||
|
||||
Encodes a single message one field at a time using the minimum
|
||||
number of bits, rounded up to the next highest byte.
|
||||
|
||||
To insure that the message does not grow in size, provide limited
|
||||
space for the output buffer and check .Fail() at the end. If it
|
||||
failed, this means it ran out of space during encoding.
|
||||
|
||||
If encoding succeeded, check .Used() to determine the number of
|
||||
bytes used by the output buffer.
|
||||
*/
|
||||
class RangeEncoder
|
||||
{
|
||||
u8 *output;
|
||||
int limit, remaining;
|
||||
|
||||
u64 low, range;
|
||||
|
||||
// Write out bytes as needed
|
||||
CAT_INLINE void Normalize();
|
||||
|
||||
CAT_INLINE void GetTableSymbol(const TextStatsCollector::TableFormat *stats, u32 &last, u8 ch, u16 &symbol_low, u16 &symbol_range);
|
||||
|
||||
public:
|
||||
// Ctors
|
||||
RangeEncoder(void *output_i, int limit_i);
|
||||
RangeEncoder(RangeEncoder &cp);
|
||||
|
||||
// Overwrite one context with another. Using context references instead
|
||||
// of working on the contexts directly is probably more efficient.
|
||||
RangeEncoder &operator=(RangeEncoder &cp);
|
||||
|
||||
// State accessors
|
||||
bool Fail() { return output == 0; }
|
||||
int Used() { return limit - remaining; }
|
||||
|
||||
public:
|
||||
// Encode the given text with the given statistics
|
||||
// NOTE: May be up to one byte longer than the original message
|
||||
void Text(const char *msg, const TextStatsCollector::TableFormat *stats);
|
||||
|
||||
// Encode a biased bit given the frequency it is 0
|
||||
// frequency = average times out of 2^32 trials the bit will be 0
|
||||
void BiasedBit(u32 b, u32 frequency);
|
||||
|
||||
// Encode a field that takes on [0, total) values with equal likelihood
|
||||
void Range(u32 symbol, u32 total);
|
||||
|
||||
// Emit the final byte(s) needed to encode the symbols
|
||||
void Finish();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Range Decoder
|
||||
|
||||
Interprets buffers produced by RangeEncoder
|
||||
*/
|
||||
class RangeDecoder
|
||||
{
|
||||
const u8 *input;
|
||||
int remaining;
|
||||
u64 code, low, range;
|
||||
|
||||
// Read in bytes as needed
|
||||
CAT_INLINE void Normalize();
|
||||
|
||||
// Grab symbol low frequency and range from the table
|
||||
CAT_INLINE u8 GetTableSymbol(const TextStatsCollector::TableFormat *stats, u32 &last, u16 freq, u16 &symbol_low, u16 &symbol_range);
|
||||
|
||||
public:
|
||||
// Initializing constructor
|
||||
RangeDecoder(const void *message, int bytes);
|
||||
|
||||
int Remaining() { return remaining; }
|
||||
|
||||
public:
|
||||
// Decode the given text with the given statistics
|
||||
int Text(char *msg, int buffer_size, const TextStatsCollector::TableFormat *stats);
|
||||
|
||||
// Decode a biased bit given the frequency it is 0
|
||||
// frequency = average times out of 2^32 trials the bit will be 0
|
||||
u32 BiasedBit(u32 frequency);
|
||||
|
||||
// Decode a field that takes on [0, total) values with equal likelihood
|
||||
u32 Range(u32 total);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_RANGE_CODER_HPP
|
||||
45
DependentExtensions/cat/crypt/SecureCompare.hpp
Normal file
45
DependentExtensions/cat/crypt/SecureCompare.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SECURE_COMPARE_HPP
|
||||
#define CAT_SECURE_COMPARE_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Binary comparison function that is resistant to timing attack
|
||||
// Note that memcmp() and strcmp() are both vulnerable
|
||||
// Returns true if they are equal
|
||||
bool SecureEqual(const void *A, const void *B, int bytes);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // SECURE_COMPARE_HPP
|
||||
70
DependentExtensions/cat/crypt/cookie/CookieJar.hpp
Normal file
70
DependentExtensions/cat/crypt/cookie/CookieJar.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_COOKIE_JAR_HPP
|
||||
#define CAT_COOKIE_JAR_HPP
|
||||
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CookieJar
|
||||
{
|
||||
static const int EXPIRE_TIME = 4000; // ms
|
||||
static const int BIN_COUNT = 16; // power of 2
|
||||
static const int BIN_TIME = EXPIRE_TIME / BIN_COUNT;
|
||||
static const int BIN_MASK = BIN_COUNT - 1;
|
||||
|
||||
u32 key[16];
|
||||
|
||||
u32 Salsa6(u32 *x);
|
||||
|
||||
u32 Hash(u32 ip, u16 port, u32 epoch);
|
||||
u32 Hash(const void *address_info, int bytes, u32 epoch);
|
||||
|
||||
u32 GetEpoch();
|
||||
u32 ReconstructEpoch(u32 cookie);
|
||||
|
||||
public:
|
||||
// Initialize to a random 512-bit key on startup
|
||||
void Initialize(FortunaOutput *csprng);
|
||||
|
||||
// Thread-safe and lock-free
|
||||
u32 Generate(u32 ip, u16 port);
|
||||
u32 Generate(const void *address_info, int bytes); // bytes <= 48
|
||||
|
||||
// Thread-safe and lock-free
|
||||
bool Verify(u32 ip, u16 port, u32 cookie);
|
||||
bool Verify(const void *address_info, int bytes, u32 cookie); // bytes <= 48
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_COOKIE_JAR_HPP
|
||||
87
DependentExtensions/cat/crypt/hash/HMAC_MD5.hpp
Normal file
87
DependentExtensions/cat/crypt/hash/HMAC_MD5.hpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
HMAC-MD5 is still secure despite the ease of producing collisions in MD5.
|
||||
See Mihir Bellare paper "New Proofs for NMAC and HMAC: Security without Collision-Resistance" (June 2006)
|
||||
|
||||
Using HMAC construction:
|
||||
HMAC(x) = h(k || p1 || h(k || p2 || x))
|
||||
h() = MD5 hash
|
||||
p1,p2 = distinct padding to bring k up to the block size
|
||||
p1 = 0x36 repeated, p2 = 0x5c repeated
|
||||
|
||||
Diverges from usual implementation by using little-endian rather than big-endian input
|
||||
*/
|
||||
|
||||
#ifndef HMAC_MD5_HPP
|
||||
#define HMAC_MD5_HPP
|
||||
|
||||
#include <cat/crypt/hash/ICryptHash.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CAT_EXPORT HMAC_MD5 : public ICryptHash
|
||||
{
|
||||
protected:
|
||||
static const int DIGEST_BYTES = 16;
|
||||
static const int WORK_BYTES = 64; // bytes in one block
|
||||
static const int WORK_WORDS = WORK_BYTES / sizeof(u32);
|
||||
|
||||
u32 CachedInitialState[4]; // Cached state for H(K||inner padding)
|
||||
u32 CachedFinalState[4]; // Cached state for H(K||outer padding)
|
||||
|
||||
u64 byte_counter;
|
||||
u32 State[4];
|
||||
u8 Work[WORK_BYTES];
|
||||
int used_bytes;
|
||||
|
||||
void HashComputation(const void *message, int blocks, u32 *NextState);
|
||||
|
||||
// Unsupported modes
|
||||
bool BeginKey(int /*bits*/) { return false; }
|
||||
bool BeginKDF() { return false; }
|
||||
bool BeginPRNG() { return false; }
|
||||
|
||||
public:
|
||||
~HMAC_MD5();
|
||||
bool SetKey(ICryptHash *parent);
|
||||
void RekeyFromMD5(HMAC_MD5 *parent);
|
||||
bool BeginMAC();
|
||||
void Crunch(const void *message, int bytes);
|
||||
void End();
|
||||
|
||||
// TODO: Strengthening is not supported right now
|
||||
void Generate(void *out, int bytes, int strengthening_rounds = 0);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // HMAC_MD5_HPP
|
||||
79
DependentExtensions/cat/crypt/hash/ICryptHash.hpp
Normal file
79
DependentExtensions/cat/crypt/hash/ICryptHash.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// 06/15/09 began
|
||||
|
||||
#ifndef CAT_I_CRYPT_HASH_HPP
|
||||
#define CAT_I_CRYPT_HASH_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <cstring>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Cryptographic hash functions of any size will derive from ICryptoHash and implement its public methods
|
||||
class CAT_EXPORT ICryptHash
|
||||
{
|
||||
protected:
|
||||
int digest_bytes;
|
||||
|
||||
public:
|
||||
virtual ~ICryptHash() {}
|
||||
|
||||
// Returns the number of bytes in a message digest produced by this hash
|
||||
CAT_INLINE int GetDigestByteCount() { return digest_bytes; }
|
||||
|
||||
CAT_INLINE void CrunchString(const char *s) { Crunch(s, (int)std::strlen(s) + 1); }
|
||||
|
||||
public:
|
||||
// Begin a new key
|
||||
virtual bool BeginKey(int bits) = 0;
|
||||
|
||||
// Start from an existing key
|
||||
virtual bool SetKey(ICryptHash *parent) = 0;
|
||||
|
||||
// Begin hash function in MAC, KDF, or PRNG mode
|
||||
virtual bool BeginMAC() = 0;
|
||||
virtual bool BeginKDF() = 0;
|
||||
virtual bool BeginPRNG() = 0;
|
||||
|
||||
// Crunch some message bytes
|
||||
virtual void Crunch(const void *message, int bytes) = 0;
|
||||
|
||||
// Finalize the hash and prepare to generate output
|
||||
virtual void End() = 0;
|
||||
|
||||
// Extended hash output mode
|
||||
virtual void Generate(void *out, int bytes, int strengthening_rounds = 0) = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_I_CRYPT_HASH_HPP
|
||||
108
DependentExtensions/cat/crypt/hash/Skein.hpp
Normal file
108
DependentExtensions/cat/crypt/hash/Skein.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Bruce Schneier's SHA-3 candidate Skein hash function
|
||||
http://www.skein-hash.info/
|
||||
*/
|
||||
|
||||
#ifndef CAT_SKEIN_HPP
|
||||
#define CAT_SKEIN_HPP
|
||||
|
||||
#include <cat/crypt/hash/ICryptHash.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Base class for various versions of Skein
|
||||
class CAT_EXPORT Skein : public ICryptHash
|
||||
{
|
||||
protected:
|
||||
// Tweak word 1 bit field starting positions
|
||||
static const int T1_POS_TREE_LVL = 112-64; // bits 112..118 : level in hash tree
|
||||
static const int T1_POS_BIT_PAD = 119-64; // bit 119 : partial final input byte
|
||||
static const int T1_POS_BLK_TYPE = 120-64; // bits 120..125 : type field
|
||||
static const int T1_POS_FIRST = 126-64; // bits 126 : first block flag
|
||||
static const int T1_POS_FINAL = 127-64; // bit 127 : final block flag
|
||||
|
||||
// Tweak word 1 bit field masks
|
||||
static const u64 T1_MASK_FIRST = (u64)1 << T1_POS_FIRST;
|
||||
static const u64 T1_MASK_FINAL = (u64)1 << T1_POS_FINAL;
|
||||
static const u64 T1_MASK_BIT_PAD = (u64)1 << T1_POS_BIT_PAD;
|
||||
static const u64 T1_MASK_TREE_LVL = (u64)0x7F << T1_POS_TREE_LVL;
|
||||
static const u64 T1_MASK_BLK_TYPE = (u64)63 << T1_POS_BLK_TYPE;
|
||||
|
||||
static const int BLK_TYPE_KEY = 0; // key, for MAC and KDF
|
||||
static const int BLK_TYPE_CFG = 4; // configuration block
|
||||
static const int BLK_TYPE_PERS = 8; // personalization string
|
||||
static const int BLK_TYPE_PK = 12; // public key (for digital signature hashing)
|
||||
static const int BLK_TYPE_KDF = 16; // key identifier for KDF
|
||||
static const int BLK_TYPE_NONCE = 20; // nonce for PRNG
|
||||
static const int BLK_TYPE_MSG = 48; // message processing
|
||||
static const int BLK_TYPE_OUT = 63; // output stage
|
||||
|
||||
static const u32 ID_STRING_LE = 0x33414853;
|
||||
static const u32 SKEIN_VERSION = 1;
|
||||
static const u64 SCHEMA_VER = ((u64)SKEIN_VERSION << 32) | ID_STRING_LE;
|
||||
|
||||
static const int MAX_BITS = 512;
|
||||
static const int MAX_WORDS = MAX_BITS / 64;
|
||||
static const int MAX_BYTES = MAX_BITS / 8;
|
||||
|
||||
u64 Tweak[2];
|
||||
u64 State[MAX_WORDS];
|
||||
u8 Work[MAX_BYTES];
|
||||
int used_bytes, digest_words;
|
||||
u64 output_block_counter;
|
||||
bool output_prng_mode;
|
||||
|
||||
typedef void (Skein::*HashComputation)(const void *message, int blocks, u32 byte_count, u64 *NextState);
|
||||
|
||||
void HashComputation256(const void *message, int blocks, u32 byte_count, u64 *NextState);
|
||||
void HashComputation512(const void *message, int blocks, u32 byte_count, u64 *NextState);
|
||||
|
||||
HashComputation hash_func;
|
||||
|
||||
void GenerateInitialState(int bits);
|
||||
|
||||
public:
|
||||
~Skein();
|
||||
bool BeginKey(int bits);
|
||||
bool SetKey(ICryptHash *parent);
|
||||
bool BeginMAC();
|
||||
bool BeginKDF();
|
||||
bool BeginPRNG();
|
||||
void Crunch(const void *message, int bytes);
|
||||
void End();
|
||||
void Generate(void *out, int bytes, int strengthening_rounds = 0);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SKEIN_HPP
|
||||
193
DependentExtensions/cat/crypt/pass/Passwords.hpp
Normal file
193
DependentExtensions/cat/crypt/pass/Passwords.hpp
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_PASSWORDS_HPP
|
||||
#define CAT_PASSWORDS_HPP
|
||||
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Why are passwords needed?
|
||||
|
||||
Passwords allow the client identity to be proved to the server. Usually
|
||||
the server identity is already proven by a secure connection, but the
|
||||
client identity is unproven until a password is provided.
|
||||
|
||||
This could be done using signatures with two-way authentication in the
|
||||
secure connection establishment, however this is very slow and roughly
|
||||
doubles the work a server has to do to accept a connection.
|
||||
|
||||
Passwords seem simple to implement at first but then you start imagining all
|
||||
the "what ifs":
|
||||
|
||||
What if the password database is stolen?
|
||||
|
||||
The user passwords had better not be stored in plaintext!
|
||||
So they must be hashed.
|
||||
|
||||
What if two users have the same password?
|
||||
|
||||
They would look the same hashed, so hash in the name with the password.
|
||||
|
||||
What if name:password for two users is "me : pass" and "m : epass" ?
|
||||
|
||||
They would look the same hashed, so insert a separator between the two
|
||||
before hashing, as in "me\r\npass" instead of just hashing "mepass".
|
||||
|
||||
What if someone tries to crack the passwords?
|
||||
|
||||
The password hash should be strengthened to make it harder to crack,
|
||||
by applying the hash function repeatedly. This does reduce the number of
|
||||
bits of entropy due to non-ideal hash function collisions, but this small
|
||||
effect is offset by the added difficulty to crack the password.
|
||||
|
||||
What if the user has a common name like "dave"?
|
||||
|
||||
The password hash should be salted to avoid falling to rainbow tables.
|
||||
|
||||
What if the attacker tries to use the stolen password hash to log into the server?
|
||||
|
||||
The client provides a hash pre-image during login, so the attacker would need
|
||||
to reverse the hash to do this, which is harder than cracking the password.
|
||||
|
||||
What if an attacker has a way to actively or passively listen to login attempts?
|
||||
|
||||
Then they would be able to steal the hash pre-image which would offer some
|
||||
amount of text password protection but would allow the attacker to log in
|
||||
as the user without knowing the password.
|
||||
|
||||
Rainbow tables can be used to crack the pre-image to determine the password.
|
||||
|
||||
If the connection is secure then the client has verified the server identity
|
||||
and these attacks are only possible through software bugs in the server.
|
||||
|
||||
|
||||
Protocol Description:
|
||||
|
||||
H: 256-bit hash function Skein-256
|
||||
c: Client
|
||||
s: Server
|
||||
X: Strengthening factor
|
||||
|
||||
|
||||
Protocol 1: Creating a User Account
|
||||
|
||||
c: Choose a name N
|
||||
c: Choose a password P
|
||||
c: Calculate I = H("N\r\nP") strengthened X times
|
||||
|
||||
c2s CREATE_ACCOUNT || N || I (32 by)
|
||||
|
||||
s: Verify account is not taken, then creates an account in the database
|
||||
s: Generate a 32-bit random salt S
|
||||
s: Calculate J = H(S || I)
|
||||
s: Store N, J and S in the account
|
||||
|
||||
s2c ACCOUNT_CREATE_SUCCESS
|
||||
|
||||
|
||||
Protocol 2: Logging into a User Account
|
||||
|
||||
c: Choose a name N
|
||||
c: Choose a password P
|
||||
c: Calculate I = H("N\r\nP") strengthened X times
|
||||
|
||||
c2s LOGIN_REQUEST || N || I (32 by)
|
||||
|
||||
s: Verify user name exists in account database
|
||||
s: Retrieve J, S from the account database
|
||||
s: Calculate J' = H(S || I)
|
||||
s: Verify J = J'
|
||||
|
||||
s2c LOGIN_SUCCESS
|
||||
|
||||
|
||||
What if the user creates an account through a website?
|
||||
|
||||
The server-side script on the website should execute a program that runs
|
||||
Protocol 1 to create the user account.
|
||||
|
||||
Why use this sort of password authentication + Tunnel instead of SRP?
|
||||
|
||||
Performance. The Tunnel key agreement takes much less CPU time than SRP
|
||||
and authenticates the server, which allows this protocol to be run without
|
||||
any disadvantages.
|
||||
*/
|
||||
|
||||
|
||||
class PasswordBase
|
||||
{
|
||||
public:
|
||||
static const int HASH_BITS = 256;
|
||||
static const int HASH_BYTES = HASH_BITS / 8;
|
||||
static const int STRENGTHENING_FACTOR = 1000;
|
||||
};
|
||||
|
||||
|
||||
class PasswordCreator : public PasswordBase
|
||||
{
|
||||
public:
|
||||
// Hash a password for transmission to the server during account creation or login
|
||||
// NOTE: You should make the name all lowercase before passing it in
|
||||
// Returns false on failure
|
||||
bool HashPassword(const void *in_name, int name_bytes,
|
||||
const void *in_password, int password_bytes,
|
||||
void *out_hash /* 32 bytes */);
|
||||
|
||||
// This version accepts non-unicode C strings with nul-terminators
|
||||
// It converts the name to lowercase internally
|
||||
bool HashPasswordString(const char *in_name,
|
||||
const char *in_password,
|
||||
void *out_hash /* 32 bytes */);
|
||||
};
|
||||
|
||||
class PasswordVerifier : public PasswordBase
|
||||
{
|
||||
public:
|
||||
// Salt a hash for storage in the account database during account creation
|
||||
// Generates a 32-bit salt and a 256-bit hash for storage
|
||||
// Returns false on failure
|
||||
bool SaltHash(IRandom *prng,
|
||||
const void *in_hash /* 32 bytes */,
|
||||
void *out_salted_hash /* 32 bytes */,
|
||||
u32 *out_salt /* 4 bytes */);
|
||||
|
||||
// Given the stored salted hash and salt, verify the client's password hash during login
|
||||
// Returns false if password is incorrect
|
||||
bool VerifyHash(const void *in_hash /* 32 bytes */,
|
||||
const void *in_salted_hash /* 32 bytes */,
|
||||
u32 in_salt /* 4 bytes */);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_PASSWORDS_HPP
|
||||
222
DependentExtensions/cat/crypt/rand/Fortuna.hpp
Normal file
222
DependentExtensions/cat/crypt/rand/Fortuna.hpp
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on Fortuna algorithm from "Practical Cryptography" section 10.3
|
||||
Published 2003 by Niels Ferguson and Bruce Schneier
|
||||
|
||||
Fortuna supplements the operating system (OS) pseudo-random number generator (PRNG)
|
||||
by incorporating additional entropy into the seeds that the OS provides.
|
||||
|
||||
Modified for use with Skein in PRNG mode, sharing the strengths of both algorithms.
|
||||
|
||||
My implementation of Fortuna (call it Cat For Tuna) has the following components:
|
||||
|
||||
+ Entropy Pools
|
||||
+ 32 pools numbered 0..31
|
||||
+ Implemented as 32 instances of the 256-bit Skein hash
|
||||
+ Entropy hashed into pools in a round-robin fashion
|
||||
+ Scheme allows for recovery against attacker with knowledge of some sources
|
||||
|
||||
+ Entropy Sources
|
||||
+ Uses best OS random number generator
|
||||
+ And a variable number of OS-dependent entropy sources
|
||||
+ Mainly cycle counts and other timing information
|
||||
|
||||
+ Output Generator
|
||||
+ Implemented as a 512-bit Skein hash of some combination of the entropy pools
|
||||
+ The output is produced by the PRNG mode of Skein keyed by the pools
|
||||
+ Hashing all of these pools together and keying the output is called "seeding"
|
||||
+ Reseeded after sufficient entropy has been collected in pool 0
|
||||
+ Pool 0 is always used for reseeding
|
||||
+ Reseed X uses pools numbered by the 1-bits in X (except MSB)
|
||||
+ Previous seed keys the next seed
|
||||
+ Diverges from normal Fortuna due to use of Skein instead of a block cipher
|
||||
+ Reseeds only once every ~512 seconds
|
||||
+ Does not have a limit of 2^16 output blocks
|
||||
+ Skein-PRNG is guaranteed sufficient security properties anyway
|
||||
|
||||
The Fortuna algorithm is broken up into two objects for efficient thread-safety:
|
||||
|
||||
+ FortunaFactory
|
||||
+ Must be initialized on startup and shut down on shutdown
|
||||
+ Spawns a thread to periodically collect additional entropy
|
||||
+ Can create FortunaOutput objects
|
||||
|
||||
+ FortunaOutput
|
||||
+ Reseeds based on master seed in the FortunaFactory
|
||||
+ Reseeds after master seed is updated
|
||||
+ Provides a unique random stream for each thread that uses Fortuna
|
||||
*/
|
||||
|
||||
#ifndef CAT_FOR_TUNA_HPP
|
||||
#define CAT_FOR_TUNA_HPP
|
||||
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/Singleton.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
|
||||
|
||||
// Defining CAT_NO_ENTROPY_THREAD will remove dependencies on pthreads and not
|
||||
// run a thread to collect more entropy. This is recommended for low-power targets
|
||||
// and other systems where no thread library is available
|
||||
#if defined(CAT_OS_WINDOWS_CE)
|
||||
# define CAT_NO_ENTROPY_THREAD
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
# include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
# include <cat/threads/Thread.hpp>
|
||||
# include <cat/threads/WaitableFlag.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
namespace cat {
|
||||
|
||||
class FortunaOutput;
|
||||
class FortunaFactory;
|
||||
|
||||
|
||||
// Factory for constructing FortunaOutput objects
|
||||
class FortunaFactory : public Singleton<FortunaFactory>
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
, public Thread
|
||||
#endif
|
||||
{
|
||||
CAT_SINGLETON(FortunaFactory)
|
||||
{
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
friend class FortunaOutput;
|
||||
|
||||
#if defined(CAT_OS_WINDOWS) && !defined(CAT_OS_WINDOWS_CE)
|
||||
|
||||
typedef LONG (WINAPI *PtNtQuerySystemInformation)(
|
||||
int SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
HANDLE CurrentProcess;
|
||||
HMODULE NTDLL;
|
||||
PtNtQuerySystemInformation NtQuerySystemInformation;
|
||||
HCRYPTPROV hCryptProv;
|
||||
|
||||
#elif defined(CAT_OS_WINDOWS_CE)
|
||||
|
||||
HCRYPTPROV hCryptProv;
|
||||
|
||||
#elif defined(CAT_OS_LINUX)
|
||||
|
||||
int urandom_fd;
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
static const int ENTROPY_THREAD_KILL_TIMEOUT = 10000; // 10 seconds
|
||||
|
||||
WaitableFlag _kill_flag;
|
||||
|
||||
bool ThreadFunction(void *param);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
static const int ENTROPY_POOLS = 32; // Setting this higher would break something
|
||||
static const int POOL_BITS = 512;
|
||||
static const int POOL_BYTES = POOL_BITS / 8;
|
||||
static const int POOL_QWORDS = POOL_BYTES / sizeof(u64);
|
||||
|
||||
static u32 MasterSeedRevision; // Should not roll over for 13 years if incremented once every RESEED_MIN_TIME
|
||||
static Skein MasterSeed;
|
||||
|
||||
bool _initialized;
|
||||
u32 reseed_counter;
|
||||
Skein Pool[ENTROPY_POOLS];
|
||||
|
||||
bool Reseed();
|
||||
void GetNextKey(FortunaOutput *output);
|
||||
bool InitializeEntropySources();
|
||||
void PollInvariantSources(int pool);
|
||||
void PollSlowEntropySources(int pool);
|
||||
void PollFastEntropySources(int pool);
|
||||
void ShutdownEntropySources();
|
||||
|
||||
public:
|
||||
// Start the entropy generator
|
||||
bool Initialize();
|
||||
|
||||
// Stop the entropy generator
|
||||
void Shutdown();
|
||||
|
||||
// Create a new Fortuna object
|
||||
static FortunaOutput *Create();
|
||||
};
|
||||
|
||||
|
||||
// LoopThread-safe output object for Fortuna
|
||||
class FortunaOutput : public IRandom
|
||||
{
|
||||
friend class FortunaFactory;
|
||||
|
||||
static const int OUTPUT_CACHE_BYTES = FortunaFactory::POOL_BYTES * 8; // Arbitrary
|
||||
|
||||
u32 thread_id, SeedRevision;
|
||||
Skein OutputHash;
|
||||
u8 CachedRandomBytes[OUTPUT_CACHE_BYTES];
|
||||
int used_bytes;
|
||||
|
||||
void Reseed();
|
||||
|
||||
FortunaOutput();
|
||||
FortunaOutput(FortunaOutput&) {}
|
||||
FortunaOutput &operator=(FortunaOutput &) { return *this; }
|
||||
|
||||
public:
|
||||
~FortunaOutput();
|
||||
|
||||
// Generate a 32-bit random number
|
||||
u32 Generate();
|
||||
|
||||
// Generate a variable number of random bytes
|
||||
void Generate(void *buffer, int bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_FOR_TUNA_HPP
|
||||
145
DependentExtensions/cat/crypt/symmetric/ChaCha.hpp
Normal file
145
DependentExtensions/cat/crypt/symmetric/ChaCha.hpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
The ChaCha cipher is a symmetric stream cipher based on Salsa20.
|
||||
http://cr.yp.to/chacha.html
|
||||
*/
|
||||
|
||||
#ifndef CAT_CHACHA_HPP
|
||||
#define CAT_CHACHA_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
/*
|
||||
To initialize the ChaCha cipher, you must specify a 256-bit key.
|
||||
|
||||
Code example:
|
||||
|
||||
ChaChaKey cck;
|
||||
char key[32]; // fill key here
|
||||
|
||||
cck.Key(key, sizeof(key));
|
||||
|
||||
Before each encryption or decryption with the ChaCha cipher,
|
||||
a 64-bit Initialization Vector (IV) must be specified. Every
|
||||
time a message is encrypted, the IV must be incremented by 1.
|
||||
The IV is then sent along with the encrypted message.
|
||||
|
||||
Encryption code example:
|
||||
|
||||
char message[19], ciphertext[19]; // message filled here
|
||||
u64 iv = 125125;
|
||||
u64 message_iv = iv;
|
||||
iv = iv + 1;
|
||||
|
||||
ChaChaOutput cco(cck, message_iv);
|
||||
cco.Crypt(message, ciphertext, sizeof(ciphertext));
|
||||
|
||||
Decryption code example:
|
||||
|
||||
char ciphertext[19], decrypted[19]; // ciphertext filled here
|
||||
|
||||
ChaChaOutput cco(cck, message_iv);
|
||||
cco.Crypt(ciphertext, decrypted, sizeof(decrypted));
|
||||
|
||||
Sending all 8 bytes of the IV in every packet is not necessary.
|
||||
Instead, only a few of the low bits of the IV need to be sent,
|
||||
if the IV is incremented by 1 each time.
|
||||
|
||||
How many? It depends on how many messages can get lost.
|
||||
If < 32768 messages can get lost in a row, then CAT_IV_BITS = 16 (default)
|
||||
|
||||
I have provided a function to handle rollover/rollunder of the IV,
|
||||
which also works if the same IV is sent twice for some reason.
|
||||
It needs to know how many of the low bits are sent across, so be sure
|
||||
to change CAT_IV_BITS in this header if you send more or less than 16.
|
||||
|
||||
Code example:
|
||||
|
||||
u64 last_accepted_iv;
|
||||
u32 new_iv_low_bits;
|
||||
|
||||
u64 new_iv = ChaCha::ReconstructIV(last_accepted_iv, new_iv_low_bits);
|
||||
|
||||
-------------------------READ THIS BEFORE USING--------------------------
|
||||
|
||||
Never use the same IV twice.
|
||||
Otherwise: An attacker can recover the plaintext without the key.
|
||||
|
||||
Never use the same key twice.
|
||||
Otherwise: An attacker can recover the plaintext without the key.
|
||||
|
||||
If you have two hosts talking to eachother securely with ChaCha encryption,
|
||||
then be sure that each host is encrypting with a DIFFERENT key.
|
||||
Otherwise: An attacker can recover the plaintext without the key.
|
||||
|
||||
Remember that an attacker can impersonate the remote computer, so be
|
||||
sure not to accept the new IV until the message authentication code has
|
||||
been verified if your protocol uses a message authentication code (MAC).
|
||||
Otherwise: An attacker could desynchronize the IVs.
|
||||
*/
|
||||
|
||||
|
||||
//// ChaChaKey
|
||||
|
||||
class CAT_EXPORT ChaChaKey
|
||||
{
|
||||
friend class ChaChaOutput;
|
||||
u32 state[16];
|
||||
|
||||
public:
|
||||
~ChaChaKey();
|
||||
|
||||
// Key up to 384 bits
|
||||
void Set(const void *key, int bytes);
|
||||
};
|
||||
|
||||
|
||||
//// ChaChaOutput
|
||||
|
||||
class CAT_EXPORT ChaChaOutput
|
||||
{
|
||||
u32 state[16];
|
||||
|
||||
void GenerateKeyStream(u32 *out);
|
||||
|
||||
public:
|
||||
ChaChaOutput(const ChaChaKey &key, u64 iv);
|
||||
~ChaChaOutput();
|
||||
|
||||
// Message with any number of bytes
|
||||
void Crypt(const void *in, void *out, int bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_CHACHA_HPP
|
||||
148
DependentExtensions/cat/crypt/tunnel/AuthenticatedEncryption.hpp
Normal file
148
DependentExtensions/cat/crypt/tunnel/AuthenticatedEncryption.hpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_AUTHENTICATED_ENCRYPTION_HPP
|
||||
#define CAT_AUTHENTICATED_ENCRYPTION_HPP
|
||||
|
||||
#include <cat/crypt/symmetric/ChaCha.hpp>
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/crypt/hash/HMAC_MD5.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Tunnel Authenticated Encryption "Calico" protocol:
|
||||
|
||||
Run after the Key Agreement protocol completes.
|
||||
Uses a 1024-bit anti-replay sliding window, suitable for Internet file transfer over UDP.
|
||||
|
||||
Cipher: 12-round ChaCha with 256-bit or 384-bit keys
|
||||
KDF: Key derivation function (Skein)
|
||||
MAC: 64-bit truncated HMAC-MD5
|
||||
IV: Initialization vector incrementing by 1 each time
|
||||
|
||||
c2sMKey = KDF(k) { "upstream-MAC" }
|
||||
s2cMKey = KDF(k) { "downstream-MAC" }
|
||||
c2sEKey = KDF(k) { "upstream-ENC" }
|
||||
s2cEKey = KDF(k) { "downstream-ENC" }
|
||||
c2sIV = KDF(k) { "upstream-IV" }
|
||||
s2cIV = KDF(k) { "downstream-IV" }
|
||||
|
||||
To transmit a message, the client calculates a MAC with the c2sMKey of the IV concatenated with
|
||||
the plaintext message and then appends the 8-byte MAC and low 3 bytes of the IV to the message,
|
||||
which is encrypted using the c2sEKey and the IV.
|
||||
|
||||
c2s Encrypt(c2sEKey) { message || MAC(c2sMKey) { full-iv-us||message } } || Obfuscated { trunc-iv-us }
|
||||
|
||||
encrypted { MESSAGE(X) MAC(8by) } IV(3by) = 11 bytes overhead at end of packet
|
||||
|
||||
To transmit a message, the server calculates a MAC with the s2cMKey of the IV concatenated with
|
||||
the plaintext message and then appends the 8-byte MAC and low 3 bytes of the IV to the message,
|
||||
which is encrypted using the s2cEKey and the IV.
|
||||
|
||||
s2c Encrypt(s2cEKey) { message || MAC(s2cMKey) { full-iv-ds||message } } || Obfuscated { trunc-iv-ds }
|
||||
|
||||
encrypted { MESSAGE(X) MAC(8by) } IV(3by) = 11 bytes overhead at end of packet
|
||||
|
||||
The full 64-bit IVs are initialized to c2sIV and s2cIV, and the first one sent is IV+1.
|
||||
*/
|
||||
|
||||
|
||||
class KeyAgreementResponder;
|
||||
class KeyAgreementInitiator;
|
||||
|
||||
|
||||
// This class is NOT THREAD-SAFE.
|
||||
class CAT_EXPORT AuthenticatedEncryption
|
||||
{
|
||||
friend class KeyAgreementResponder;
|
||||
friend class KeyAgreementInitiator;
|
||||
|
||||
bool _is_initiator, _accept_out_of_order;
|
||||
Skein key_hash;
|
||||
|
||||
HMAC_MD5 local_mac_key, remote_mac_key;
|
||||
ChaChaKey local_cipher_key, remote_cipher_key;
|
||||
u64 local_iv, remote_iv;
|
||||
|
||||
// 1024-bit anti-replay sliding window
|
||||
static const int BITMAP_BITS = 1024;
|
||||
static const int BITMAP_WORDS = BITMAP_BITS / 64;
|
||||
u64 iv_bitmap[BITMAP_WORDS];
|
||||
|
||||
public:
|
||||
CAT_INLINE AuthenticatedEncryption() {}
|
||||
CAT_INLINE ~AuthenticatedEncryption() {}
|
||||
|
||||
// Tunnel overhead bytes
|
||||
static const int MAC_BYTES = 8;
|
||||
static const int IV_BYTES = 3;
|
||||
static const u32 OVERHEAD_BYTES = IV_BYTES + MAC_BYTES;
|
||||
|
||||
// IV constants
|
||||
static const int IV_BITS = IV_BYTES * 8;
|
||||
static const u32 IV_MSB = (1 << IV_BITS);
|
||||
static const u32 IV_MASK = (IV_MSB - 1);
|
||||
static const u32 IV_FUZZ = 0xCA7DCA7D;
|
||||
|
||||
protected:
|
||||
bool SetKey(int KeyBytes, Skein *key, bool is_initiator, const char *key_name);
|
||||
|
||||
bool IsValidIV(u64 iv);
|
||||
void AcceptIV(u64 iv);
|
||||
|
||||
public:
|
||||
// Generate a proof that the local host has the key
|
||||
bool GenerateProof(u8 *local_proof, int proof_bytes);
|
||||
|
||||
// Validate a proof that the remote host has the key
|
||||
bool ValidateProof(const u8 *remote_proof, int proof_bytes);
|
||||
|
||||
public:
|
||||
void AllowOutOfOrder(bool allowed = true) { _accept_out_of_order = allowed; }
|
||||
|
||||
public:
|
||||
// Overhead is OVERHEAD_BYTES bytes at the end of the packet
|
||||
// Returns false if the message is invalid. Invalid messages should just be ignored as if they were never received
|
||||
// buf_bytes: Number of bytes in the buffer, including the overhead
|
||||
// If Decrypt() returns true, buf_bytes is set to the size of the decrypted message
|
||||
bool Decrypt(u8 *buffer, u32 &buf_bytes);
|
||||
|
||||
// Overhead is OVERHEAD_BYTES bytes at the end of the packet
|
||||
// buffer_bytes: Number of bytes in the buffer; will return false if buffer size too small
|
||||
// msg_bytes: Number of bytes in the message, excluding the overhead
|
||||
// If Encrypt() returns true, msg_bytes is set to the size of the encrypted message
|
||||
bool Encrypt(u8 *buffer, u32 buffer_bytes, u32 &msg_bytes);
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_AUTHENTICATED_ENCRYPTION_HPP
|
||||
307
DependentExtensions/cat/crypt/tunnel/EasyHandshake.hpp
Normal file
307
DependentExtensions/cat/crypt/tunnel/EasyHandshake.hpp
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_EASY_HANDSHAKE_HPP
|
||||
#define CAT_EASY_HANDSHAKE_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreementInitiator.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreementResponder.hpp>
|
||||
#include <cat/crypt/cookie/CookieJar.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
The EasyHandshake classes implement a simplified version of my Tunnel protocol.
|
||||
|
||||
This only works for single-threaded servers and only produces a single authenticated encryption
|
||||
object for each handshake. Explanations on how to use the library with a multi-threaded
|
||||
server, and how to use one handshake to secure several TCP streams, are documented in the
|
||||
comments of these classes.
|
||||
|
||||
|
||||
Over the network, the handshake will look like this:
|
||||
|
||||
client --> server : CHALLENGE (64 random-looking bytes)
|
||||
|
||||
server --> client : ANSWER (128 random-looking bytes)
|
||||
|
||||
client --> server : PROOF (32 random-looking bytes) + first encrypted packet can be appended here
|
||||
|
||||
|
||||
As far as coding goes, the function calls fit into the protocol like this:
|
||||
|
||||
server is offline:
|
||||
|
||||
During startup, both the client and server should initialize the library.
|
||||
This is necessary also just for generating keys:
|
||||
----------------------------------------------------------------
|
||||
#include <cat/AllTunnel.hpp>
|
||||
using namespace cat;
|
||||
|
||||
if (!EasyHandshake::Initialize())
|
||||
{
|
||||
printf("ERROR:Unable to initialize crypto subsystem\n");
|
||||
}
|
||||
----------------------------------------------------------------
|
||||
|
||||
Generate the server public and private key pairs:
|
||||
----------------------------------------------------------------
|
||||
u8 public_key[EasyHandshake::PUBLIC_KEY_BYTES];
|
||||
u8 private_key[EasyHandshake::PRIVATE_KEY_BYTES];
|
||||
|
||||
EasyHandshake temp;
|
||||
temp.GenerateServerKey(public_key, private_key);
|
||||
----------------------------------------------------------------
|
||||
|
||||
(keys are stored to disk for reading on start-up)
|
||||
|
||||
(public key is given to the client somehow)
|
||||
+ built into the client code
|
||||
+ provided by a trusted server
|
||||
|
||||
server comes online:
|
||||
|
||||
----------------------------------------------------------------
|
||||
ServerEasyHandshake server_handshake;
|
||||
|
||||
server_handshake.Initialize(public_key, private_key);
|
||||
----------------------------------------------------------------
|
||||
|
||||
client comes online:
|
||||
|
||||
----------------------------------------------------------------
|
||||
ClientEasyHandshake client_handshake;
|
||||
|
||||
client_handshake.Initialize(public_key);
|
||||
|
||||
u8 challenge[EasyHandshake::CHALLENGE_BYTES];
|
||||
|
||||
client_handshake.GenerateChallenge(challenge);
|
||||
----------------------------------------------------------------
|
||||
|
||||
client --> server : CHALLENGE (64 random-looking bytes)
|
||||
|
||||
----------------------------------------------------------------
|
||||
AuthenticatedEncryption server_e;
|
||||
|
||||
u8 answer[EasyHandshake::ANSWER_BYTES];
|
||||
|
||||
server_handshake.ProcessChallenge(challenge, answer, &server_e);
|
||||
----------------------------------------------------------------
|
||||
|
||||
server --> client : ANSWER (128 random-looking bytes)
|
||||
|
||||
----------------------------------------------------------------
|
||||
AuthenticatedEncryption client_e;
|
||||
|
||||
client_handshake.ProcessAnswer(answer, &client_e);
|
||||
|
||||
u8 proof[EasyHandshake::PROOF_BYTES];
|
||||
|
||||
client_e.GenerateProof(proof, EasyHandshake::PROOF_BYTES);
|
||||
----------------------------------------------------------------
|
||||
|
||||
Encryption example:
|
||||
----------------------------------------------------------------
|
||||
// Example message encryption of "Hello". Note that encryption
|
||||
// inflates the size of the message by OVERHEAD_BYTES.
|
||||
const int PLAINTEXT_BYTES = 5;
|
||||
const int BUFFER_BYTES = \
|
||||
PLAINTEXT_BYTES + AuthenticatedEncryption::OVERHEAD_BYTES;
|
||||
int msg_bytes = PLAINTEXT_BYTES;
|
||||
|
||||
// Note that it makes room for message inflation
|
||||
const u8 message[CIPHERTEXT_BYTES] = {
|
||||
'H', 'e', 'l', 'l', 'o'
|
||||
};
|
||||
|
||||
// Note the second parameter is the size of the buffer, and
|
||||
// the third parameter will be adjusted to the size of the
|
||||
// encrypted message:
|
||||
|
||||
if (client_e.Encrypt(message, BUFFER_BYTES, msg_bytes))
|
||||
{
|
||||
// msg_bytes is now adjusted to be the size of the ciphertext
|
||||
}
|
||||
----------------------------------------------------------------
|
||||
|
||||
client --> server : PROOF (32 random-looking bytes) + first encrypted packet can be appended here
|
||||
|
||||
----------------------------------------------------------------
|
||||
server_e.ValidateProof(proof, EasyHandshake::PROOF_BYTES);
|
||||
----------------------------------------------------------------
|
||||
|
||||
Decryption example:
|
||||
----------------------------------------------------------------
|
||||
int buf_bytes = msg_bytes;
|
||||
|
||||
// The second parameter is the number of bytes in the encrypted message
|
||||
if (server_e.Decrypt(message, buf_bytes))
|
||||
{
|
||||
// buf_bytes is now adjusted to be the size of the plaintext
|
||||
}
|
||||
----------------------------------------------------------------
|
||||
|
||||
During program termination, the client and server should clean up:
|
||||
----------------------------------------------------------------
|
||||
EasyHandshake::Shutdown();
|
||||
----------------------------------------------------------------
|
||||
|
||||
NOTES:
|
||||
|
||||
Once the authenticated encryption objects are created, if the messages received are always
|
||||
guaranteed to be in order, then the following flag can be set to make the object reject
|
||||
packets received out of order, which would indicate tampering:
|
||||
auth_enc.AllowOutOfOrder(false);
|
||||
By default the messages are assumed to arrive in any order up to 1024 messages out of order.
|
||||
|
||||
The server similarly can encrypt messages the same way the client does in the examples.
|
||||
|
||||
Encrypted messages are inflated by 11 random-looking bytes for a MAC and an IV.
|
||||
Modifications to the code can allow lower overhead if needed.
|
||||
|
||||
The EasyHandshake classes are *NOT* THREAD-SAFE.
|
||||
|
||||
The AuthenticatedEncryption class is *NOT* THREAD-SAFE. Simultaneously, only ONE thread
|
||||
can be encrypting messages. And only ONE thread can be decrypting messages. Encryption
|
||||
and decryption are separate and safe to perform simultaneously.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Common data needed for handshaking
|
||||
*/
|
||||
class CAT_EXPORT EasyHandshake
|
||||
{
|
||||
protected:
|
||||
// Normally these would be created per-thread.
|
||||
// To free memory associated with these objects just delete them.
|
||||
BigTwistedEdwards *tls_math;
|
||||
FortunaOutput *tls_csprng;
|
||||
|
||||
public:
|
||||
static const int BITS = 256;
|
||||
static const int BYTES = BITS / 8;
|
||||
static const int PUBLIC_KEY_BYTES = BYTES * 2;
|
||||
static const int PRIVATE_KEY_BYTES = BYTES;
|
||||
static const int CHALLENGE_BYTES = BYTES * 2; // Packet # 1 in handshake, sent to server
|
||||
static const int ANSWER_BYTES = BYTES * 4; // Packet # 2 in handshake, sent to client
|
||||
static const int PROOF_BYTES = BYTES; // Packet # 3 in handshake, sent to server
|
||||
static const int IDENTITY_BYTES = BYTES * 5; // [optional] Packet # 3 in handshake, sent to server, proves identity of client also
|
||||
|
||||
public:
|
||||
// Demonstrates how to allocate and free the math and prng objects
|
||||
EasyHandshake();
|
||||
~EasyHandshake();
|
||||
|
||||
public:
|
||||
static bool Initialize();
|
||||
static void Shutdown();
|
||||
|
||||
public:
|
||||
// Generate a server (public, private) key pair
|
||||
// Connecting clients will need to know the public key in order to connect
|
||||
bool GenerateServerKey(void *out_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */,
|
||||
void *out_private_key /* EasyHandshake::PRIVATE_KEY_BYTES */);
|
||||
|
||||
// Fills the given buffer with a variable number of random bytes
|
||||
// Returns false on failure
|
||||
bool GenerateRandomNumber(void *out_num, int bytes);
|
||||
};
|
||||
|
||||
/*
|
||||
Implements the simple case of a server that performs handshakes with clients
|
||||
from a single thread. Note that this implementation is not thread-safe.
|
||||
*/
|
||||
class CAT_EXPORT ServerEasyHandshake : public EasyHandshake
|
||||
{
|
||||
KeyAgreementResponder tun_server;
|
||||
|
||||
public:
|
||||
ServerEasyHandshake();
|
||||
~ServerEasyHandshake();
|
||||
|
||||
// Prepare a cookie jar for hungry consumers
|
||||
void FillCookieJar(CookieJar *jar);
|
||||
|
||||
// Provide the public and private key for the server, previously generated offline
|
||||
bool Initialize(const void *in_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */,
|
||||
const void *in_private_key /* EasyHandshake::PRIVATE_KEY_BYTES */);
|
||||
|
||||
// Process a client challenge and generate a server answer
|
||||
// Returns false if challenge was invalid
|
||||
bool ProcessChallenge(const void *in_challenge /* EasyHandshake::CHALLENGE_BYTES */,
|
||||
void *out_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
AuthenticatedEncryption *auth_enc);
|
||||
|
||||
// Validate a client proof of identity
|
||||
// Returns false if proof was invalid
|
||||
bool VerifyInitiatorIdentity(const void *in_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
const void *in_proof /* EasyHandshake::IDENTITY_BYTES */,
|
||||
void *out_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */);
|
||||
};
|
||||
|
||||
/*
|
||||
Implements the simple case of a client that performs handshakes with servers
|
||||
from a single thread. Note that this implementation is not thread-safe.
|
||||
*/
|
||||
class CAT_EXPORT ClientEasyHandshake : public EasyHandshake
|
||||
{
|
||||
KeyAgreementInitiator tun_client;
|
||||
|
||||
public:
|
||||
ClientEasyHandshake();
|
||||
~ClientEasyHandshake();
|
||||
|
||||
// Provide the public key for the server, acquired through some secure means
|
||||
bool Initialize(const void *in_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */);
|
||||
|
||||
// (optional) Provide the identity for the client
|
||||
bool SetIdentity(const void *in_public_key /* EasyHandshake::PUBLIC_KEY_BYTES */,
|
||||
const void *in_private_key /* EasyHandshake::PRIVATE_KEY_BYTES */);
|
||||
|
||||
// Generate a challenge for the server to answer
|
||||
bool GenerateChallenge(void *out_challenge /* EasyHandshake::CHALLENGE_BYTES */);
|
||||
|
||||
// Process a server answer to our challenge
|
||||
// Returns false if answer was invalid
|
||||
bool ProcessAnswer(const void *in_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
AuthenticatedEncryption *auth_enc);
|
||||
|
||||
// Process a server answer to our challenge and provide a proof of client identity
|
||||
// Returns false if answer was invalid
|
||||
bool ProcessAnswerWithIdentity(const void *in_answer /* EasyHandshake::ANSWER_BYTES */,
|
||||
void *out_identity /* EasyHandshake::IDENTITY_BYTES */,
|
||||
AuthenticatedEncryption *auth_enc);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_EASY_HANDSHAKE_HPP
|
||||
210
DependentExtensions/cat/crypt/tunnel/KeyAgreement.hpp
Normal file
210
DependentExtensions/cat/crypt/tunnel/KeyAgreement.hpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_AGREEMENT_HPP
|
||||
#define CAT_KEY_AGREEMENT_HPP
|
||||
|
||||
#include <cat/math/BigTwistedEdwards.hpp>
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Tunnel Key Agreement "Tabby" protocol:
|
||||
An unauthenticated Diffie-Hellman key agreement protocol with forward secrecy
|
||||
Immune to active attacks (man-in-the-middle) if server key is known ahead of time
|
||||
|
||||
Using Elliptic Curve Cryptography over finite field Fp, p = 2^n - c, c small
|
||||
Shape of curve: a' * x^2 + y^2 = 1 + d' * x^2 * y^2, a' = -1 (square in Fp)
|
||||
d' (non square in Fp) -> order of curve = q * cofactor h, order of generator point = q
|
||||
Curves satisfy MOV conditions and are not anomalous
|
||||
Point operations performed with Extended Twisted Edwards group laws
|
||||
See BigTwistedEdwards.hpp for more information
|
||||
|
||||
H: Skein-Key, either 256-bit or 512-bit based on security level
|
||||
MAC: Skein-MAC, keyed from output of H()
|
||||
|
||||
Here the protocol initiator is the (c)lient, and the responder is the (s)erver:
|
||||
|
||||
s: long-term private key 1 < b < q, long-term public key B = b * G
|
||||
|
||||
256-bit security: B = 64 bytes for public key, b = 32 bytes for private key
|
||||
384-bit security: B = 96 bytes for public key, b = 48 bytes for private key
|
||||
512-bit security: B = 128 bytes for public key, b = 64 bytes for private key
|
||||
|
||||
c: Client already knows the server's public key B before Key Agreement
|
||||
c: ephemeral private key 1 < a < q, ephemeral public key A = a * G
|
||||
|
||||
Initiator Challenge: c2s A
|
||||
|
||||
256-bit security: A = 64 bytes
|
||||
384-bit security: A = 96 bytes
|
||||
512-bit security: A = 128 bytes
|
||||
|
||||
s: validate A, ignore invalid
|
||||
Invalid A(x,y) would be the additive identity x=0 or any point not on the curve
|
||||
|
||||
s: ephemeral private key 1 < y < q, ephemeral public key Y = y * G
|
||||
Ephemeral key is re-used for several connections before being regenerated
|
||||
|
||||
s: hA = h * A
|
||||
s: random n-bit number r
|
||||
s: d = H(A,B,Y,r)
|
||||
Repeat the previous two steps until d >= 1000
|
||||
|
||||
s: e = b + d*y (mod q)
|
||||
s: T = AffineX(e * hA)
|
||||
s: k = H(d,T)
|
||||
|
||||
Responder Answer: s2c Y || r || MAC(k) {"responder proof"}
|
||||
|
||||
256-bit security: Y(64by) r(32by) MAC(32by) = 128 bytes
|
||||
384-bit security: Y(96by) r(48by) MAC(48by) = 192 bytes
|
||||
512-bit security: Y(128by) r(64by) MAC(64by) = 256 bytes
|
||||
|
||||
c: validate Y, ignore invalid
|
||||
Invalid Y(x,y) would be the additive identity x=0 or any point not on the curve
|
||||
|
||||
c: hY = h * Y
|
||||
c: d = H(A,B,Y,r)
|
||||
c: Verify d >= 1000
|
||||
c: T = AffineX(a * hB + d*a * hY)
|
||||
c: k = H(d,T)
|
||||
|
||||
c: validate MAC, ignore invalid
|
||||
|
||||
Initiator Proof: c2s MAC(k) {"initiator proof"}
|
||||
|
||||
This packet can also include the client's first encrypted message
|
||||
|
||||
256-bit security: MAC(32by) = 32 bytes
|
||||
384-bit security: MAC(48by) = 48 bytes
|
||||
512-bit security: MAC(64by) = 64 bytes
|
||||
|
||||
s: validate MAC, ignore invalid
|
||||
|
||||
Notes:
|
||||
|
||||
The strategy of this protocol is to perform two EC Diffie-Hellman exchanges,
|
||||
one with the long-term server key and the second with an ephemeral key that
|
||||
should be much harder to obtain by an attacker. The resulting two shared
|
||||
secret points are added together into one point that is used for the key.
|
||||
|
||||
It is perfectly acceptable to re-use an ephemeral key for several runs of
|
||||
the protocol. This means that most of the processing done by the server is
|
||||
just one point multiplication.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Schnorr signatures:
|
||||
|
||||
For signing, the signer reuses its Key Agreement key pair (b,B)
|
||||
|
||||
H: Skein-Key, either 256-bit or 512-bit based on security level
|
||||
|
||||
To sign a message M, signer computes:
|
||||
|
||||
ephemeral secret random 1 < k < q, ephemeral point K = k * G
|
||||
e = H(M || K)
|
||||
s = k - b*e (mod q)
|
||||
|
||||
This process is repeated until e and s are non-zero
|
||||
|
||||
Signature: s2c e || s
|
||||
|
||||
256-bit security: e(32by) s(32by) = 64 bytes
|
||||
384-bit security: e(48by) s(48by) = 96 bytes
|
||||
512-bit security: e(64by) s(64by) = 128 bytes
|
||||
|
||||
To verify a signature:
|
||||
|
||||
Check e, s are in the range [1,q-1]
|
||||
|
||||
K' = s*G + e*B
|
||||
e' = H(M || K')
|
||||
|
||||
The signature is verified if e == e'
|
||||
|
||||
Notes:
|
||||
|
||||
K ?= K'
|
||||
= s*G + e*B
|
||||
= (k - b*e)*G + e*(b*G)
|
||||
= k*G - b*e*G + e*b*G
|
||||
= K
|
||||
*/
|
||||
|
||||
|
||||
// If CAT_DETERMINISTIC_KEY_GENERATION is undefined, the time to generate a
|
||||
// key is unbounded, but tends to be 1 try. I think this is a good thing
|
||||
// because it randomizes the runtime and helps avoid timing attacks
|
||||
//#define CAT_DETERMINISTIC_KEY_GENERATION
|
||||
|
||||
// If CAT_USER_ERROR_CHECKING is defined, the key agreement objects will
|
||||
// check to make sure that the input parameters are all the right length
|
||||
// and that the math and prng objects are not null
|
||||
#define CAT_USER_ERROR_CHECKING
|
||||
|
||||
class CAT_EXPORT KeyAgreementCommon
|
||||
{
|
||||
public:
|
||||
static BigTwistedEdwards *InstantiateMath(int bits);
|
||||
|
||||
// Math library register usage
|
||||
static const int ECC_REG_OVERHEAD = 21;
|
||||
|
||||
// c: field prime modulus p = 2^bits - C, p = 5 mod 8 s.t. a=-1 is a square in Fp
|
||||
// d: curve coefficient (yy-xx=1+Dxxyy), not a square in Fp
|
||||
static const int EDWARD_C_256 = 435;
|
||||
static const int EDWARD_D_256 = 31720;
|
||||
static const int EDWARD_C_384 = 2147;
|
||||
static const int EDWARD_D_384 = 13036;
|
||||
static const int EDWARD_C_512 = 875;
|
||||
static const int EDWARD_D_512 = 32;
|
||||
|
||||
// Limits on field prime
|
||||
static const int MAX_BITS = 512;
|
||||
static const int MAX_BYTES = MAX_BITS / 8;
|
||||
static const int MAX_LEGS = MAX_BYTES / sizeof(Leg);
|
||||
|
||||
protected:
|
||||
int KeyBits, KeyBytes, KeyLegs;
|
||||
|
||||
bool Initialize(int bits);
|
||||
|
||||
public:
|
||||
// Generates an unbiased random key in the range 1 < key < q
|
||||
void GenerateKey(BigTwistedEdwards *math, IRandom *prng, Leg *key);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_AGREEMENT_HPP
|
||||
101
DependentExtensions/cat/crypt/tunnel/KeyAgreementInitiator.hpp
Normal file
101
DependentExtensions/cat/crypt/tunnel/KeyAgreementInitiator.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_AGREEMENT_INITIATOR_HPP
|
||||
#define CAT_KEY_AGREEMENT_INITIATOR_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CAT_EXPORT KeyAgreementInitiator : public KeyAgreementCommon
|
||||
{
|
||||
Leg *B; // Responder's public key (pre-shared with initiator)
|
||||
Leg *a; // Initiator's private key (kept secret)
|
||||
Leg *A; // Initiator's public key (shared with responder in Challenge message)
|
||||
Leg *hB; // h*B
|
||||
Leg *G_MultPrecomp; // Precomputed table for multiplication
|
||||
Leg *B_MultPrecomp; // Precomputed table for multiplication
|
||||
Leg *Y_MultPrecomp; // Precomputed table for multiplication
|
||||
Leg *A_neutral; // Endian-neutral A
|
||||
Leg *B_neutral; // Endian-neutral B
|
||||
|
||||
// Identity data
|
||||
Leg *I_private; // Initiator's identity private key
|
||||
Leg *I_public; // Endian-neutral initiator's identity public key
|
||||
|
||||
bool AllocateMemory();
|
||||
void FreeMemory();
|
||||
|
||||
public:
|
||||
KeyAgreementInitiator();
|
||||
~KeyAgreementInitiator();
|
||||
|
||||
bool Initialize(BigTwistedEdwards *math,
|
||||
const u8 *responder_public_key, int public_bytes);
|
||||
|
||||
// Call after Initialize()
|
||||
bool SetIdentity(BigTwistedEdwards *math,
|
||||
const u8 *initiator_public_key, int public_bytes,
|
||||
const u8 *initiator_private_key, int private_bytes);
|
||||
|
||||
public:
|
||||
bool GenerateChallenge(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
u8 *initiator_challenge, int challenge_bytes);
|
||||
|
||||
bool ProcessAnswer(BigTwistedEdwards *math,
|
||||
const u8 *responder_answer, int answer_bytes,
|
||||
Skein *key_hash);
|
||||
|
||||
// Will fail if SetIdentity() has not been called
|
||||
bool ProcessAnswerWithIdentity(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *responder_answer, int answer_bytes,
|
||||
Skein *key_hash,
|
||||
u8 *identity_proof, int proof_bytes);
|
||||
|
||||
CAT_INLINE bool KeyEncryption(Skein *key_hash, AuthenticatedEncryption *auth_enc, const char *key_name)
|
||||
{
|
||||
return auth_enc->SetKey(KeyBytes, key_hash, true, key_name);
|
||||
}
|
||||
|
||||
// Erase the private key after handshake completes
|
||||
// Also done as this object is destroyed
|
||||
void SecureErasePrivateKey();
|
||||
|
||||
public:
|
||||
bool Verify(BigTwistedEdwards *math,
|
||||
const u8 *message, int message_bytes,
|
||||
const u8 *signature, int signature_bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_AGREEMENT_INITIATOR_HPP
|
||||
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_AGREEMENT_RESPONDER_HPP
|
||||
#define CAT_KEY_AGREEMENT_RESPONDER_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
|
||||
#include <cat/threads/Atomic.hpp>
|
||||
|
||||
#if defined(CAT_NO_ATOMIC_ADD) || defined(CAT_NO_ATOMIC_SET)
|
||||
# include <cat/threads/Mutex.hpp>
|
||||
# define CAT_NO_ATOMIC_RESPONDER
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class CAT_EXPORT KeyAgreementResponder : public KeyAgreementCommon
|
||||
{
|
||||
Leg *b; // Responder's private key (kept secret)
|
||||
Leg *B; // Responder's public key (pre-shared with initiator)
|
||||
Leg *B_neutral; // Endian-neutral B
|
||||
Leg *G_MultPrecomp; // 8-bit table for multiplication
|
||||
Leg *y[2]; // Responder's ephemeral private key (kept secret)
|
||||
Leg *Y_neutral[2]; // Responder's ephemeral public key (shared online with initiator)
|
||||
|
||||
#if defined(CAT_NO_ATOMIC_RESPONDER)
|
||||
Mutex m_thread_id_mutex;
|
||||
#endif // CAT_NO_ATOMIC_RESPONDER
|
||||
|
||||
volatile u32 ChallengeCount;
|
||||
volatile u32 ActiveY;
|
||||
|
||||
void Rekey(BigTwistedEdwards *math, FortunaOutput *csprng);
|
||||
bool AllocateMemory();
|
||||
void FreeMemory();
|
||||
|
||||
public:
|
||||
KeyAgreementResponder();
|
||||
~KeyAgreementResponder();
|
||||
|
||||
bool Initialize(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *responder_public_key, int public_bytes,
|
||||
const u8 *responder_private_key, int private_bytes);
|
||||
|
||||
public:
|
||||
bool ProcessChallenge(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *initiator_challenge, int challenge_bytes,
|
||||
u8 *responder_answer, int answer_bytes, Skein *key_hash);
|
||||
|
||||
inline bool KeyEncryption(Skein *key_hash, AuthenticatedEncryption *auth_enc, const char *key_name)
|
||||
{
|
||||
return auth_enc->SetKey(KeyBytes, key_hash, false, key_name);
|
||||
}
|
||||
|
||||
// Public key is filled if proof succeeds, and will return true
|
||||
bool VerifyInitiatorIdentity(BigTwistedEdwards *math,
|
||||
const u8 *responder_answer, int answer_bytes,
|
||||
const u8 *proof, int proof_bytes,
|
||||
u8 *public_key, int public_bytes);
|
||||
|
||||
public:
|
||||
bool Sign(BigTwistedEdwards *math, FortunaOutput *csprng,
|
||||
const u8 *message, int message_bytes,
|
||||
u8 *signature, int signature_bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_AGREEMENT_RESPONDER_HPP
|
||||
47
DependentExtensions/cat/crypt/tunnel/KeyMaker.hpp
Normal file
47
DependentExtensions/cat/crypt/tunnel/KeyMaker.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_KEY_MAKER_HPP
|
||||
#define CAT_KEY_MAKER_HPP
|
||||
|
||||
#include <cat/crypt/tunnel/KeyAgreement.hpp>
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class KeyMaker : public KeyAgreementCommon
|
||||
{
|
||||
public:
|
||||
bool GenerateKeyPair(BigTwistedEdwards *math, FortunaOutput *csprng, u8 *public_key, int public_bytes, u8 *private_key, int private_bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_KEY_MAKER_HPP
|
||||
171
DependentExtensions/cat/db/BombayTable.hpp
Normal file
171
DependentExtensions/cat/db/BombayTable.hpp
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BOMBAY_TABLE_HPP
|
||||
#define CAT_BOMBAY_TABLE_HPP
|
||||
|
||||
#include <cat/threads/RWLock.hpp>
|
||||
#include <cat/io/ThreadPoolFiles.hpp>
|
||||
#include <cat/db/BombayTableIndex.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
namespace bombay {
|
||||
|
||||
|
||||
static u64 INVALID_RECORD_OFFSET = ~(u64)0;
|
||||
|
||||
struct CacheNode
|
||||
{
|
||||
CacheNode *parent, *lower, *higher;
|
||||
u64 offset;
|
||||
};
|
||||
|
||||
class TableIndex;
|
||||
class IHash;
|
||||
|
||||
|
||||
// Query() AsyncBuffer tag must derive from AsyncQueryRead
|
||||
struct AsyncQueryRead
|
||||
{
|
||||
ThreadRefObject *_reference;
|
||||
AsyncCallback _callback;
|
||||
|
||||
CAT_INLINE void SetCallback(AsyncCallback callback = 0, ThreadRefObject *reference = 0)
|
||||
{
|
||||
if (reference)
|
||||
reference->AddRef();
|
||||
|
||||
_callback = callback;
|
||||
_reference = reference;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///// Table
|
||||
|
||||
class Table : public AsyncFile
|
||||
{
|
||||
ShutdownObserver *_shutdown_observer;
|
||||
u32 _record_bytes; // Bytes per record (without CacheNode overhead)
|
||||
u64 _next_record; // Next record offset
|
||||
|
||||
protected:
|
||||
RWLock _lock;
|
||||
|
||||
u64 _index_database_size, _index_read_offset, _index_read_completed;
|
||||
u32 _index_read_size;
|
||||
static const u32 MAX_INDEX_READ_SIZE = 32768;
|
||||
static const int NUM_PARALLEL_INDEX_READS = 3;
|
||||
|
||||
// Cache hash table of binary trees
|
||||
static const u32 TARGET_TREE_SIZE = 16;
|
||||
static const u32 MIN_TABLE_SIZE = 2048;
|
||||
|
||||
u32 _hash_table_size;
|
||||
CacheNode **_cache_hash_table;
|
||||
|
||||
u8 *_cache; // Cache memory
|
||||
u32 _cache_bytes; // Cache bytes
|
||||
u32 _next_cache_slot; // Offset in cache memory to next free slot
|
||||
bool _cache_full; // Cache full flag for optimization
|
||||
|
||||
TableIndex *_head_index, *_head_index_unique;
|
||||
TableIndex *_head_index_waiting, *_head_index_update;
|
||||
|
||||
bool AllocateCache();
|
||||
void FreeCache();
|
||||
|
||||
// Node versions
|
||||
CacheNode *FindNode(u64 offset);
|
||||
void UnlinkNode(CacheNode *node);
|
||||
void InsertNode(u64 offset, u32 key, CacheNode *hint, CacheNode *node);
|
||||
|
||||
// Always returns with a cache node; may re-use an old cache node
|
||||
u8 *SetOffset(u64 offset);
|
||||
u8 *InsertOffset(u64 offset);
|
||||
u8 *PeekOffset(u64 offset);
|
||||
bool RemoveOffset(u64 offset);
|
||||
|
||||
public:
|
||||
Table(const char *file_path, u32 record_bytes, u32 cache_bytes, ShutdownObserver *shutdown_observer);
|
||||
virtual ~Table();
|
||||
|
||||
private:
|
||||
TableIndex *MakeIndex(const char *index_file_path, IHash *hash_function, bool unique);
|
||||
u64 UniqueIndexLookup(const void *data);
|
||||
|
||||
public:
|
||||
// To initialize, run MakeIndex() for all of the desired indexing routines,
|
||||
// and then run Initialize(), which will initialize index objects.
|
||||
template<class THashFunc> CAT_INLINE TableIndex *MakeIndex(const char *index_file_path, bool unique)
|
||||
{
|
||||
return MakeIndex(index_file_path, new THashFunc, unique);
|
||||
}
|
||||
|
||||
bool Initialize();
|
||||
|
||||
public:
|
||||
CAT_INLINE u32 GetCacheBytes() { return _cache_bytes; }
|
||||
CAT_INLINE u32 GetRecordBytes() { return _record_bytes; }
|
||||
|
||||
protected:
|
||||
virtual bool OnRemoveRead(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
virtual bool OnQueryRead(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
bool StartIndexing();
|
||||
bool StartIndexingRead();
|
||||
void OnIndexingDone();
|
||||
|
||||
virtual bool OnIndexingRead(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
public:
|
||||
bool RequestIndexRebuild(TableIndex *index);
|
||||
|
||||
public:
|
||||
// Insert an AsyncBuffer data buffer
|
||||
u64 Insert(void *data);
|
||||
|
||||
// Update with an AsyncBuffer data buffer
|
||||
bool Update(void *data, u64 offset);
|
||||
|
||||
// Query with an AsyncBuffer
|
||||
// NOTE: Query() AsyncBuffer tag must derive from AsyncQueryRead
|
||||
bool Query(u64 offset, AsyncBuffer *buffer);
|
||||
|
||||
// Remove based on offset
|
||||
bool Remove(u64 offset);
|
||||
};
|
||||
|
||||
|
||||
} // namespace bombay
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BOMBAY_TABLE_HPP
|
||||
231
DependentExtensions/cat/db/BombayTableIndex.hpp
Normal file
231
DependentExtensions/cat/db/BombayTableIndex.hpp
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BOMBAY_TABLE_INDEX_HPP
|
||||
#define CAT_BOMBAY_TABLE_INDEX_HPP
|
||||
|
||||
#include <cat/db/BombayTable.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
namespace bombay {
|
||||
|
||||
|
||||
/*
|
||||
Returning 0 from one of these hash functions will cause insertion or lookup to fail,
|
||||
which is how invalid input is intended to be handled.
|
||||
*/
|
||||
|
||||
class IHash
|
||||
{
|
||||
public:
|
||||
virtual u64 HashField(const void *just_field) = 0;
|
||||
virtual u64 HashComplete(const void *complete_record) = 0;
|
||||
virtual u64 HashVarField(const void *just_field, u32 bytes) { return HashField(just_field); }
|
||||
};
|
||||
|
||||
#define DECL_BOMBAY_SCHEMA_VAR_FIELD_HASH(T) \
|
||||
class T : public bombay::IHash \
|
||||
{ \
|
||||
public: \
|
||||
u64 HashField(const void *just_field); \
|
||||
u64 HashComplete(const void *complete_record); \
|
||||
u64 HashVarField(const void *just_field, u32 bytes); \
|
||||
};
|
||||
|
||||
#define DECL_BOMBAY_SCHEMA_FIXED_FIELD_HASH(T) \
|
||||
class T : public bombay::IHash \
|
||||
{ \
|
||||
public: \
|
||||
u64 HashField(const void *just_field); \
|
||||
u64 HashComplete(const void *complete_record); \
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Table index must present a complete index of the contents of a Table.
|
||||
|
||||
The index uses some region of bytes in each entry as a key to find
|
||||
the entry given just that set of bytes. For example, mapping a user
|
||||
name to a database node.
|
||||
|
||||
The table index should be loaded from disk on startup. If this is
|
||||
not possible, then an index rebuild will need to be done on startup.
|
||||
|
||||
Hash table size will be at least twice as large as the number of
|
||||
database entries, growing as needed.
|
||||
|
||||
To avoid a lot of expensive setup, each element is arranged like this:
|
||||
|
||||
<-- MSB LSB -->
|
||||
C(1 bit) || OFFSET+1 (63 bits)
|
||||
HASH(64 bits)
|
||||
|
||||
C: Collision flag
|
||||
0 = No collision
|
||||
1 = Collision, actual data may be stored at next walk location
|
||||
|
||||
OFFSET+1: Database file offset for this entry that contains the
|
||||
full unique identifier. One(1) is added to the offset in
|
||||
the memory representation of the index table element, so that
|
||||
OFFSET = ~0 will be set by zeroing out the table.
|
||||
0 = No data at this table element.
|
||||
Other values = Valid offset+1
|
||||
|
||||
HASH: 64-bit full hash
|
||||
Only low bits are used for table lookup, so hash does not need
|
||||
to be recomputed if the table grows and lookup of something that
|
||||
is not in the table does not have collisions half the time.
|
||||
|
||||
The whole structure fits in one cache line on an x86 server.
|
||||
*/
|
||||
|
||||
class Table;
|
||||
|
||||
class TableIndex : public AsyncFile
|
||||
{
|
||||
friend class Table;
|
||||
|
||||
ShutdownObserver *_shutdown_observer;
|
||||
Table *_parent;
|
||||
IHash *_index_hash;
|
||||
TableIndex *_next, *_next_unique, *_next_loading;
|
||||
|
||||
protected:
|
||||
// (multiplier-1) divisible by all prime factors of table size
|
||||
// (multiplier-1) is a multiple of 4 if table size is a multiple of 4
|
||||
// Increment is relatively prime to the table size.
|
||||
static const u32 COLLISION_MULTIPLIER = 71*7487 * 4 + 1;
|
||||
static const u32 COLLISION_INCREMENTER = 1017234223;
|
||||
|
||||
static const u64 OFFSET_MASK = (~(u64)0) >> 1;
|
||||
static const u64 COLLIDE_MASK = ~OFFSET_MASK;
|
||||
static const u32 MIN_ELEMENTS = 1024;
|
||||
|
||||
static const u32 TABLE_FOOTER_BYTES = 16;
|
||||
static const u64 TABLE_CHECK_HASH_SALT = 0x74B1301234DEADBE;
|
||||
|
||||
RWLock _lock;
|
||||
|
||||
u64 *_table;
|
||||
u32 _table_raw_bytes;
|
||||
u32 _table_elements; // A power of 2; just subtract 1 to make a mask
|
||||
u32 _used_elements;
|
||||
|
||||
char _file_path[MAX_PATH+1];
|
||||
|
||||
bool AllocateTable();
|
||||
bool DoubleTable();
|
||||
void FreeTable();
|
||||
|
||||
protected:
|
||||
void Save();
|
||||
|
||||
public:
|
||||
TableIndex(Table *parent, const char *index_file_path,
|
||||
IHash *hash_function, ShutdownObserver *shutdown_observer);
|
||||
~TableIndex();
|
||||
|
||||
bool Initialize();
|
||||
|
||||
protected:
|
||||
virtual bool OnRead(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
public:
|
||||
CAT_INLINE const char *GetFilePath() { return _file_path; }
|
||||
|
||||
public:
|
||||
CAT_INLINE u64 VarField(const void *data, u32 bytes)
|
||||
{
|
||||
return _index_hash->HashVarField(data, bytes);
|
||||
}
|
||||
CAT_INLINE u64 Field(const void *data)
|
||||
{
|
||||
return _index_hash->HashField(data);
|
||||
}
|
||||
CAT_INLINE u64 Complete(const void *data)
|
||||
{
|
||||
return _index_hash->HashComplete(data);
|
||||
}
|
||||
|
||||
public:
|
||||
// Hash value of 0 will be ignored
|
||||
u64 Lookup(u64 hash);
|
||||
void Insert(u64 hash, u64 offset);
|
||||
void Remove(u64 hash);
|
||||
|
||||
public:
|
||||
CAT_INLINE u64 LookupVarField(const void *data, u32 bytes)
|
||||
{
|
||||
return Lookup(_index_hash->HashVarField(data, bytes));
|
||||
}
|
||||
CAT_INLINE u64 LookupField(const void *data)
|
||||
{
|
||||
return Lookup(_index_hash->HashField(data));
|
||||
}
|
||||
CAT_INLINE u64 LookupComplete(const void *data)
|
||||
{
|
||||
return Lookup(_index_hash->HashComplete(data));
|
||||
}
|
||||
|
||||
public:
|
||||
CAT_INLINE void InsertVarField(const void *data, u32 bytes, u64 offset)
|
||||
{
|
||||
Insert(_index_hash->HashVarField(data, bytes), offset);
|
||||
}
|
||||
CAT_INLINE void InsertField(const void *data, u64 offset)
|
||||
{
|
||||
Insert(_index_hash->HashField(data), offset);
|
||||
}
|
||||
CAT_INLINE void InsertComplete(const void *data, u64 offset)
|
||||
{
|
||||
Insert(_index_hash->HashComplete(data), offset);
|
||||
}
|
||||
|
||||
public:
|
||||
CAT_INLINE void RemoveVarField(const void *data, u32 bytes)
|
||||
{
|
||||
Remove(_index_hash->HashVarField(data, bytes));
|
||||
}
|
||||
CAT_INLINE void RemoveField(const void *data)
|
||||
{
|
||||
Remove(_index_hash->HashField(data));
|
||||
}
|
||||
CAT_INLINE void RemoveComplete(const void *data)
|
||||
{
|
||||
Remove(_index_hash->HashComplete(data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace bombay
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BOMBAY_TABLE_INDEX_HPP
|
||||
76
DependentExtensions/cat/gfx/LoadBitmap.hpp
Normal file
76
DependentExtensions/cat/gfx/LoadBitmap.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LOAD_BITMAP_HPP
|
||||
#define LOAD_BITMAP_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
LoadBitmap() loads a memory-mapped bitmap or a file from disk into RGBA format,
|
||||
meaning the first byte of every pixel is Red, then Green, Blue, and Alpha.
|
||||
The output data is useful for creating an OpenGL texture using GL_RGBA format.
|
||||
The output width and height will be powers of two.
|
||||
|
||||
Parameters:
|
||||
file, bytes : Memory-mapped file pointer and number of bytes in the file
|
||||
path : Alternatively, the path to the file to load
|
||||
width, height : The dimensions of the loaded file, in pixels
|
||||
|
||||
Returns: Zero on error, or a pointer to the rasterized RGBA pixels.
|
||||
|
||||
Free the allocated memory using Aligned::Delete(a);
|
||||
*/
|
||||
void *LoadBitmap(void *file, u32 bytes, u32 &width, u32 &height);
|
||||
void *LoadBitmap(const char *path, u32 &width, u32 &height);
|
||||
|
||||
|
||||
class BMPTokenizer
|
||||
{
|
||||
u8 trans_red, trans_green, trans_blue;
|
||||
|
||||
bool requirePOTS; // Require Power-of-Two Size
|
||||
|
||||
void rasterizeImage(u8 *image);
|
||||
void onImage(u32 *image, u32 newWidth, u32 newHeight);
|
||||
|
||||
public:
|
||||
BMPTokenizer();
|
||||
~BMPTokenizer();
|
||||
|
||||
public:
|
||||
bool LoadFile(const char *path);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // LOAD_BITMAP_HPP
|
||||
162
DependentExtensions/cat/gfx/LoadPNG.hpp
Normal file
162
DependentExtensions/cat/gfx/LoadPNG.hpp
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LOAD_PNG_HPP
|
||||
#define LOAD_PNG_HPP
|
||||
|
||||
#include <cat/AllFramework.hpp>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
#include "zlib-1.2.4/zlib.h"
|
||||
|
||||
namespace cat {
|
||||
|
||||
#include "CRC32.hpp"
|
||||
|
||||
#ifdef CAT_PRAGMA_PACK
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 length;
|
||||
char type[4];
|
||||
} CAT_PACKED SectionHeader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 length;
|
||||
char type[4];
|
||||
u32 crc;
|
||||
} CAT_PACKED EmptySection;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 width, height;
|
||||
u8 bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod;
|
||||
} CAT_PACKED PNG_IHDR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 r, g, b;
|
||||
} CAT_PACKED PLTE_Entry8;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PLTE_Entry8 table[256];
|
||||
} CAT_PACKED PNG_PLTE;
|
||||
|
||||
#ifdef CAT_PRAGMA_PACK
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
|
||||
class PNGSkeletonTokenizer
|
||||
{
|
||||
protected:
|
||||
MMapFile mmf;
|
||||
CRC32Calculator calculator;
|
||||
string path;
|
||||
|
||||
// Split this from the ctor, so virtual overloads are in place by the time we start reading
|
||||
bool read(const u8 signature[8]); // Returns false on failure
|
||||
|
||||
public:
|
||||
PNGSkeletonTokenizer(const string &path, u32 CRC32polynomial);
|
||||
virtual ~PNGSkeletonTokenizer() {}
|
||||
|
||||
protected:
|
||||
// return true only if section is valid (no exceptions please)
|
||||
virtual bool onSection(char type[4], u8 data[], u32 len) = 0;
|
||||
};
|
||||
|
||||
|
||||
class PNGTokenizer : public PNGSkeletonTokenizer
|
||||
{
|
||||
protected:
|
||||
z_stream zstream;
|
||||
u8 *obuf;
|
||||
u32 olen;
|
||||
int lastZlibResult;
|
||||
|
||||
bool requirePOTS;
|
||||
|
||||
PNG_IHDR header;
|
||||
u16 bpp;
|
||||
u32 palette[256];
|
||||
u8 trans_red, trans_green, trans_blue;
|
||||
|
||||
void rasterizeImage(u8 *image);
|
||||
|
||||
public:
|
||||
PNGTokenizer(const string &path, bool requirePOTS);
|
||||
virtual ~PNGTokenizer();
|
||||
|
||||
protected:
|
||||
bool onSection(char type[4], u8 data[], u32 len);
|
||||
|
||||
protected:
|
||||
// Rasterized image in R8G8B8A8 format, new dimensions are powers of two
|
||||
virtual void onImage(u32 *image, u32 newWidth, u32 newHeight);
|
||||
|
||||
protected:
|
||||
// Important sections
|
||||
void onIHDR(PNG_IHDR *infohdr);
|
||||
void onPLTE(PNG_PLTE *c_palette);
|
||||
void onIDAT(u8 *data, u32 len);
|
||||
void onIEND();
|
||||
|
||||
// Transparency info
|
||||
void onTRNS_Color2(u16 red, u16 green, u16 blue);
|
||||
void onTRNS_Color3(u8 trans[256], u16 len);
|
||||
|
||||
// Color space information (all unimplemented)
|
||||
void onGAMA();
|
||||
void onCHRM();
|
||||
void onSRGB();
|
||||
void onICCP();
|
||||
|
||||
// Textual information (all unimplemented)
|
||||
void onTEXT();
|
||||
void onZTXT();
|
||||
void onITXT();
|
||||
|
||||
// Other non-essential info (all unimplemented)
|
||||
void onBKGD();
|
||||
void onPHYS();
|
||||
void onSBIT();
|
||||
void onSPLT();
|
||||
void onHIST();
|
||||
void onTIME();
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // LOAD_PNG_HPP
|
||||
186
DependentExtensions/cat/gfx/Matrix.hpp
Normal file
186
DependentExtensions/cat/gfx/Matrix.hpp
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_MATRIX_HPP
|
||||
#define CAT_MATRIX_HPP
|
||||
|
||||
#include <cat/gfx/Vector.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
#define FOR_EACH_ELEMENT(index) for (int index = 0; index < ELEMENTS; ++index)
|
||||
|
||||
|
||||
/*
|
||||
4x4 matrix elements arranged column major (row, column):
|
||||
|
||||
m[0] m[4] m[8] m[12]
|
||||
m[1] m[5] m[9] m[13]
|
||||
m[2] m[6] m[10] m[14]
|
||||
m[3] m[7] m[11] m[15]
|
||||
|
||||
Matrix element order corresponds to OpenGL matrix ordering s.t. in a
|
||||
4x4 matrix the elements define the following new coordinate system:
|
||||
|
||||
new x-axis vector: { m[0] m[1] m[2] }
|
||||
new y-axis vector: { m[4] m[5] m[6] }
|
||||
new z-axis vector: { m[7] m[9] m[10] }
|
||||
new origin: { m[12] m[13] m[14] }
|
||||
*/
|
||||
|
||||
template<int ROWS, int COLS, class Scalar> class Matrix
|
||||
{
|
||||
protected:
|
||||
static const int ELEMENTS = ROWS * COLS;
|
||||
Scalar _elements[ROWS * COLS];
|
||||
|
||||
public:
|
||||
// Short-hand for the current matrix type
|
||||
typedef Matrix<ROWS, COLS, Scalar> mytype;
|
||||
|
||||
// Default constructor does not initialize elements
|
||||
Matrix()
|
||||
{
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
Matrix(const mytype &u)
|
||||
{
|
||||
memcpy(_elements, u._elements, sizeof(_elements));
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
mytype &operator=(const mytype &u)
|
||||
{
|
||||
memcpy(_elements, u._elements, sizeof(_elements));
|
||||
}
|
||||
|
||||
// Load zero matrix
|
||||
void loadZero()
|
||||
{
|
||||
OBJCLR(_elements);
|
||||
}
|
||||
|
||||
// Load identity matrix
|
||||
void loadIdentity()
|
||||
{
|
||||
OBJCLR(_elements);
|
||||
|
||||
// Write a 1 along the diagonal
|
||||
for (int ii = 0; ii < ROWS && ii < COLS; ++ii)
|
||||
{
|
||||
_elements[ii * ROWS + ii] = static_cast<Scalar>( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Addition in-place
|
||||
mytype &operator+=(const mytype &u)
|
||||
{
|
||||
FOR_EACH_ELEMENT(ii) _elements[ii] += u._elements[ii];
|
||||
}
|
||||
|
||||
// Subtraction in-place
|
||||
mytype &operator-=(const mytype &u)
|
||||
{
|
||||
FOR_EACH_ELEMENT(ii) _elements[ii] -= u._elements[ii];
|
||||
}
|
||||
|
||||
// Multiplication by scalar in-place
|
||||
mytype &operator*=(Scalar u)
|
||||
{
|
||||
FOR_EACH_ELEMENT(ii) _elements[ii] *= u;
|
||||
}
|
||||
|
||||
// Division by scalar in-place
|
||||
mytype &operator/=(Scalar u)
|
||||
{
|
||||
FOR_EACH_ELEMENT(ii) _elements[ii] /= u;
|
||||
}
|
||||
|
||||
// Matrix multiplication
|
||||
template<int OTHER_COLS>
|
||||
Matrix<ROWS, OTHER_COLS, Scalar> operator*(const Matrix<COLS, OTHER_COLS, Scalar> &u)
|
||||
{
|
||||
Matrix<ROWS, OTHER_COLS, Scalar> result;
|
||||
|
||||
// For each row of the matrix product,
|
||||
for (int r = 0; r < ROWS; ++r)
|
||||
{
|
||||
// For each column of the matrix product,
|
||||
for (int c = 0; c < OTHER_COLS; ++c)
|
||||
{
|
||||
Scalar x = static_cast<Scalar>( 0 );
|
||||
|
||||
// For each row of the right operand (u),
|
||||
for (int ii = 0; ii < COLS; ++ii)
|
||||
{
|
||||
// Accumulate sum of products
|
||||
x += (*this)(r, ii) * u(ii, c);
|
||||
}
|
||||
|
||||
// Write the sum
|
||||
result(r, c) = x;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Accessors
|
||||
inline Scalar &operator()(int ii) { return _elements[ii]; }
|
||||
inline const Scalar &operator()(int ii) const { return _elements[ii]; }
|
||||
|
||||
inline Scalar &operator()(int row, int col) { return _elements[col * ROWS + row]; }
|
||||
inline const Scalar &operator()(int row, int col) const { return _elements[col * ROWS + row]; }
|
||||
};
|
||||
|
||||
|
||||
// Short-hand for common usages:
|
||||
|
||||
typedef Matrix<2, 2, u32> Matrix2x2u;
|
||||
typedef Matrix<3, 3, u32> Matrix3x3u;
|
||||
typedef Matrix<4, 4, u32> Matrix4x4u;
|
||||
|
||||
typedef Matrix<2, 2, s32> Matrix2x2i;
|
||||
typedef Matrix<3, 3, s32> Matrix3x3i;
|
||||
typedef Matrix<4, 4, s32> Matrix4x4i;
|
||||
|
||||
typedef Matrix<2, 2, f32> Matrix2x2f;
|
||||
typedef Matrix<3, 3, f32> Matrix3x3f;
|
||||
typedef Matrix<4, 4, f32> Matrix4x4f;
|
||||
|
||||
typedef Matrix<2, 2, f64> Matrix2x2d;
|
||||
typedef Matrix<3, 3, f64> Matrix3x3d;
|
||||
typedef Matrix<4, 4, f64> Matrix4x4d;
|
||||
|
||||
|
||||
#undef FOR_EACH_ELEMENT
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_MATRIX_HPP
|
||||
401
DependentExtensions/cat/gfx/Quaternion.hpp
Normal file
401
DependentExtensions/cat/gfx/Quaternion.hpp
Normal file
@ -0,0 +1,401 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Based on code from "Physics for Game Developers", David M. Bourg
|
||||
|
||||
slerp() code adapted from this website:
|
||||
http://www.number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
|
||||
*/
|
||||
|
||||
#ifndef CAT_QUATERNION_HPP
|
||||
#define CAT_QUATERNION_HPP
|
||||
|
||||
#include <cat/gfx/Vector.hpp>
|
||||
#include <cat/gfx/Matrix.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Generic quaternion class for linear algebra
|
||||
template <typename Scalar, typename Double>
|
||||
class Quaternion
|
||||
{
|
||||
protected:
|
||||
// Backed by a 4D vector with elements arranged as <x,y,z,w>
|
||||
Vector<4, Scalar, Double> _v;
|
||||
|
||||
public:
|
||||
// Short-hand for the current quaternion type
|
||||
typedef Quaternion<Scalar, Double> mytype;
|
||||
|
||||
// Short-hand for the vector type
|
||||
typedef Vector<3, Scalar, Double> vectype;
|
||||
|
||||
// Uninitialized quaternion is not cleared
|
||||
Quaternion() { }
|
||||
|
||||
// Copy constructor
|
||||
Quaternion(const mytype &u)
|
||||
: _v(u._v)
|
||||
{
|
||||
}
|
||||
|
||||
// Initialization constructor
|
||||
Quaternion(const vectype &v, Scalar w)
|
||||
: _v(v)
|
||||
{
|
||||
}
|
||||
|
||||
// Initialization constructor
|
||||
Quaternion(Scalar x, Scalar y, Scalar z, Scalar w)
|
||||
: _v(x, y, z, w)
|
||||
{
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
mytype &operator=(const mytype &u)
|
||||
{
|
||||
_v.copy(u._v);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Convert from Euler angle representation
|
||||
// Pre-condition: angles in radians (see Deg2Rad in Scalar.hpp)
|
||||
void setFromEulerAngles(f32 xroll, f32 ypitch, f32 zyaw)
|
||||
{
|
||||
f64 croll = cos(0.5f * xroll);
|
||||
f64 cpitch = cos(0.5f * ypitch);
|
||||
f64 cyaw = cos(0.5f * zyaw);
|
||||
f64 sroll = sin(0.5f * xroll);
|
||||
f64 spitch = sin(0.5f * ypitch);
|
||||
f64 syaw = sin(0.5f * zyaw);
|
||||
|
||||
f64 cyawcpitch = cyaw * cpitch;
|
||||
f64 syawspitch = syaw * spitch;
|
||||
f64 cyawspitch = cyaw * spitch;
|
||||
f64 syawcpitch = syaw * cpitch;
|
||||
|
||||
_v(0) = static_cast<Scalar>( cyawcpitch * sroll - syawspitch * croll );
|
||||
_v(1) = static_cast<Scalar>( cyawspitch * croll + syawcpitch * sroll );
|
||||
_v(2) = static_cast<Scalar>( syawcpitch * croll - cyawspitch * sroll );
|
||||
_v(3) = static_cast<Scalar>( cyawcpitch * croll + syawspitch * sroll );
|
||||
|
||||
_v.normalize();
|
||||
}
|
||||
|
||||
// Convert from axis-angle representation
|
||||
// Pre-condition: axis must be unit-length
|
||||
void setFromAxisAngle(const vectype &axis, f32 angle)
|
||||
{
|
||||
angle *= 0.5f;
|
||||
|
||||
Scalar theta = static_cast<Scalar>( sin(angle) );
|
||||
|
||||
_v(0) = theta * axis(0);
|
||||
_v(1) = theta * axis(1);
|
||||
_v(2) = theta * axis(2);
|
||||
_v(3) = static_cast<Scalar>( cos(angle) );
|
||||
}
|
||||
|
||||
// Conjugate
|
||||
mytype operator~() const
|
||||
{
|
||||
return mytype(-_v(0), -_v(1), -_v(2), _v(3));
|
||||
}
|
||||
|
||||
// Conjugate in-place
|
||||
mytype &conjugate() const
|
||||
{
|
||||
_v(0) = -_v(0);
|
||||
_v(1) = -_v(1);
|
||||
_v(2) = -_v(2);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Multiply by quaternion
|
||||
mytype operator*(const mytype &u)
|
||||
{
|
||||
// Cache each of the elements since each is used 4 times
|
||||
Double x1 = _v(0), x2 = u._v(0);
|
||||
Double y1 = _v(1), y2 = u._v(1);
|
||||
Double z1 = _v(2), z2 = u._v(2);
|
||||
Double w1 = _v(3), w2 = u._v(3);
|
||||
|
||||
// Quaternion multiplication formula:
|
||||
Scalar x3 = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
|
||||
Scalar y3 = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
|
||||
Scalar z3 = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
|
||||
Scalar w3 = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );
|
||||
|
||||
return mytype(x3, y3, z3, w3);
|
||||
}
|
||||
|
||||
// Multiply by quaternion in-place: this = this * u
|
||||
mytype &operator*=(const mytype &u)
|
||||
{
|
||||
// Cache each of the elements since each is used 4 times
|
||||
Double x1 = _v(0), x2 = u._v(0);
|
||||
Double y1 = _v(1), y2 = u._v(1);
|
||||
Double z1 = _v(2), z2 = u._v(2);
|
||||
Double w1 = _v(3), w2 = u._v(3);
|
||||
|
||||
// Quaternion multiplication formula:
|
||||
_v(0) = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
|
||||
_v(1) = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
|
||||
_v(2) = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
|
||||
_v(3) = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Multiply by quaternion in-place: this = u * this
|
||||
mytype &postMultiply(const mytype &u)
|
||||
{
|
||||
// Cache each of the elements since each is used 4 times
|
||||
Double x2 = _v(0), x1 = u._v(0);
|
||||
Double y2 = _v(1), y1 = u._v(1);
|
||||
Double z2 = _v(2), z1 = u._v(2);
|
||||
Double w2 = _v(3), w1 = u._v(3);
|
||||
|
||||
// Quaternion multiplication formula:
|
||||
_v(0) = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
|
||||
_v(1) = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
|
||||
_v(2) = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
|
||||
_v(3) = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Rotate given vector in-place
|
||||
void rotate(vectype &u)
|
||||
{
|
||||
// Implements the simple formula: (q1 * u2 * ~q1).getVector()
|
||||
|
||||
// Cache each of the elements since each is used 4 times
|
||||
Double x1 = _v(0), x2 = u(0);
|
||||
Double y1 = _v(1), y2 = u(1);
|
||||
Double z1 = _v(2), z2 = u(2);
|
||||
Double w1 = _v(3);
|
||||
|
||||
// Quaternion-vector multiplication formula (q3 = q1 * u2):
|
||||
Double x3 = w1*x2 + y1*z2 - z1*y2;
|
||||
Double y3 = w1*y2 - x1*z2 + z1*x2;
|
||||
Double z3 = w1*z2 + x1*y2 - y1*x2;
|
||||
Double w3 = -(x1*x2 + y1*y2 + z1*z2);
|
||||
|
||||
// Quaternion multiplication formula (q2' = q3 * ~q1):
|
||||
u(0) = static_cast<Scalar>( w1*x3 - x1*w3 + y1*z3 - z1*y3 );
|
||||
u(1) = static_cast<Scalar>( w1*y3 - x1*z3 - y1*w3 + z1*x3 );
|
||||
u(2) = static_cast<Scalar>( w1*z3 + x1*y3 - y1*x3 - z1*w3 );
|
||||
}
|
||||
|
||||
// NLERP: Very fast, non-constant velocity and torque-minimal
|
||||
// Precondition: q1, q2 are unit length
|
||||
friend void nlerp(const mytype &q1, const mytype &q2, Scalar t, mytype &result)
|
||||
{
|
||||
// Linearly interpolate and normalize result
|
||||
// This formula is a little more work than "q1 + (q2 - q1) * t"
|
||||
// but less likely to lose precision when it matters
|
||||
|
||||
// Cosine of phi, the angle between the two vectors
|
||||
Double cos_phi = q1._v.dotProduct(q2._v);
|
||||
|
||||
// I have read this may try to rotate around the "long way" sometimes and to
|
||||
// fix that we check if cos(phi) is negative and invert one of the inputs.
|
||||
if (cos_phi < 0.0)
|
||||
{
|
||||
result._v = -q1._v;
|
||||
}
|
||||
else
|
||||
{
|
||||
result._v = q1._v;
|
||||
}
|
||||
|
||||
// Simple linear interpolation
|
||||
Scalar scale0 = static_cast<Scalar>(1) - t;
|
||||
Scalar scale1 = t;
|
||||
|
||||
result._v *= scale0;
|
||||
result._v += q2._v * scale1;
|
||||
result._v.normalize();
|
||||
}
|
||||
|
||||
// SLERP: Slower, constant velocity and torque-minimal
|
||||
// Precondition: q1, q2 are unit length
|
||||
friend void slerp(const mytype &q1, const mytype &q2, Scalar t, mytype &result)
|
||||
{
|
||||
// Cosine of phi, the angle between the two vectors
|
||||
Double cos_phi = q1._v.dotProduct(q2._v);
|
||||
|
||||
// I have read this may try to rotate around the "long way" sometimes and to
|
||||
// fix that we check if cos(phi) is negative and invert one of the inputs.
|
||||
if (cos_phi < 0.0)
|
||||
{
|
||||
cos_phi = -cos_phi;
|
||||
result._v = -q1._v;
|
||||
}
|
||||
else
|
||||
{
|
||||
result._v = q1._v;
|
||||
}
|
||||
|
||||
// Default to simple linear interpolation
|
||||
Scalar scale0 = static_cast<Scalar>(1) - t;
|
||||
Scalar scale1 = t;
|
||||
|
||||
// If the distance is not small we need to do full slerp:
|
||||
if (cos_phi < 0.9995)
|
||||
{
|
||||
// cos_phi is guaranteed to be within the domain of acos(), 0..1
|
||||
Double phi = static_cast<Double>( acos(cos_phi) );
|
||||
Double inv_sin_phi = static_cast<Double>(1) / sin(phi);
|
||||
|
||||
scale0 = static_cast<Scalar>( sin(scale0 * phi) * inv_sin_phi );
|
||||
scale1 = static_cast<Scalar>( sin(scale1 * phi) * inv_sin_phi );
|
||||
}
|
||||
|
||||
result._v *= scale0;
|
||||
result._v += q2._v * scale1;
|
||||
result._v.normalize();
|
||||
}
|
||||
|
||||
// Get angle of rotation
|
||||
Scalar getAngle()
|
||||
{
|
||||
return static_cast<Scalar>( 2 ) * static_cast<Scalar>( acos(_v(3)) );
|
||||
}
|
||||
|
||||
// Get axis of rotation
|
||||
vectype getAxis()
|
||||
{
|
||||
return vectype(_v(0), _v(1), _v(2)).normalize();
|
||||
}
|
||||
|
||||
// Get matrix form of the rotation represented by this quaternion
|
||||
void getMatrix4x4(Matrix<4, 4, Scalar> &result)
|
||||
{
|
||||
Double dx = _v(0);
|
||||
Double dy = _v(1);
|
||||
Double dz = _v(2);
|
||||
Double dw = _v(3);
|
||||
|
||||
Double x2 = dx * dx;
|
||||
Double y2 = dy * dy;
|
||||
Double z2 = dz * dz;
|
||||
Double xy = dx * dy;
|
||||
Double yz = dy * dz;
|
||||
Double zx = dz * dx;
|
||||
Double xw = dx * dw;
|
||||
Double yw = dy * dw;
|
||||
Double zw = dz * dw;
|
||||
|
||||
const Double ONE = static_cast<Double>( 1 );
|
||||
const Double TWO = static_cast<Double>( 2 );
|
||||
|
||||
// Result is written in OpenGL column-major matrix order:
|
||||
result( 0) = static_cast<Scalar>( ONE - TWO * (y2 + z2) );
|
||||
result( 1) = static_cast<Scalar>( TWO * (xy - zw) );
|
||||
result( 2) = static_cast<Scalar>( TWO * (zx + yw) );
|
||||
result( 3) = static_cast<Scalar>( 0 );
|
||||
|
||||
result( 4) = static_cast<Scalar>( TWO * (xy + zw) );
|
||||
result( 5) = static_cast<Scalar>( ONE - TWO * (x2 + z2) );
|
||||
result( 6) = static_cast<Scalar>( TWO * (yz - xw) );
|
||||
result( 7) = static_cast<Scalar>( 0 );
|
||||
|
||||
result( 8) = static_cast<Scalar>( TWO * (zx - yw) );
|
||||
result( 9) = static_cast<Scalar>( TWO * (yz + xw) );
|
||||
result(10) = static_cast<Scalar>( ONE - TWO * (x2 + y2) );
|
||||
result(11) = static_cast<Scalar>( 0 );
|
||||
|
||||
result(12) = static_cast<Scalar>( 0 );
|
||||
result(13) = static_cast<Scalar>( 0 );
|
||||
result(14) = static_cast<Scalar>( 0 );
|
||||
result(15) = static_cast<Scalar>( ONE );
|
||||
}
|
||||
|
||||
// Get Euler angles
|
||||
vectype Quaternion::getEulerAngles()
|
||||
{
|
||||
Double dx = _v(0);
|
||||
Double dy = _v(1);
|
||||
Double dz = _v(2);
|
||||
Double dw = _v(3);
|
||||
|
||||
Double x2 = dx * dx;
|
||||
Double y2 = dy * dy;
|
||||
Double z2 = dz * dz;
|
||||
Double w2 = dw * dw;
|
||||
Double xy = dx * dy;
|
||||
Double yz = dy * dz;
|
||||
Double xw = dx * dw;
|
||||
Double yw = dy * dw;
|
||||
Double zw = dz * dw;
|
||||
|
||||
const Double TWO = static_cast<Double>( 2 );
|
||||
|
||||
Double r11 = w2 + x2 - y2 - z2;
|
||||
Double r21 = TWO * (xy + zw);
|
||||
Double r31 = TWO * (xy - yw);
|
||||
Double r32 = TWO * (yz + xw);
|
||||
Double r33 = w2 - x2 - y2 + z2;
|
||||
|
||||
Double tmp = fabs(r31);
|
||||
const Double LIMIT = static_cast<Double>( 0.999999 );
|
||||
|
||||
if (tmp > LIMIT)
|
||||
{
|
||||
Double xz = dx * dz;
|
||||
|
||||
Double r12 = TWO * (yz - zw);
|
||||
Double r13 = TWO * (xz + yw);
|
||||
|
||||
return vectype(static_cast<Scalar>( 0 ),
|
||||
static_cast<Scalar>( -CAT_HALF_PI_64 * r31 / tmp ),
|
||||
static_cast<Scalar>( atan2(-r12, -r31 * r13) ));
|
||||
}
|
||||
|
||||
return vectype(static_cast<Scalar>( atan2(r32, r33) ),
|
||||
static_cast<Scalar>( asin(-r31) ),
|
||||
static_cast<Scalar>( atan2(r21, r11) ));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Short-hand for common usages:
|
||||
|
||||
typedef Quaternion<f32, f64> Quaternion4f;
|
||||
typedef Quaternion<f64, f64> Quaternion4d;
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_QUATERNION_HPP
|
||||
85
DependentExtensions/cat/gfx/Scalar.hpp
Normal file
85
DependentExtensions/cat/gfx/Scalar.hpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SCALAR_HPP
|
||||
#define CAT_SCALAR_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// PI
|
||||
#define CAT_TWO_PI_64 6.283185307179586476925286766559
|
||||
#define CAT_TWO_PI_32 6.28318531f
|
||||
#define CAT_PI_64 3.1415926535897932384626433832795
|
||||
#define CAT_PI_32 3.14159265f
|
||||
#define CAT_HALF_PI_64 1.5707963267948966192313216916398
|
||||
#define CAT_HALF_PI_32 1.5707963268f
|
||||
#define CAT_QUARTER_PI_64 0.78539816339744830961566084581988
|
||||
#define CAT_QUARTER_PI_32 0.7853981634f
|
||||
#define CAT_INV_PI_64 0.31830988618379067153776752674503
|
||||
#define CAT_INV_PI_32 0.3183098862f
|
||||
|
||||
|
||||
// Angle conversion
|
||||
inline f64 Deg2Rad(f64 angle)
|
||||
{
|
||||
return angle * CAT_TWO_PI_64 / 360.0;
|
||||
}
|
||||
inline f32 Deg2Rad(f32 angle)
|
||||
{
|
||||
return angle * CAT_TWO_PI_32 / 360.0f;
|
||||
}
|
||||
inline f64 Rad2Deg(f64 angle)
|
||||
{
|
||||
return angle * 360.0 / CAT_TWO_PI_64;
|
||||
}
|
||||
inline f32 Rad2Deg(f32 angle)
|
||||
{
|
||||
return angle * 360.0f / CAT_TWO_PI_32;
|
||||
}
|
||||
|
||||
|
||||
// Generic clamp() function
|
||||
template<class Scalar>
|
||||
void Clamp(Scalar &x, Scalar low, Scalar high)
|
||||
{
|
||||
if (x < low) x = low;
|
||||
else if (x > high) x = high;
|
||||
}
|
||||
|
||||
|
||||
// Fast inverse square root
|
||||
f32 InvSqrt(f32 x);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SCALAR_HPP
|
||||
389
DependentExtensions/cat/gfx/Vector.hpp
Normal file
389
DependentExtensions/cat/gfx/Vector.hpp
Normal file
@ -0,0 +1,389 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_VECTOR_HPP
|
||||
#define CAT_VECTOR_HPP
|
||||
|
||||
#include <cat/gfx/Scalar.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
#define FOR_EACH_DIMENSION(index) for (int index = 0; index < DIM; ++index)
|
||||
|
||||
|
||||
// Generic vector class for linear algebra
|
||||
template<int DIM, typename Scalar, typename Double> class Vector
|
||||
{
|
||||
protected:
|
||||
// Protected internal storage of vector components
|
||||
Scalar _elements[DIM];
|
||||
|
||||
public:
|
||||
// Short-hand for the current vector type
|
||||
typedef Vector<DIM, Scalar, Double> mytype;
|
||||
|
||||
// Uninitialized vector is not cleared
|
||||
Vector() {}
|
||||
|
||||
// Component-wise initializing constructors
|
||||
Vector(Scalar x, Scalar y)
|
||||
{
|
||||
_elements[0] = x;
|
||||
_elements[1] = y;
|
||||
}
|
||||
Vector(Scalar x, Scalar y, Scalar z)
|
||||
{
|
||||
_elements[0] = x;
|
||||
_elements[1] = y;
|
||||
_elements[2] = z;
|
||||
}
|
||||
Vector(Scalar x, Scalar y, Scalar z, Scalar w)
|
||||
{
|
||||
_elements[0] = x;
|
||||
_elements[1] = y;
|
||||
_elements[2] = z;
|
||||
_elements[3] = w;
|
||||
}
|
||||
|
||||
// Make the vector a copy of a given vector
|
||||
mytype ©(const mytype &u)
|
||||
{
|
||||
memcpy(_elements, u._elements, sizeof(_elements));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
Vector(const mytype &u)
|
||||
{
|
||||
copy(u);
|
||||
}
|
||||
|
||||
// Assignment operator
|
||||
mytype &operator=(const mytype &u)
|
||||
{
|
||||
return copy(u);
|
||||
}
|
||||
|
||||
// Magnitude calculation
|
||||
Double magnitude() const
|
||||
{
|
||||
Double element, sum = 0;
|
||||
|
||||
FOR_EACH_DIMENSION(ii)
|
||||
{
|
||||
element = _elements[ii];
|
||||
sum += element * element;
|
||||
}
|
||||
|
||||
return static_cast<Double>( sqrt(sum) );
|
||||
}
|
||||
|
||||
// Fast normalization for 32-bit floating point elements in-place
|
||||
mytype &normalize_fast_f32()
|
||||
{
|
||||
f32 element = _elements[0];
|
||||
f32 sum = element * element;
|
||||
|
||||
for (int ii = 1; ii < DIM; ++ii)
|
||||
{
|
||||
element = _elements[ii];
|
||||
sum += element * element;
|
||||
}
|
||||
|
||||
// If sum is not close to 1, then perform normalization:
|
||||
if (sum > 1.005f || sum < 0.995f)
|
||||
{
|
||||
f32 inv = InvSqrt(sum);
|
||||
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Normalization in-place
|
||||
mytype &normalize()
|
||||
{
|
||||
Double m = magnitude();
|
||||
Double inv = static_cast<Double>( 1 ) / m;
|
||||
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Zero elements
|
||||
void zero()
|
||||
{
|
||||
OBJCLR(_elements);
|
||||
}
|
||||
|
||||
// Is zero?
|
||||
bool isZero()
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii)
|
||||
if (_elements[ii] != static_cast<Scalar>( 0 ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// For consistency with Matrix class, use the () operator instead of [] to index it
|
||||
inline Scalar &operator()(int ii) { return _elements[ii]; }
|
||||
inline Scalar &x() { return _elements[0]; }
|
||||
inline Scalar &y() { return _elements[1]; }
|
||||
inline Scalar &z() { return _elements[2]; }
|
||||
inline Scalar &w() { return _elements[3]; }
|
||||
|
||||
// Const version for accessors
|
||||
inline const Scalar &operator()(int ii) const { return _elements[ii]; }
|
||||
inline const Scalar &x() const { return _elements[0]; }
|
||||
inline const Scalar &y() const { return _elements[1]; }
|
||||
inline const Scalar &z() const { return _elements[2]; }
|
||||
inline const Scalar &w() const { return _elements[3]; }
|
||||
|
||||
// Negation
|
||||
mytype operator-() const
|
||||
{
|
||||
mytype x;
|
||||
|
||||
FOR_EACH_DIMENSION(ii) x._elements[ii] = -_elements[ii];
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Negation in-place
|
||||
mytype &negate()
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] = -_elements[ii];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Addition
|
||||
mytype operator+(const mytype &u) const
|
||||
{
|
||||
mytype x;
|
||||
|
||||
FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] + u._elements[ii];
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Addition in-place
|
||||
mytype &operator+=(const mytype &u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] += u._elements[ii];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Add a scalar to each element in-place
|
||||
mytype &addToEachElement(Scalar u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] += u;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Subtraction
|
||||
mytype operator-(const mytype &u) const
|
||||
{
|
||||
mytype x;
|
||||
|
||||
FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] - u._elements[ii];
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Subtraction in-place
|
||||
mytype &operator-=(const mytype &u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] -= u._elements[ii];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Subtract a scalar from each element in-place
|
||||
mytype &subtractFromEachElement(Scalar u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] -= u;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Scalar multiplication
|
||||
mytype operator*(Scalar u) const
|
||||
{
|
||||
mytype x;
|
||||
|
||||
FOR_EACH_DIMENSION(ii) x._elements[ii] = u * _elements[ii];
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Scalar multiplication in-place
|
||||
mytype &operator*=(Scalar u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] *= u;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Component-wise multiply in-place
|
||||
mytype &componentMultiply(const mytype &u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] *= u._elements[ii];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Scalar division
|
||||
mytype operator/(Scalar u) const
|
||||
{
|
||||
mytype x;
|
||||
|
||||
Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
|
||||
|
||||
FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] * inv_u;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// Scalar division in-place
|
||||
mytype &operator/=(Scalar u)
|
||||
{
|
||||
Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
|
||||
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] *= inv_u;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Component-wise divide in-place
|
||||
mytype &componentDivide(const mytype &u)
|
||||
{
|
||||
FOR_EACH_DIMENSION(ii) _elements[ii] /= u._elements[ii];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Dot product
|
||||
Double dotProduct(const mytype &u) const
|
||||
{
|
||||
Double sum = 0;
|
||||
|
||||
FOR_EACH_DIMENSION(ii)
|
||||
sum += static_cast<Double>( _elements[ii] )
|
||||
* static_cast<Double>( u._elements[ii] );
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
public:
|
||||
// Only for 2-element vectors:
|
||||
|
||||
// Generate a 2D rotation vector in-place
|
||||
void generateRotation2D(f32 angle)
|
||||
{
|
||||
x() = cos(angle);
|
||||
y() = sin(angle);
|
||||
}
|
||||
|
||||
// Add rotation vector in-place
|
||||
mytype &addRotation2D(const mytype &r)
|
||||
{
|
||||
Double ax = x(), ay = y();
|
||||
Double rx = r.x(), ry = r.y();
|
||||
|
||||
x() = static_cast<Scalar>( ax*rx - ay*ry ); // cos(a+r) = cos(a)*cos(r) - sin(a)*sin(r)
|
||||
y() = static_cast<Scalar>( ay*rx + ax*ry ); // sin(a+r) = sin(a)*cos(r) + cos(a)*sin(r)
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Subtract rotation vector in-place
|
||||
mytype &subtractRotation2D(const mytype &r)
|
||||
{
|
||||
Double ax = x(), ay = y();
|
||||
Double rx = r.x(), ry = r.y();
|
||||
|
||||
x() = static_cast<Scalar>( ax*rx + ay*ry ); // cos(a-r) = cos(a)*cos(r) + sin(a)*sin(r)
|
||||
y() = static_cast<Scalar>( ay*rx - ax*ry ); // sin(a-r) = sin(a)*cos(r) - cos(a)*sin(r)
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Cross product: Result is a scalar
|
||||
f32 crossProduct2D(const mytype &u)
|
||||
{
|
||||
return x() * u.y() - y() * u.x();
|
||||
}
|
||||
|
||||
public:
|
||||
// Only for 3-element vectors:
|
||||
|
||||
// Cross product: Result is a 3D vector
|
||||
mytype crossProduct3D(const mytype &u)
|
||||
{
|
||||
mytype result;
|
||||
|
||||
result.x() = y() * u.z() - z() * u.y();
|
||||
result.y() = z() * u.x() - x() * u.z();
|
||||
result.z() = x() * u.y() - y() * u.x();
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Short-hand for common usages:
|
||||
|
||||
typedef Vector<2, u32, u32> Vector2u;
|
||||
typedef Vector<3, u32, u32> Vector3u;
|
||||
typedef Vector<4, u32, u32> Vector4u;
|
||||
|
||||
typedef Vector<2, s32, s32> Vector2s;
|
||||
typedef Vector<3, s32, s32> Vector3s;
|
||||
typedef Vector<4, s32, s32> Vector4s;
|
||||
|
||||
typedef Vector<2, f32, f64> Vector2f;
|
||||
typedef Vector<3, f32, f64> Vector3f;
|
||||
typedef Vector<4, f32, f64> Vector4f;
|
||||
|
||||
typedef Vector<2, f64, f64> Vector2d;
|
||||
typedef Vector<3, f64, f64> Vector3d;
|
||||
typedef Vector<4, f64, f64> Vector4d;
|
||||
|
||||
|
||||
#undef FOR_EACH_DIMENSION
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_VECTOR_HPP
|
||||
80
DependentExtensions/cat/hash/MurmurHash2.hpp
Normal file
80
DependentExtensions/cat/hash/MurmurHash2.hpp
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
MurmurHash2 is a very fast noncryptographic 32/64-bit hash
|
||||
|
||||
Algorithm by Austin Appleby <aappleby@gmail.com>
|
||||
http://murmurhash.googlepages.com/
|
||||
*/
|
||||
|
||||
#ifndef CAT_MURMUR_HASH_2_HPP
|
||||
#define CAT_MURMUR_HASH_2_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// NOTE: Result is NOT endian-neutral. Use getLE().
|
||||
u32 MurmurHash32(const void *key, int bytes, u32 seed);
|
||||
u64 MurmurHash64(const void *key, int bytes, u64 seed);
|
||||
|
||||
|
||||
class IncrementalMurmurHash32
|
||||
{
|
||||
u32 _hash, _tail, _count, _size;
|
||||
|
||||
static const u32 M = 0x5bd1e995;
|
||||
static const u32 R = 24;
|
||||
|
||||
public:
|
||||
void Begin(u32 seed = 0);
|
||||
void Add(const void *data, int bytes);
|
||||
u32 End();
|
||||
};
|
||||
|
||||
|
||||
class IncrementalMurmurHash64
|
||||
{
|
||||
u32 _count;
|
||||
u64 _hash, _tail, _size;
|
||||
|
||||
static const u64 M = 0xc6a4a7935bd1e995ULL;
|
||||
static const u64 R = 47;
|
||||
|
||||
public:
|
||||
void Begin(u64 seed = 0);
|
||||
void Add(const void *data, int bytes);
|
||||
u64 End();
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_MURMUR_HASH_2_HPP
|
||||
261
DependentExtensions/cat/io/AsyncBuffer.hpp
Normal file
261
DependentExtensions/cat/io/AsyncBuffer.hpp
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_ASYNC_BUFFER_HPP
|
||||
#define CAT_ASYNC_BUFFER_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <cat/port/FastDelegate.h>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class ThreadPoolLocalStorage;
|
||||
class AsyncBuffer;
|
||||
|
||||
|
||||
typedef fastdelegate::FastDelegate4<ThreadPoolLocalStorage *, int, AsyncBuffer *, u32, bool> AsyncCallback;
|
||||
|
||||
|
||||
// Overlapped base object
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
typedef OVERLAPPED AsyncOv;
|
||||
#else
|
||||
#error "TODO"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
AsyncBuffer: Utility object representing the buffers for a single I/O operation.
|
||||
|
||||
This is flexible enough to represent network and file IO buffers.
|
||||
*/
|
||||
class AsyncBuffer
|
||||
{
|
||||
private:
|
||||
AsyncOv _ov;
|
||||
AsyncCallback _callback;
|
||||
u8 *_data;
|
||||
u32 _data_bytes, _tag_bytes;
|
||||
u8 _tag[1];
|
||||
|
||||
public:
|
||||
// Reset AsyncOv and set offset and callback
|
||||
CAT_INLINE void Reset(const AsyncCallback &callback, u64 offset = 0)
|
||||
{
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
_ov.hEvent = 0;
|
||||
_ov.Internal = 0;
|
||||
_ov.InternalHigh = 0;
|
||||
_ov.OffsetHigh = (u32)(offset >> 32);
|
||||
_ov.Offset = (u32)offset;
|
||||
#else
|
||||
#error "TODO"
|
||||
#endif
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
public:
|
||||
static CAT_INLINE u32 OVERHEAD() { return (u32)(offsetof(AsyncBuffer, _tag)); }
|
||||
|
||||
CAT_INLINE AsyncOv *GetOv() { return &_ov; }
|
||||
CAT_INLINE u64 GetOffset() { return ((u64)_ov.OffsetHigh << 32) | _ov.Offset; }
|
||||
|
||||
CAT_INLINE bool Call(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes)
|
||||
{
|
||||
if (!_callback) return true;
|
||||
return _callback(tls, error, buffer, bytes);
|
||||
}
|
||||
|
||||
CAT_INLINE void Zero()
|
||||
{
|
||||
CAT_CLR(_data, _data_bytes);
|
||||
}
|
||||
|
||||
public:
|
||||
CAT_INLINE u32 GetDataBytes() { return _data_bytes; }
|
||||
|
||||
CAT_INLINE u8 *GetData() { return reinterpret_cast<u8*>( _data ); }
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE T *GetData() { return reinterpret_cast<T*>( _data ); }
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE T *GetData(T * &ptr) { return (ptr = reinterpret_cast<T*>( _data )); }
|
||||
|
||||
public:
|
||||
CAT_INLINE u32 GetTagBytes() { return _tag_bytes; }
|
||||
|
||||
CAT_INLINE u8 *GetTagData() { return _tag; }
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE T *GetTag() { return reinterpret_cast<T*>( _tag ); }
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE T *GetTag(T * &ptr) { return (ptr = reinterpret_cast<T*>( _tag )); }
|
||||
|
||||
public:
|
||||
// Acquire with built-in data pointer
|
||||
static CAT_INLINE AsyncBuffer *Acquire(AsyncBuffer * &ptr, u32 data_bytes = 0, u32 tag_bytes = 0)
|
||||
{
|
||||
const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag));
|
||||
|
||||
AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>(
|
||||
RegionAllocator::ii->Acquire(OVERHEAD_BYTES + data_bytes + tag_bytes) );
|
||||
|
||||
if (!buffer) return 0;
|
||||
|
||||
buffer->_data_bytes = data_bytes;
|
||||
buffer->_tag_bytes = tag_bytes;
|
||||
buffer->_data = buffer->_tag + tag_bytes;
|
||||
|
||||
return (ptr = buffer);
|
||||
}
|
||||
|
||||
// Change number of data bytes allocated to the buffer
|
||||
// Returns a new data pointer that may be different from the old data pointer
|
||||
CAT_INLINE AsyncBuffer *Resize(u32 data_bytes)
|
||||
{
|
||||
const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag));
|
||||
|
||||
AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>(
|
||||
RegionAllocator::ii->Resize( this,
|
||||
OVERHEAD_BYTES + _tag_bytes + data_bytes) );
|
||||
|
||||
if (!buffer) return 0;
|
||||
|
||||
buffer->_data_bytes = data_bytes;
|
||||
buffer->_data = buffer->_tag + buffer->_tag_bytes;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public:
|
||||
// Acquire with built-in data pointer
|
||||
static CAT_INLINE u8 *Acquire(u32 data_bytes = 0, u32 tag_bytes = 0)
|
||||
{
|
||||
AsyncBuffer *buffer;
|
||||
|
||||
if (!Acquire(buffer, data_bytes, tag_bytes)) return 0;
|
||||
|
||||
return buffer->_data;
|
||||
}
|
||||
|
||||
// Acquire with built-in data pointer
|
||||
template<class T>
|
||||
static CAT_INLINE T *Acquire(T * &data, u32 tag_bytes = 0)
|
||||
{
|
||||
AsyncBuffer *buffer;
|
||||
|
||||
if (!Acquire(buffer, sizeof(T), tag_bytes)) return 0;
|
||||
|
||||
return (data = reinterpret_cast<T*>( buffer->_data ));
|
||||
}
|
||||
|
||||
// Change number of data bytes allocated to the buffer
|
||||
// Returns a new data pointer that may be different from the old data pointer
|
||||
static CAT_INLINE u8 *Resize(void *vdata, u32 data_bytes)
|
||||
{
|
||||
u8 *data = reinterpret_cast<u8*>( vdata );
|
||||
const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag));
|
||||
|
||||
if (!data) return Acquire(data_bytes);
|
||||
|
||||
AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( data - OVERHEAD_BYTES );
|
||||
|
||||
buffer = reinterpret_cast<AsyncBuffer*>(
|
||||
RegionAllocator::ii->Resize(buffer,
|
||||
OVERHEAD_BYTES + buffer->_tag_bytes + data_bytes) );
|
||||
|
||||
if (!buffer) return 0;
|
||||
|
||||
buffer->_data_bytes = data_bytes;
|
||||
|
||||
return (buffer->_data = buffer->_tag + buffer->_tag_bytes);
|
||||
}
|
||||
|
||||
public:
|
||||
// Wrap external data pointer
|
||||
static CAT_INLINE AsyncBuffer *Wrap(void *vdata, u32 data_bytes, u32 tag_bytes = 0)
|
||||
{
|
||||
u8 *data = reinterpret_cast<u8*>( vdata );
|
||||
const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag));
|
||||
|
||||
AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>(
|
||||
RegionAllocator::ii->Acquire(OVERHEAD_BYTES + tag_bytes) );
|
||||
|
||||
if (!buffer) return 0;
|
||||
|
||||
buffer->_data_bytes = data_bytes;
|
||||
buffer->_tag_bytes = tag_bytes;
|
||||
buffer->_data = data;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public:
|
||||
// Only works on Acquired() buffers, not Wrap()ed buffers
|
||||
static CAT_INLINE AsyncBuffer *Promote(void *vdata)
|
||||
{
|
||||
u8 *data = reinterpret_cast<u8*>( vdata );
|
||||
const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag));
|
||||
|
||||
if (!data) return 0;
|
||||
return reinterpret_cast<AsyncBuffer*>( data - OVERHEAD_BYTES );
|
||||
}
|
||||
|
||||
public:
|
||||
// Release memory
|
||||
CAT_INLINE void Release()
|
||||
{
|
||||
RegionAllocator::ii->Release(this);
|
||||
}
|
||||
static CAT_INLINE void Release(AsyncBuffer *buffer)
|
||||
{
|
||||
RegionAllocator::ii->Release(buffer);
|
||||
}
|
||||
static CAT_INLINE void Release(void *vdata)
|
||||
{
|
||||
u8 *data = reinterpret_cast<u8*>( vdata );
|
||||
const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag));
|
||||
|
||||
if (!data) return;
|
||||
|
||||
AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( data - OVERHEAD_BYTES );
|
||||
|
||||
RegionAllocator::ii->Release(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_ASYNC_BUFFER_HPP
|
||||
56
DependentExtensions/cat/io/Base64.hpp
Normal file
56
DependentExtensions/cat/io/Base64.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BASE64_HPP
|
||||
#define CAT_BASE64_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Write buffer to output stream in Base64 encoding
|
||||
int GetBase64LengthFromBinaryLength(int bytes);
|
||||
|
||||
// Returns number of bytes written, or 0 for error
|
||||
int WriteBase64(const void *buffer, int bytes, char *encoded_buffer, int encoded_bytes);
|
||||
int WriteBase64Str(const void *buffer, int bytes, char *encoded_buffer, int encoded_bytes); // This version writes a null-terminator
|
||||
int WriteBase64(const void *buffer, int bytes, std::ostream &output);
|
||||
|
||||
// Read buffer in Base64 encoding
|
||||
int GetBinaryLengthFromBase64Length(const char *encoded_buffer, int bytes);
|
||||
|
||||
// Returns number of bytes read, or 0 for error
|
||||
int ReadBase64(const char *encoded_buffer, int encoded_bytes, void *decoded_buffer, int decoded_bytes);
|
||||
int ReadBase64(const char *encoded_buffer, int encoded_bytes, std::ostream &output);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BASE64_HPP
|
||||
194
DependentExtensions/cat/io/Logging.hpp
Normal file
194
DependentExtensions/cat/io/Logging.hpp
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_LOGGING_HPP
|
||||
#define CAT_LOGGING_HPP
|
||||
|
||||
#include <cat/threads/RegionAllocator.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// Enumerations
|
||||
|
||||
enum EventSeverity
|
||||
{
|
||||
LVL_INANE,
|
||||
LVL_INFO,
|
||||
LVL_WARN,
|
||||
LVL_OOPS,
|
||||
LVL_FATAL,
|
||||
|
||||
LVL_SILENT, // invalid for an actual event's level, valid value for a threshold
|
||||
};
|
||||
|
||||
|
||||
//// Utility
|
||||
|
||||
region_string HexDumpString(const void *vdata, u32 bytes);
|
||||
|
||||
// Write to console (and debug log in windows) then trigger a breakpoint and exit
|
||||
void FatalStop(const char *message);
|
||||
|
||||
void DefaultLogCallback(EventSeverity severity, const char *source, region_ostringstream &msg);
|
||||
|
||||
|
||||
//// Logging
|
||||
|
||||
typedef void (*LogCallback)(EventSeverity severity, const char *source, region_ostringstream &msg);
|
||||
|
||||
class Logging : public Singleton<Logging>
|
||||
{
|
||||
CAT_SINGLETON(Logging);
|
||||
|
||||
LogCallback _callback;
|
||||
|
||||
friend class Recorder;
|
||||
void LogEvent(Recorder *recorder);
|
||||
|
||||
public:
|
||||
int _log_threshold;
|
||||
|
||||
public:
|
||||
void Initialize(EventSeverity min_severity = LVL_INANE);
|
||||
CAT_INLINE void SetThreshold(EventSeverity min_severity) { _log_threshold = min_severity; }
|
||||
void ReadSettings();
|
||||
void Shutdown();
|
||||
|
||||
protected:
|
||||
bool _service;
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
HANDLE _event_source;
|
||||
#endif
|
||||
|
||||
public:
|
||||
CAT_INLINE bool IsService() { return _service; }
|
||||
void EnableServiceMode(const char *service_name);
|
||||
void WriteServiceLog(EventSeverity severity, const char *line);
|
||||
|
||||
public:
|
||||
// Not thread-safe
|
||||
CAT_INLINE void SetLogCallback(LogCallback cb) { _callback = cb; }
|
||||
};
|
||||
|
||||
|
||||
//// Recorder
|
||||
|
||||
class Recorder
|
||||
{
|
||||
friend class Logging;
|
||||
EventSeverity _severity;
|
||||
const char *_subsystem;
|
||||
region_ostringstream _msg;
|
||||
|
||||
public:
|
||||
Recorder(const char *subsystem, EventSeverity severity);
|
||||
~Recorder();
|
||||
|
||||
public:
|
||||
template<class T> inline Recorder &operator<<(const T &t)
|
||||
{
|
||||
_msg << t;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// Because there is an IF statement in the macro, you cannot use the
|
||||
// braceless if-else construction:
|
||||
// if (XYZ) WARN("SS") << "ERROR!"; else INFO("SS") << "OK!"; <-- bad
|
||||
// Instead use:
|
||||
// if (XYZ) { WARN("SS") << "ERROR!"; } else INFO("SS") << "OK!"; <-- good
|
||||
#define RECORD(subsystem, severity) \
|
||||
if (severity >= Logging::ii->_log_threshold) Recorder(subsystem, severity)
|
||||
|
||||
#define INANE(subsystem) RECORD(subsystem, LVL_INANE)
|
||||
#define INFO(subsystem) RECORD(subsystem, LVL_INFO)
|
||||
#define WARN(subsystem) RECORD(subsystem, LVL_WARN)
|
||||
#define OOPS(subsystem) RECORD(subsystem, LVL_OOPS)
|
||||
#define FATAL(subsystem) RECORD(subsystem, LVL_FATAL)
|
||||
|
||||
|
||||
//// Enforcer
|
||||
|
||||
class Enforcer
|
||||
{
|
||||
protected:
|
||||
std::ostringstream oss;
|
||||
|
||||
public:
|
||||
Enforcer(const char *locus);
|
||||
~Enforcer();
|
||||
|
||||
public:
|
||||
template<class T> inline Enforcer &operator<<(const T &t)
|
||||
{
|
||||
oss << t;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define USE_ENFORCE_EXPRESSION_STRING
|
||||
#define USE_ENFORCE_FILE_LINE_STRING
|
||||
|
||||
|
||||
#if defined(USE_ENFORCE_EXPRESSION_STRING)
|
||||
# define ENFORCE_EXPRESSION_STRING(exp) "Failed assertion (" #exp ")"
|
||||
#else
|
||||
# define ENFORCE_EXPRESSION_STRING(exp) "Failed assertion"
|
||||
#endif
|
||||
|
||||
#if defined(USE_ENFORCE_FILE_LINE_STRING)
|
||||
# define ENFORCE_FILE_LINE_STRING " at " __FILE__ ":" CAT_STRINGIZE(__LINE__)
|
||||
#else
|
||||
# define ENFORCE_FILE_LINE_STRING ""
|
||||
#endif
|
||||
|
||||
// Because there is an IF statement in the macro, you cannot use the
|
||||
// braceless if-else construction:
|
||||
// if (XYZ) ENFORCE(A == B) << "ERROR"; else INFO("SS") << "OK"; <-- bad!
|
||||
// Instead use:
|
||||
// if (XYZ) { ENFORCE(A == B) << "ERROR"; } else INFO("SS") << "OK"; <-- good!
|
||||
|
||||
#define ENFORCE(exp) if ( (exp) == 0 ) Enforcer(ENFORCE_EXPRESSION_STRING(exp) ENFORCE_FILE_LINE_STRING "\n")
|
||||
#define EXCEPTION() Enforcer("Exception" ENFORCE_FILE_LINE_STRING "\n")
|
||||
|
||||
#if defined(CAT_DEBUG)
|
||||
# define DEBUG_ENFORCE(exp) ENFORCE(exp)
|
||||
#else
|
||||
# define DEBUG_ENFORCE(exp) if (0) ENFORCE(exp) /* hopefully will be optimized out of existence */
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_LOGGING_HPP
|
||||
75
DependentExtensions/cat/io/MMapFile.hpp
Normal file
75
DependentExtensions/cat/io/MMapFile.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_MMAPFILE_HPP
|
||||
#define CAT_MMAPFILE_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class MMapFile
|
||||
{
|
||||
char *data;
|
||||
u32 len;
|
||||
s32 offset;
|
||||
|
||||
#if defined(CAT_OS_LINUX)
|
||||
int fd;
|
||||
#elif defined(CAT_OS_WINDOWS)
|
||||
HANDLE hFile, hMapping;
|
||||
#endif
|
||||
|
||||
public:
|
||||
MMapFile(const char *path);
|
||||
~MMapFile();
|
||||
|
||||
inline bool good() { return data != 0; }
|
||||
inline bool inside() { return offset >= 0 && offset < (s32)len; }
|
||||
|
||||
inline u32 size() { return len; }
|
||||
|
||||
inline void seek(s32 poffset) { offset = poffset; }
|
||||
inline bool underrun(s32 requested) { return (u32)(offset + requested) > len; }
|
||||
inline char *look() { return data + offset; }
|
||||
inline char *look(s32 offset) { return data + offset; }
|
||||
inline char *read(s32 requested) { offset += requested; return data + (offset - requested); }
|
||||
inline void skip(s32 requested) { offset += requested; }
|
||||
inline u32 remaining() { return len - offset; }
|
||||
inline u32 getOffset() { return offset; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_MMAPFILE_HPP
|
||||
107
DependentExtensions/cat/io/PackageManager.hpp
Normal file
107
DependentExtensions/cat/io/PackageManager.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_PACKAGE_MANAGER_HPP
|
||||
#define CAT_PACKAGE_MANAGER_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <cat/port/FastDelegate.h>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Package resource identifier macro
|
||||
#define CAT_UNCAGE(packagePath, offset, size) offset, size
|
||||
|
||||
/*
|
||||
All file resources are packed into one large file and each is
|
||||
assigned a unique identifying number, starting from 0.
|
||||
|
||||
The client source code is preprocessed by a tool that replaces the
|
||||
arguments of the CAT_UNPACK() macro with the correct ID number based
|
||||
on the string given as the first argument.
|
||||
|
||||
CAT_UNPACK("world1/lightmap3.png")
|
||||
-> CAT_UNPACK("world1/lightmap3.png", 15241, 256, 0xdecryptionkey)
|
||||
|
||||
At runtime the client application will not be aware of the string
|
||||
name of a resource in the package, only where to go to get it.
|
||||
|
||||
Resources that are used together during tuning will have identifiers
|
||||
that are close together so that disk seek time is minimized.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Kennel files are simple concatenations of all of the game resources.
|
||||
|
||||
The goal is to reduce access time to data by cutting the operating
|
||||
system's file-system out completely. Furthermore, data that are
|
||||
accessed together are stored together on disk and in the same order
|
||||
that they are accessed.
|
||||
|
||||
Textures are compressed with modified JPEG-LS, providing the fastest
|
||||
possible access time.
|
||||
Sounds compression hasn't been investigated yet.
|
||||
|
||||
Each resource (sound/texture) is obfuscated with a 64-bit key, making
|
||||
it necessary to reverse-engineer the game client to decode in-game
|
||||
resources outside of the game.
|
||||
|
||||
The KennelFile object implements optimized algorithms for performing
|
||||
in-place modification to a large datafile (>4 GB).
|
||||
*/
|
||||
|
||||
class KennelPatchFile : AsyncFile
|
||||
{
|
||||
public:
|
||||
KennelPatchFile();
|
||||
~KennelPatchFile();
|
||||
|
||||
public:
|
||||
void Insert
|
||||
};
|
||||
|
||||
|
||||
// Kennel Patch Callback (param=bool: true on successful patch, false on error)
|
||||
typedef fastdelegate::FastDelegate1<bool, void> KennelPatchCallback;
|
||||
|
||||
class KennelFile : AsyncFile
|
||||
{
|
||||
public:
|
||||
KennelFile();
|
||||
virtual ~KennelFile();
|
||||
|
||||
public:
|
||||
bool Move(u64 dest, u32 region_size, u64 src, KennelPatchCallback OnComplete);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_PACKAGE_MANAGER_HPP
|
||||
117
DependentExtensions/cat/io/Settings.hpp
Normal file
117
DependentExtensions/cat/io/Settings.hpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SETTINGS_HPP
|
||||
#define CAT_SETTINGS_HPP
|
||||
|
||||
#include <cat/Singleton.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
enum SettingsValueFlags
|
||||
{
|
||||
CAT_SETTINGS_FILLED = 1, // s[] array has been set
|
||||
CAT_SETTINGS_INT = 2, // value has been promoted to int 'i'
|
||||
};
|
||||
|
||||
struct SettingsValue
|
||||
{
|
||||
u8 flags; // sum of SettingsValueFlags
|
||||
char s[256]; // always nul-terminated
|
||||
int i;
|
||||
};
|
||||
|
||||
|
||||
class SettingsKey
|
||||
{
|
||||
public:
|
||||
SettingsKey(SettingsKey *lnode, SettingsKey *gnode, const char *name);
|
||||
~SettingsKey();
|
||||
|
||||
public:
|
||||
SettingsKey *lnode, *gnode;
|
||||
|
||||
char name[64]; // not necessarily nul-terminated
|
||||
|
||||
SettingsValue value;
|
||||
|
||||
public:
|
||||
void write(std::ofstream &file);
|
||||
};
|
||||
|
||||
|
||||
// User settings manager
|
||||
class Settings : public Singleton<Settings>
|
||||
{
|
||||
CAT_SINGLETON(Settings);
|
||||
|
||||
Mutex _lock;
|
||||
|
||||
protected:
|
||||
static const u32 KEY_HASH_SALT = 0xbaddecaf;
|
||||
static const int SETTINGS_HASH_BINS = 256;
|
||||
|
||||
SettingsKey *hbtrees[SETTINGS_HASH_BINS]; // hash table of binary trees
|
||||
|
||||
bool readSettings; // Flag set when settings have been read from disk
|
||||
bool modified; // Flag set when settings have been modified since last write
|
||||
|
||||
std::string _settings_file;
|
||||
|
||||
protected:
|
||||
SettingsKey *addKey(const char *name);
|
||||
SettingsKey *getKey(const char *name);
|
||||
|
||||
SettingsKey *initInt(const char *name, int n, bool overwrite);
|
||||
SettingsKey *initStr(const char *name, const char *value, bool overwrite);
|
||||
|
||||
void clear();
|
||||
|
||||
public:
|
||||
void readSettingsFromFile(const char *file_path = "settings.txt", const char *override_file = "override.txt");
|
||||
void readSettingsFromBuffer(const char *data, int len);
|
||||
void write();
|
||||
|
||||
public:
|
||||
int getInt(const char *name);
|
||||
const char *getStr(const char *name);
|
||||
|
||||
int getInt(const char *name, int init);
|
||||
const char *getStr(const char *name, const char *init);
|
||||
|
||||
void setInt(const char *name, int n);
|
||||
void setStr(const char *name, const char *value);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SETTINGS_HPP
|
||||
82
DependentExtensions/cat/io/ThreadPoolFiles.hpp
Normal file
82
DependentExtensions/cat/io/ThreadPoolFiles.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_FILES_HPP
|
||||
#define CAT_THREAD_POOL_FILES_HPP
|
||||
|
||||
#include <cat/threads/ThreadPool.hpp>
|
||||
#include <cat/port/FastDelegate.h>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
enum AsyncFileModes
|
||||
{
|
||||
ASYNCFILE_READ = 1,
|
||||
ASYNCFILE_WRITE = 2,
|
||||
ASYNCFILE_RANDOM = 4
|
||||
};
|
||||
|
||||
class AsyncFile : public ThreadRefObject
|
||||
{
|
||||
HANDLE _file;
|
||||
|
||||
protected:
|
||||
char _file_path[MAX_PATH+1];
|
||||
|
||||
public:
|
||||
AsyncFile(int priorityLevel);
|
||||
virtual ~AsyncFile();
|
||||
|
||||
public:
|
||||
bool Valid();
|
||||
const char *GetFilePath();
|
||||
|
||||
public:
|
||||
/*
|
||||
In read mode, Open() will fail if the file does not exist.
|
||||
In write mode, Open() will create the file if it does not exist.
|
||||
*/
|
||||
bool Open(const char *file_path, u32 async_file_modes);
|
||||
void Close();
|
||||
|
||||
bool SetSize(u64 bytes);
|
||||
u64 GetSize();
|
||||
|
||||
bool Read(AsyncBuffer *buffer, u64 offset, const AsyncCallback &callback);
|
||||
bool Write(AsyncBuffer *buffer, u64 offset, const AsyncCallback &callback = 0);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_FILES_HPP
|
||||
106
DependentExtensions/cat/lang/Strings.hpp
Normal file
106
DependentExtensions/cat/lang/Strings.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_STRINGS_HPP
|
||||
#define CAT_STRINGS_HPP
|
||||
|
||||
/*
|
||||
These are ANSI C String function that do not work with UNICODE, UTF-8, etc.
|
||||
*/
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
#include <string.h> // _stricmp
|
||||
#elif defined(CAT_COMPILER_GCC)
|
||||
#include <strings.h> // strcasecmp
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Convert from signed 32-bit number to string (up to 12 bytes including '\0')
|
||||
int DecToString(s32 x, char *outs);
|
||||
|
||||
|
||||
// iStrEqual(): Returns true if strings match. Case-insensitive
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
|
||||
CAT_INLINE bool iStrEqual(const char *A, const char *B)
|
||||
{
|
||||
return _stricmp(A, B) == 0;
|
||||
}
|
||||
|
||||
#elif defined(CAT_COMPILER_GCC)
|
||||
|
||||
CAT_INLINE bool iStrEqual(const char *A, const char *B)
|
||||
{
|
||||
return strcasecmp(A, B) == 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define CAT_UNKNOWN_BUILTIN_ISTRCMP
|
||||
bool iStrEqual(const char *A, const char *B);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Get length of string that has a maximum length (potentially no trailing nul)
|
||||
u32 GetFixedStrLen(const char *str, u32 max_len);
|
||||
|
||||
|
||||
// Set a fixed string buffer (zero-padded) from a variable-length string,
|
||||
// both either zero or length-terminated. Returns length of copied string
|
||||
u32 SetFixedStr(char *dest, u32 dest_len, const char *src, u32 src_max_len);
|
||||
|
||||
|
||||
// Returns true if buffer contains any non-zero bytes
|
||||
bool IsZeroFixedBuffer(const void *buffer, u32 bytes);
|
||||
|
||||
|
||||
// Replaces all similar-looking glyphs with a common character
|
||||
char DesimilarizeCharacter(char ch);
|
||||
|
||||
// Replaces all similar-looking glyphs with common characters while copying a string
|
||||
void CopyDesimilarizeString(const char *from, char *to);
|
||||
|
||||
// Replaces all similar-looking glyphs with common characters in a fixed string
|
||||
u32 DesimilarizeFixedString(char *str, u32 max_len);
|
||||
|
||||
// Copies the input string to an output string replacing lowercase letters with their uppercase equivalents
|
||||
void CopyToUppercaseString(const char *from, char *to);
|
||||
|
||||
// Copies the input string to an output string replacing uppercase letters with their lowercase equivalents
|
||||
void CopyToLowercaseString(const char *from, char *to);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_STRINGS_HPP
|
||||
BIN
DependentExtensions/cat/lib/cat/big_x64.lib
Normal file
BIN
DependentExtensions/cat/lib/cat/big_x64.lib
Normal file
Binary file not shown.
BIN
DependentExtensions/cat/lib/cat/big_x64.o
Normal file
BIN
DependentExtensions/cat/lib/cat/big_x64.o
Normal file
Binary file not shown.
BIN
DependentExtensions/cat/lib/cat/big_x64.obj
Normal file
BIN
DependentExtensions/cat/lib/cat/big_x64.obj
Normal file
Binary file not shown.
101
DependentExtensions/cat/math/BigMontgomery.hpp
Normal file
101
DependentExtensions/cat/math/BigMontgomery.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Several algorithms based on ideas from the "Handbook of Applied Cryptography"
|
||||
http://www.cacr.math.uwaterloo.ca/hac/
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_MONTGOMERY_HPP
|
||||
#define CAT_BIG_MONTGOMERY_HPP
|
||||
|
||||
#include <cat/math/BigRTL.hpp>
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Performs fast modular arithmetic in the Montgomery Residue Number System
|
||||
class BigMontgomery : public BigRTL
|
||||
{
|
||||
static const int MON_OVERHEAD = 3 + 4;
|
||||
int mon_regs;
|
||||
|
||||
protected:
|
||||
Leg *TempProduct;
|
||||
Leg *TempProductHi;
|
||||
Leg *CachedModulus;
|
||||
Leg mod_inv;
|
||||
|
||||
public:
|
||||
BigMontgomery(int regs, int bits);
|
||||
|
||||
// Must call SetModulus() before using this object
|
||||
void SetModulus(const Leg *mod);
|
||||
|
||||
public:
|
||||
const Leg *GetModulus() { return CachedModulus; }
|
||||
void CopyModulus(Leg *out);
|
||||
|
||||
public:
|
||||
// Convert value in register into RNS, stored in out
|
||||
void MonInput(const Leg *in, Leg *out);
|
||||
|
||||
// Convert value in register from RNS, stored in out
|
||||
void MonOutput(const Leg *in, Leg *out);
|
||||
|
||||
// Note: This will clobber the input product!
|
||||
// Reduce a double-register product to a single register in the RNS
|
||||
void MonReduceProduct(Leg *inout_product, Leg *out);
|
||||
|
||||
public:
|
||||
// Inputs and outputs must be in the Montgomery RNS
|
||||
void MonAdd(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void MonSubtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void MonNegate(const Leg *in, Leg *out);
|
||||
void MonDouble(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Inputs and outputs must be in the Montgomery RNS
|
||||
void MonMultiply(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void MonSquare(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Base must be in the Montgomery RNS. in_base != out
|
||||
void MonExpMod(const Leg *in_base, const Leg *in_exp, Leg *out);
|
||||
|
||||
public:
|
||||
// Input is NOT in the RNS (don't call MonInput)
|
||||
// Probably a prime, certainty = 4^-trials. 20: %99.9999999999 certainty
|
||||
bool IsRabinMillerPrime(IRandom *prng, const Leg *n, int trials = 20);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_MONTGOMERY_HPP
|
||||
95
DependentExtensions/cat/math/BigPseudoMersenne.hpp
Normal file
95
DependentExtensions/cat/math/BigPseudoMersenne.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Several algorithms based on ideas from the "Handbook of Applied Cryptography"
|
||||
http://www.cacr.math.uwaterloo.ca/hac/
|
||||
|
||||
Several algorithms based on ideas from the
|
||||
"Handbook of Elliptic and Hyperelliptic Curve Cryptography"
|
||||
http://www.hyperelliptic.org/HEHCC/
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_PSEUDO_MERSENNE_HPP
|
||||
#define CAT_BIG_PSEUDO_MERSENNE_HPP
|
||||
|
||||
#include <cat/math/BigRTL.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Performs fast arithmetic modulo 2^bits-C, C = 1 (mod 4) or 3 (mod 8), C < 16384
|
||||
class BigPseudoMersenne : public BigRTL
|
||||
{
|
||||
static const int PM_OVERHEAD = 6; // overhead for MrSquareRoot()
|
||||
int pm_regs;
|
||||
|
||||
protected:
|
||||
Leg *CachedModulus;
|
||||
Leg modulus_c;
|
||||
|
||||
void CAT_FASTCALL MrReduceProductX(Leg overflow, Leg *inout);
|
||||
void CAT_FASTCALL MrReduceProduct(const Leg *in_hi, const Leg *in_lo, Leg *out);
|
||||
|
||||
public:
|
||||
BigPseudoMersenne(int regs, int bits, int C);
|
||||
|
||||
public:
|
||||
const Leg *GetModulus() { return CachedModulus; }
|
||||
void CAT_FASTCALL CopyModulus(Leg *out);
|
||||
|
||||
public:
|
||||
// Result may be one modulus too large, so efficiently correct that
|
||||
void CAT_FASTCALL MrReduce(Leg *inout);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrAdd(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void CAT_FASTCALL MrAddX(Leg *inout, Leg x);
|
||||
void CAT_FASTCALL MrSubtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void CAT_FASTCALL MrSubtractX(Leg *inout, Leg x);
|
||||
void CAT_FASTCALL MrNegate(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrDouble(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrMultiply(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void CAT_FASTCALL MrMultiplyX(const Leg *in_a, Leg in_b, Leg *out);
|
||||
void CAT_FASTCALL MrSquare(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrInvert(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MrSquareRoot(const Leg *in, Leg *out);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_PSEUDO_MERSENNE_HPP
|
||||
164
DependentExtensions/cat/math/BigRTL.hpp
Normal file
164
DependentExtensions/cat/math/BigRTL.hpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Several algorithms based on ideas from the "Handbook of Applied Cryptography"
|
||||
http://www.cacr.math.uwaterloo.ca/hac/
|
||||
|
||||
Several algorithms based on ideas from the
|
||||
"Handbook of Elliptic and Hyperelliptic Curve Cryptography"
|
||||
http://www.hyperelliptic.org/HEHCC/
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_RTL_HPP
|
||||
#define CAT_BIG_RTL_HPP
|
||||
|
||||
#include <cat/math/Legs.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Implements a register transfer language (RTL) for big integer arithmetic
|
||||
class BigRTL
|
||||
{
|
||||
static const int BIG_OVERHEAD = 7; // overhead for ModularInverse()
|
||||
int library_regs;
|
||||
|
||||
protected:
|
||||
int library_legs;
|
||||
Leg *library_memory;
|
||||
|
||||
protected:
|
||||
static Leg CAT_FASTCALL ShiftRight(int legs, const Leg *in, int shift, Leg *out);
|
||||
static Leg CAT_FASTCALL ShiftLeft(int legs, const Leg *in, int shift, Leg *out);
|
||||
|
||||
protected:
|
||||
static u8 CAT_FASTCALL Add(int legs, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
static u8 CAT_FASTCALL Add(int legs_a, const Leg *in_a, int legs_b, const Leg *in_b, Leg *out); // legs_b <= legs_a
|
||||
static u8 CAT_FASTCALL Subtract(int legs, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
|
||||
protected:
|
||||
static Leg CAT_FASTCALL MultiplyX(int legs, const Leg *in_a, Leg in_b, Leg *out);
|
||||
static Leg CAT_FASTCALL MultiplyXAdd(int legs, const Leg *in_a, Leg in_b, const Leg *in_c, Leg *out);
|
||||
static Leg CAT_FASTCALL DoubleAdd(int legs, const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
|
||||
protected:
|
||||
static void CAT_FASTCALL DivideCore(int A_used, Leg A_overflow, Leg *A, int B_used, Leg *B, Leg *Q); // A = remainder
|
||||
|
||||
public:
|
||||
BigRTL(int regs, int bits);
|
||||
~BigRTL();
|
||||
|
||||
public:
|
||||
Leg * CAT_FASTCALL Get(int reg_index);
|
||||
CAT_INLINE int Legs() { return library_legs; }
|
||||
CAT_INLINE int RegBytes() { return library_legs * sizeof(Leg); }
|
||||
|
||||
public:
|
||||
// Save one single register to an endian-neutral byte array
|
||||
void CAT_FASTCALL Save(const Leg *in, void *out, int bytes);
|
||||
|
||||
// Load one single register from an endian-neutral byte array
|
||||
void CAT_FASTCALL Load(const void *in, int bytes, Leg *out);
|
||||
|
||||
bool CAT_FASTCALL LoadFromString(const char *in, int base, Leg *out);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL Copy(const Leg *in, Leg *out);
|
||||
void CAT_FASTCALL CopyX(Leg in, Leg *out);
|
||||
|
||||
public:
|
||||
int CAT_FASTCALL LegsUsed(const Leg *in);
|
||||
|
||||
public:
|
||||
bool CAT_FASTCALL Greater(const Leg *in_a, const Leg *in_b);
|
||||
bool CAT_FASTCALL GreaterX(const Leg *in, Leg x);
|
||||
bool CAT_FASTCALL Less(const Leg *in_a, const Leg *in_b);
|
||||
bool CAT_FASTCALL LessX(const Leg *in, Leg x);
|
||||
bool CAT_FASTCALL Equal(const Leg *in_a, const Leg *in_b);
|
||||
bool CAT_FASTCALL EqualX(const Leg *in, Leg x);
|
||||
bool CAT_FASTCALL IsZero(const Leg *in);
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL ShiftLeft(const Leg *in, int shift, Leg *out);
|
||||
void CAT_FASTCALL MoveLegsRight(const Leg *in, int legs, Leg *out);
|
||||
|
||||
public:
|
||||
u8 CAT_FASTCALL Add(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
u8 CAT_FASTCALL AddX(Leg *inout, Leg x);
|
||||
u8 CAT_FASTCALL Subtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
u8 CAT_FASTCALL SubtractX(Leg *inout, Leg x);
|
||||
void CAT_FASTCALL Negate(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
u8 CAT_FASTCALL Double(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Eat all trailing least significant zeroes from the argument and return the number eatten
|
||||
int CAT_FASTCALL EatTrailingZeroes(Leg *inout);
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL MultiplyX(const Leg *in_a, Leg in_b, Leg *out); // out = a[] * b
|
||||
Leg CAT_FASTCALL MultiplyXAdd(const Leg *in_a, Leg in_b, const Leg *in_c, Leg *out); // out = a[] * b + c[]
|
||||
Leg CAT_FASTCALL DoubleAdd(const Leg *in_a, const Leg *in_b, Leg *out); // out = a[] * 2 + b[]
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL MultiplyLow(const Leg *in_a, const Leg *in_b, Leg *out); // out = a[] * b[], low half
|
||||
|
||||
public:
|
||||
// out[] gets the low part of the product, next reg gets high part
|
||||
// note: in_a != out, in_b != out
|
||||
void CAT_FASTCALL Multiply(const Leg *in_a, const Leg *in_b, Leg *out); // out+1:out = a[] * b[]
|
||||
void CAT_FASTCALL Square(const Leg *in, Leg *out); // out+1:out = in[] * in[]
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL DivideX(const Leg *in_a, Leg in_b, Leg *out); // out = a[] / b, returns modulus
|
||||
Leg CAT_FASTCALL ModulusX(const Leg *in_a, Leg in_b); // returns a[] % b
|
||||
|
||||
public:
|
||||
bool CAT_FASTCALL Divide(const Leg *in_a, const Leg *in_b, Leg *out_q, Leg *out_r);
|
||||
|
||||
// Divide the product of two registers (a+1:a) by single register (b)
|
||||
// Resulting quotient is two registers (q+1:q) and remainder is one register (r)
|
||||
bool CAT_FASTCALL DivideProduct(const Leg *in_a, const Leg *in_b, Leg *out_q, Leg *out_r);
|
||||
|
||||
public:
|
||||
// r = a * b (mod m)
|
||||
void CAT_FASTCALL MulMod(const Leg *in_a, const Leg *in_b, const Leg *in_m, Leg *r);
|
||||
|
||||
public:
|
||||
void CAT_FASTCALL ModularInverse(const Leg *x, const Leg *modulus, Leg *inverse);
|
||||
|
||||
public:
|
||||
Leg CAT_FASTCALL MultiplicativeInverseX(Leg x);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_RTL_HPP
|
||||
195
DependentExtensions/cat/math/BigTwistedEdwards.hpp
Normal file
195
DependentExtensions/cat/math/BigTwistedEdwards.hpp
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Addition and doubling formulas using Extended Twisted Edwards coordinates from
|
||||
Hisil<69>Wong<6E>Carter<65>Dawson paper "Twisted Edwards Curves Revisited" (Asiacrypt 2008)
|
||||
|
||||
w-MOF scalar multiplication from http://www.sdl.hitachi.co.jp/crypto/mof/index-e.html
|
||||
|
||||
Scalar multiplication precomputation with "conjugate addition" inspired by
|
||||
Longa-Gebotys paper "Novel Precomputation Schemes for Elliptic Curve Cryptosystems" (2008)
|
||||
*/
|
||||
|
||||
/*
|
||||
Twisted Edwards E(p) Curve: a * x^2 + y^2 = 1 + d * x^2 * y^2, a = -1, p = 2^256 - c, c small
|
||||
|
||||
Edwards coordinates: (X : Y : Z)
|
||||
Extended Edwards coordinates: (X : Y : T : Z), T = XY
|
||||
Edwards to Extended Edwards: (X : Y : Z) -> (XZ : YZ : XY : ZZ)
|
||||
Extended Edwards to Edwards: (X : Y : T : Z) -> (X : Y : Z)
|
||||
|
||||
-(X : Y : T : Z) = (-X : Y : -T : Z)
|
||||
|
||||
Additive Identity element: X = 0
|
||||
|
||||
When Z = 1, a multiplication can be omitted
|
||||
|
||||
Mixing operations for more speed:
|
||||
doubling, doubling -> E = 2E
|
||||
doubling, add -> Ee = 2E, E = Ee + Ee
|
||||
*/
|
||||
|
||||
#ifndef CAT_BIG_TWISTED_EDWARDS_HPP
|
||||
#define CAT_BIG_TWISTED_EDWARDS_HPP
|
||||
|
||||
#include <cat/math/BigPseudoMersenne.hpp>
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
class BigTwistedEdwards : public BigPseudoMersenne
|
||||
{
|
||||
static const int POINT_REGS = 4;
|
||||
static const int XOFF = 0;
|
||||
int YOFF, TOFF, ZOFF, POINT_STRIDE;
|
||||
|
||||
// Point multiplication default window
|
||||
static const int WINDOW_BITS = 6;
|
||||
static const int PRECOMP_POINTS = 1 << (WINDOW_BITS-1);
|
||||
static const int PRECOMP_NEG_OFFSET = PRECOMP_POINTS / 2;
|
||||
|
||||
static const int TE_OVERHEAD = (1 + PRECOMP_POINTS) * POINT_REGS + 9 + POINT_REGS * 2;
|
||||
int te_regs;
|
||||
|
||||
// Local workspace
|
||||
Leg *A, *B, *C, *D, *E, *F, *G, *H, *CurveQ, *Generator;
|
||||
Leg *TempPt;
|
||||
|
||||
protected:
|
||||
Leg curve_d;
|
||||
|
||||
// Simultaneous Add and Subtract for efficient precomputation (A +/- B) in 14M 1D 11a (versus 16M 2D 16a)
|
||||
void PtPrecompAddSub(const Leg *in_a, const Leg *in_b, Leg *sum, Leg *diff, int neg_offset);
|
||||
|
||||
public:
|
||||
BigTwistedEdwards(int regs, int bits, int C, int D, const u8 *Q, const u8 *GenPt);
|
||||
|
||||
int PtLegs() { return Legs() * POINT_REGS; }
|
||||
|
||||
Leg GetCurveD() { return curve_d; }
|
||||
const Leg *GetCurveQ() { return CurveQ; }
|
||||
const Leg *GetGenerator() { return Generator; }
|
||||
|
||||
public:
|
||||
// Unpack an Extended Projective point (X,Y,T,Z) from affine point (x,y)
|
||||
void PtUnpack(Leg *inout);
|
||||
|
||||
// Set a point to the identity
|
||||
void PtIdentity(Leg *inout);
|
||||
|
||||
// Check if the affine point (x,y) is the additive identity x=0
|
||||
bool IsAffineIdentity(const Leg *in);
|
||||
|
||||
public:
|
||||
void PtCopy(const Leg *in, Leg *out);
|
||||
|
||||
// Fill the X coordinate of the point with a random value
|
||||
void PtFillRandomX(IRandom *prng, Leg *out);
|
||||
|
||||
// Generate a random point on the curve that is not part of a small subgroup
|
||||
void PtGenerate(IRandom *prng, Leg *out);
|
||||
|
||||
public:
|
||||
// Solve for Y given the X point on a curve
|
||||
void PtSolveAffineY(Leg *inout);
|
||||
|
||||
// Verify that the point (x,y) exists on the given curve
|
||||
bool PtValidAffine(const Leg *in);
|
||||
|
||||
public:
|
||||
// out(x) = X/Z
|
||||
void SaveAffineX(const Leg *in, void *out_x);
|
||||
|
||||
// out(x,y) = (X/Z,Y/Z)
|
||||
void SaveAffineXY(const Leg *in, void *out_x, void *out_y);
|
||||
|
||||
// out(X,Y) = (X,Y) without attempting to convert to affine from projective
|
||||
void SaveProjectiveXY(const Leg *in, void *out_x, void *out_y);
|
||||
|
||||
// out(X,Y,Z,T) = (in_x,in_y), returns false if the coordinates are invalid
|
||||
bool LoadVerifyAffineXY(const void *in_x, const void *in_y, Leg *out);
|
||||
|
||||
// Compute affine coordinates for (X,Y), set Z=1, and compute T = xy
|
||||
void PtNormalize(const Leg *in, Leg *out);
|
||||
|
||||
public:
|
||||
// Extended Twisted Edwards Negation Formula
|
||||
void PtNegate(const Leg *in, Leg *out);
|
||||
|
||||
// Extended Twisted Edwards Unified Addition Formula (works when both inputs are the same) in 8M 1D 9a
|
||||
void PtEAdd(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void PtAdd(const Leg *in_a, const Leg *in_b, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
// Extended Twisted Edwards Unified Subtraction Formula (works when both inputs are the same) in 8M 1D 9a
|
||||
void PtESubtract(const Leg *in_a, const Leg *in_b, Leg *out);
|
||||
void PtSubtract(const Leg *in_a, const Leg *in_b, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
// Extended Twisted Edwards Dedicated Doubling Formula in 4M 4S 5a
|
||||
void PtEDouble(const Leg *in, Leg *out);
|
||||
void PtDouble(const Leg *in, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
// Extended Twisted Edwards Dedicated Doubling Formula Assuming Z=1, in 4M 3S 4a
|
||||
void PtEDoubleZ1(const Leg *in, Leg *out);
|
||||
void PtDoubleZ1(const Leg *in, Leg *out); // -1M, cannot be followed by PtAdd
|
||||
|
||||
public:
|
||||
// Allocate a table for use with PtMultiplyPrecomp()
|
||||
// Free the table with Aligned::Delete()
|
||||
Leg *PtMultiplyPrecompAlloc(int w);
|
||||
|
||||
// Precompute odd multiples of input point
|
||||
void PtMultiplyPrecomp(const Leg *in, int w, Leg *table);
|
||||
|
||||
public:
|
||||
// Extended Twisted Edwards Scalar Multiplication k*p
|
||||
// Requires precomputation with PtMultiplyPrecomp()
|
||||
// CAN *NOT* BE followed by a Pt[E]Add()
|
||||
void PtMultiply(const Leg *in_precomp, int w, const Leg *in_k, u8 msb_k, Leg *out);
|
||||
|
||||
// Extended Twisted Edwards Scalar Multiplication k*p
|
||||
// Uses default precomputation
|
||||
// CAN *NOT* BE followed by a Pt[E]Add()
|
||||
void PtMultiply(const Leg *in_p, const Leg *in_k, u8 msb_k, Leg *out);
|
||||
|
||||
// A reference multiplier to verify that PtMultiply() is functionally the same
|
||||
void RefMul(const Leg *in_p, const Leg *in_k, u8 msb_k, Leg *out);
|
||||
|
||||
public:
|
||||
// Extended Twisted Edwards Simultaneous Scalar Multiplication k*P + l*Q
|
||||
// Requires precomputation with PtMultiplyPrecomp()
|
||||
// CAN *NOT* BE followed by a Pt[E]Add()
|
||||
void PtSiMultiply(const Leg *precomp_p, const Leg *precomp_q, int w,
|
||||
const Leg *in_k, u8 msb_k, const Leg *in_l, u8 msb_l, Leg *out);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIG_TWISTED_EDWARDS_HPP
|
||||
246
DependentExtensions/cat/math/BitMath.hpp
Normal file
246
DependentExtensions/cat/math/BitMath.hpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BITMATH_HPP
|
||||
#define CAT_BITMATH_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Next highest power of two (e.g. 13 -> 16)
|
||||
CAT_INLINE u32 NextHighestPow2(u32 n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
return n + 1;
|
||||
}
|
||||
CAT_INLINE u64 NextHighestPow2(u64 n)
|
||||
{
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
n |= n >> 4;
|
||||
n |= n >> 8;
|
||||
n |= n >> 16;
|
||||
n |= n >> 32;
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
// Bit Scan Forward (BSF)
|
||||
// Scans from bit 0 to MSB
|
||||
// Undefined when input is zero
|
||||
CAT_INLINE u32 BSF32(u32 x);
|
||||
CAT_INLINE u32 BSF64(u64 x);
|
||||
|
||||
// Bit Scan Reverse (BSR)
|
||||
// Scans from MSB to bit 0
|
||||
// Undefined when input is zero
|
||||
CAT_INLINE u32 BSR32(u32 x);
|
||||
CAT_INLINE u32 BSR64(u64 x);
|
||||
|
||||
// Returns the count of bits set in the input for types up to 128 bits
|
||||
template<typename T> CAT_INLINE T BitCount(T v)
|
||||
{
|
||||
// From Stanford Bit Twiddling Hacks collection
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
|
||||
v = v - ((v >> 1) & (T)~(T)0/3);
|
||||
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);
|
||||
v = (v + (v >> 4)) & (T)~(T)0/255*15;
|
||||
return (T)(v * ((T)~(T)0/255)) >> ((sizeof(v) - 1) * 8);
|
||||
}
|
||||
|
||||
// Reconstruct a 32-bit or 64-bit counter that increments by one each time,
|
||||
// given a truncated sample of its low bits, and the last accepted value of the counter.
|
||||
template<int BITS, typename T> CAT_INLINE T ReconstructCounter(T last_accepted_count, u32 partial_low_bits)
|
||||
{
|
||||
const u32 IV_MSB = (1 << BITS); // BITS < 32
|
||||
const u32 IV_MASK = (IV_MSB - 1);
|
||||
|
||||
s32 diff = partial_low_bits - (u32)(last_accepted_count & IV_MASK);
|
||||
return ((last_accepted_count & ~(T)IV_MASK) | partial_low_bits)
|
||||
- (((IV_MSB >> 1) - (diff & IV_MASK)) & IV_MSB)
|
||||
+ (diff & IV_MSB);
|
||||
}
|
||||
|
||||
|
||||
u32 BSF32(u32 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64) && !defined(CAT_DEBUG)
|
||||
|
||||
u32 index;
|
||||
_BitScanForward((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
BSF eax, [x]
|
||||
CAT_ASM_END
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSFl %1, %%eax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
return BSR32(x ^ (x - 1));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u32 BSR32(u32 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && defined(CAT_WORD_64) && !defined(CAT_DEBUG)
|
||||
|
||||
u32 index;
|
||||
_BitScanReverse((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_INTEL) && defined(CAT_ISA_X86)
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
BSR eax, [x]
|
||||
CAT_ASM_END
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSRl %1, %%eax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
// Adapted from the Stanford Bit Twiddling Hacks collection
|
||||
register u32 shift, r;
|
||||
|
||||
r = (x > 0xFFFF) << 4; x >>= r;
|
||||
shift = (x > 0xFF) << 3; x >>= shift; r |= shift;
|
||||
shift = (x > 0xF) << 2; x >>= shift; r |= shift;
|
||||
shift = (x > 0x3) << 1; x >>= shift; r |= shift;
|
||||
r |= (x >> 1);
|
||||
return r;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u32 BSF64(u64 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && !defined(CAT_DEBUG) && defined(CAT_WORD_64)
|
||||
|
||||
u32 index;
|
||||
_BitScanForward64((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_WORD_64) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSFq %1, %%rax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
return BSR64(x ^ (x - 1));
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u32 BSR64(u64 x)
|
||||
{
|
||||
#if defined(CAT_COMPILER_MSVC) && !defined(CAT_DEBUG) && defined(CAT_WORD_64)
|
||||
|
||||
u32 index;
|
||||
_BitScanReverse64((unsigned long*)&index, x);
|
||||
return index;
|
||||
|
||||
#elif defined(CAT_ASM_ATT) && defined(CAT_WORD_64) && defined(CAT_ISA_X86)
|
||||
|
||||
u32 retval;
|
||||
|
||||
CAT_ASM_BEGIN
|
||||
"BSRq %1, %%rax"
|
||||
: "=a" (retval)
|
||||
: "r" (x)
|
||||
: "cc"
|
||||
CAT_ASM_END
|
||||
|
||||
return retval;
|
||||
|
||||
#else
|
||||
|
||||
// Adapted from the Stanford Bit Twiddling Hacks collection
|
||||
register u32 shift, r;
|
||||
|
||||
r = (x > 0xFFFFFFFF) << 5; x >>= r;
|
||||
shift = (x > 0xFFFF) << 4; x >>= shift; r |= shift;
|
||||
shift = (x > 0xFF) << 3; x >>= shift; r |= shift;
|
||||
shift = (x > 0xF) << 2; x >>= shift; r |= shift;
|
||||
shift = (x > 0x3) << 1; x >>= shift; r |= shift;
|
||||
r |= (u32)(x >> 1);
|
||||
return r;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BITMATH_HPP
|
||||
196
DependentExtensions/cat/math/Legs.hpp
Normal file
196
DependentExtensions/cat/math/Legs.hpp
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_LEGS_HPP
|
||||
#define CAT_LEGS_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
|
||||
#define CAT_LEG_BITS 64
|
||||
#define CAT_USED_BITS(x) BSR64(x) /* does not work if x = 0 */
|
||||
#define CAT_TRAILING_ZEROES(x) BSF64(x) /* does not work if x = 0 */
|
||||
typedef u64 Leg;
|
||||
typedef s64 LegSigned;
|
||||
#if !defined(CAT_COMPILER_MSVC)
|
||||
typedef u128 LegPair;
|
||||
typedef s128 LegPairSigned;
|
||||
# define CAT_LEG_PAIRMUL(A, B) ((LegPair)A * B)
|
||||
#else
|
||||
# define CAT_NO_LEGPAIR
|
||||
#endif
|
||||
|
||||
// If x86-64 and MSVC
|
||||
#if defined(CAT_ISA_X86) && defined(CAT_COMPILER_MSVC)
|
||||
#define CAT_USE_LEGS_ASM64 /* use 64-bit assembly code inner loops */
|
||||
#endif
|
||||
|
||||
#elif defined(CAT_WORD_32)
|
||||
|
||||
#define CAT_LEG_BITS 32
|
||||
#define CAT_USED_BITS(x) BSR32(x) /* does not work if x = 0 */
|
||||
#define CAT_TRAILING_ZEROES(x) BSF32(x) /* does not work if x = 0 */
|
||||
typedef u32 Leg;
|
||||
typedef s32 LegSigned;
|
||||
typedef u64 LegPair;
|
||||
typedef s64 LegPairSigned;
|
||||
|
||||
#if defined(CAT_COMPILER_MSVC)
|
||||
# define CAT_LEG_PAIRMUL(A, B) __emulu(A, B) /* slightly faster in ICC */
|
||||
#else
|
||||
# define CAT_LEG_PAIRMUL(A, B) ((LegPair)A * B)
|
||||
#endif
|
||||
|
||||
#endif // CAT_WORD_32
|
||||
|
||||
// Largest value that can be taken on by a Leg
|
||||
const Leg CAT_LEG_LARGEST = ~(Leg)0;
|
||||
|
||||
// MSB of a leg
|
||||
const Leg CAT_LEG_MSB = (Leg)1 << (CAT_LEG_BITS - 1);
|
||||
|
||||
|
||||
#if defined(CAT_NO_LEGPAIR)
|
||||
|
||||
////
|
||||
// Platforms that do not have LegPair (assumes 64-bit MSVC)
|
||||
////
|
||||
|
||||
|
||||
// p(hi:lo) = A * B
|
||||
#define CAT_LEG_MUL(A, B, p_hi, p_lo) \
|
||||
{ \
|
||||
p_lo = _umul128(A, B, &p_hi); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C
|
||||
#define CAT_LEG_MULADD(A, B, C, p_hi, p_lo) \
|
||||
{ \
|
||||
u64 _C0 = C; \
|
||||
p_lo = _umul128(A, B, &p_hi); \
|
||||
p_hi += ((p_lo += _C0) < _C0); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C + D
|
||||
#define CAT_LEG_MULADD2(A, B, C, D, p_hi, p_lo) \
|
||||
{ \
|
||||
u64 _C0 = C, _D0 = D; \
|
||||
p_lo = _umul128(A, B, &p_hi); \
|
||||
p_hi += ((p_lo += _C0) < _C0); \
|
||||
p_hi += ((p_lo += _D0) < _D0); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C1:C0)
|
||||
#define CAT_LEG_COMBA2(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
u64 _p_hi, _p_lo; \
|
||||
_p_lo = _umul128(A, B, &_p_hi); \
|
||||
_p_hi += ((C0 += _p_lo) < _p_lo); \
|
||||
C2 = ((C1 += _p_hi) < _p_hi); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C2:C1:C0)
|
||||
#define CAT_LEG_COMBA3(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
u64 _p_hi, _p_lo; \
|
||||
_p_lo = _umul128(A, B, &_p_hi); \
|
||||
_p_hi += ((C0 += _p_lo) < _p_lo); \
|
||||
C2 += ((C1 += _p_hi) < _p_hi); \
|
||||
}
|
||||
|
||||
|
||||
#else // has LegPair
|
||||
|
||||
////
|
||||
// Platforms that have LegPair (assumes 32-bit MSVC or any-bit GCC)
|
||||
////
|
||||
|
||||
|
||||
// p(hi:lo) = A * B
|
||||
#define CAT_LEG_MUL(A, B, p_hi, p_lo) \
|
||||
{ \
|
||||
LegPair _mt = CAT_LEG_PAIRMUL(A, B); \
|
||||
(p_lo) = (Leg)_mt; \
|
||||
(p_hi) = (Leg)(_mt >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C
|
||||
#define CAT_LEG_MULADD(A, B, C, p_hi, p_lo) \
|
||||
{ \
|
||||
LegPair _mt = CAT_LEG_PAIRMUL(A, B) + (Leg)(C); \
|
||||
(p_lo) = (Leg)_mt; \
|
||||
(p_hi) = (Leg)(_mt >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(hi:lo) = A * B + C + D
|
||||
#define CAT_LEG_MULADD2(A, B, C, D, p_hi, p_lo) \
|
||||
{ \
|
||||
LegPair _mt = CAT_LEG_PAIRMUL(A, B) + (Leg)(C) + (Leg)(D); \
|
||||
(p_lo) = (Leg)_mt; \
|
||||
(p_hi) = (Leg)(_mt >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C1:C0)
|
||||
#define CAT_LEG_COMBA2(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
LegPair _cp = CAT_LEG_PAIRMUL(A, B) + (C0); \
|
||||
(C0) = (Leg)_cp; \
|
||||
_cp = (_cp >> CAT_LEG_BITS) + (C1); \
|
||||
(C1) = (Leg)_cp; \
|
||||
(C2) = (Leg)(_cp >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// p(C2:C1:C0) = A * B + (C2:C1:C0)
|
||||
#define CAT_LEG_COMBA3(A, B, C0, C1, C2) \
|
||||
{ \
|
||||
LegPair _cp = CAT_LEG_PAIRMUL(A, B) + (C0); \
|
||||
(C0) = (Leg)_cp; \
|
||||
_cp = (_cp >> CAT_LEG_BITS) + (C1); \
|
||||
(C1) = (Leg)_cp; \
|
||||
(C2) += (Leg)(_cp >> CAT_LEG_BITS); \
|
||||
}
|
||||
|
||||
// Q(hi:lo) = A(hi:lo) / B
|
||||
#define CAT_LEG_DIV(A_hi, A_lo, B, Q_hi, Q_lo) \
|
||||
{ \
|
||||
LegPair _Ax = ((LegPair)(A_hi) << CAT_LEG_BITS) | (Leg)(A_lo); \
|
||||
LegPair _qt = (LegPair)(_Ax / (B)); \
|
||||
(Q_hi) = (Leg)(_qt >> CAT_LEG_BITS); \
|
||||
(Q_lo) = (Leg)_qt; \
|
||||
}
|
||||
|
||||
#endif // CAT_NO_LEGPAIR
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_LEGS_HPP
|
||||
191
DependentExtensions/cat/net/DNSClient.hpp
Normal file
191
DependentExtensions/cat/net/DNSClient.hpp
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// TODO: React to timeouts from DNS server by switching to a backup
|
||||
// TODO: Use TTL from DNS record instead of fixed constant
|
||||
// TODO: If the DNS resolution load is high, it would make sense to put
|
||||
// multiple requests in the same DNS packet
|
||||
// TODO: Retransmissions could also be grouped into the same DNS packets
|
||||
// TODO: The locks held in DNSClient are fairly coarse and could be broken up
|
||||
|
||||
#ifndef CAT_DNS_CLIENT_HPP
|
||||
#define CAT_DNS_CLIENT_HPP
|
||||
|
||||
#include <cat/net/ThreadPoolSockets.hpp>
|
||||
#include <cat/threads/Thread.hpp>
|
||||
#include <cat/threads/WaitableFlag.hpp>
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
#include <cat/port/FastDelegate.h>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
static const int HOSTNAME_MAXLEN = 63; // Max characters in a hostname request
|
||||
static const int DNSREQ_TIMEOUT = 3000; // DNS request timeout interval
|
||||
static const int DNSREQ_REPOST_TIME = 300; // Number of milliseconds between retries
|
||||
static const int DNSREQ_MAX_SIMUL = 2048; // Maximum number of simultaneous DNS requests
|
||||
static const int DNSCACHE_MAX_REQS = 8; // Maximum number of requests to cache
|
||||
static const int DNSCACHE_MAX_RESP = 8; // Maximum number of responses to cache
|
||||
static const int DNSCACHE_TIMEOUT = 60000; // Time until a cached response is dropped
|
||||
|
||||
// Prototype: bool MyResultCallback(const char *, const NetAddr*, int);
|
||||
typedef fastdelegate::FastDelegate3<const char *, const NetAddr*, int, bool> DNSResultCallback;
|
||||
|
||||
|
||||
//// DNSRequest
|
||||
|
||||
struct DNSCallback
|
||||
{
|
||||
DNSCallback *next;
|
||||
|
||||
DNSResultCallback cb;
|
||||
ThreadRefObject *ref;
|
||||
};
|
||||
|
||||
struct DNSRequest
|
||||
{
|
||||
DNSRequest *last, *next;
|
||||
|
||||
u32 first_post_time; // Timestamp for first post, for timeout
|
||||
u32 last_post_time; // Timestamp for last post, for retries and cache
|
||||
|
||||
// Our copy of the hostname string
|
||||
char hostname[HOSTNAME_MAXLEN+1];
|
||||
u16 id; // Random request ID
|
||||
DNSCallback callback_head;
|
||||
|
||||
// For caching purposes
|
||||
NetAddr responses[DNSCACHE_MAX_RESP];
|
||||
int num_responses;
|
||||
};
|
||||
|
||||
|
||||
//// DNSClient
|
||||
|
||||
class DNSClient : Thread, public UDPEndpoint, public Singleton<DNSClient>
|
||||
{
|
||||
static const int TICK_RATE = 200; // milliseconds
|
||||
static const int DNS_THREAD_KILL_TIMEOUT = 10000; // 10 seconds
|
||||
|
||||
CAT_SINGLETON(DNSClient)
|
||||
: UDPEndpoint(REFOBJ_PRIO_0+5)
|
||||
{
|
||||
_server_addr.Invalidate();
|
||||
_dns_unavailable = true;
|
||||
|
||||
_cache_head = _cache_tail = 0;
|
||||
_cache_size = 0;
|
||||
|
||||
_request_head = _request_tail = 0;
|
||||
_request_queue_size = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~DNSClient();
|
||||
|
||||
/*
|
||||
In your startup code, call Initialize() and check the return value.
|
||||
In your shutdown code, call Shutdown(). This will delete the DNSClient object.
|
||||
*/
|
||||
bool Initialize();
|
||||
void Shutdown();
|
||||
|
||||
/*
|
||||
If hostname is numeric or in the cache, the callback function will be invoked
|
||||
immediately from the requesting thread, rather than from another thread.
|
||||
|
||||
First attempts numerical resolve of hostname, then queries the DNS server.
|
||||
|
||||
Hostname string length limited to HOSTNAME_MAXLEN characters.
|
||||
Caches the most recent DNSCACHE_MAX_REQS requests.
|
||||
Returns up to DNSCACHE_MAX_RESP addresses per resolve request.
|
||||
Performs DNS lookup on a cached request after DNSCACHE_TIMEOUT.
|
||||
Gives up on DNS lookup after DNSREQ_TIMEOUT.
|
||||
|
||||
If holdRef is valid, the reference will be held until the callback completes.
|
||||
|
||||
If no results were found, array_length == 0.
|
||||
If the callback returns false, the result will not be entered into the cache.
|
||||
|
||||
The resolved addresses may need to be promoted to IPv6.
|
||||
|
||||
If Resolve() returns false, no callback will be generated.
|
||||
*/
|
||||
bool Resolve(const char *hostname, DNSResultCallback, ThreadRefObject *holdRef = 0);
|
||||
|
||||
private:
|
||||
NetAddr _server_addr;
|
||||
volatile bool _dns_unavailable;
|
||||
FortunaOutput *_csprng;
|
||||
|
||||
private:
|
||||
Mutex _request_lock;
|
||||
DNSRequest *_request_head;
|
||||
DNSRequest *_request_tail;
|
||||
int _request_queue_size;
|
||||
|
||||
bool GetUnusedID(u16 &id); // not thread-safe, caller must lock
|
||||
bool IsValidHostname(const char *hostname);
|
||||
DNSRequest *PullRequest(u16 id); // not thread-safe, caller must lock
|
||||
|
||||
private:
|
||||
Mutex _cache_lock;
|
||||
DNSRequest *_cache_head;
|
||||
DNSRequest *_cache_tail;
|
||||
int _cache_size;
|
||||
|
||||
// These functions do not lock, caller must lock:
|
||||
void CacheAdd(DNSRequest *req); // Assumes not already in cache
|
||||
DNSRequest *CacheGet(const char *hostname); // Case-insensitive
|
||||
void CacheKill(DNSRequest *req); // Assumes already in cache
|
||||
|
||||
private:
|
||||
bool GetServerAddr();
|
||||
bool BindToRandomPort(bool ignoreUnreachable);
|
||||
bool PostDNSPacket(DNSRequest *req, u32 now);
|
||||
bool PerformLookup(DNSRequest *req); // not thread-safe, caller must lock
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &src, u8 *data, u32 bytes);
|
||||
virtual void OnClose();
|
||||
virtual void OnUnreachable(const NetAddr &src);
|
||||
|
||||
protected:
|
||||
void ProcessDNSResponse(DNSRequest *req, int qdcount, int ancount, u8 *data, u32 bytes);
|
||||
void NotifyRequesters(DNSRequest *req);
|
||||
|
||||
private:
|
||||
WaitableFlag _kill_flag;
|
||||
|
||||
bool ThreadFunction(void *param);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_DNS_CLIENT_HPP
|
||||
188
DependentExtensions/cat/net/Sockets.hpp
Normal file
188
DependentExtensions/cat/net/Sockets.hpp
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SOCKETS_HPP
|
||||
#define CAT_SOCKETS_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <string>
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
# include <WS2tcpip.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define CAT_IP4_LOOPBACK "127.0.0.1"
|
||||
#define CAT_IP6_LOOPBACK "::1"
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// Data Types
|
||||
|
||||
#if defined(CAT_OS_WINDOWS)
|
||||
typedef SOCKET Socket;
|
||||
CAT_INLINE bool CloseSocket(Socket s) { return !closesocket(s); }
|
||||
#else
|
||||
typedef int Socket;
|
||||
static const Socket INVALID_SOCKET = -1;
|
||||
static const int SOCKET_ERROR = -1;
|
||||
CAT_INLINE bool CloseSocket(Socket s) { return !close(s); }
|
||||
#endif
|
||||
|
||||
typedef u16 Port;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
// Wrapper for IPv4 and IPv6 addresses
|
||||
class NetAddr
|
||||
{
|
||||
union
|
||||
{
|
||||
u8 v6_bytes[16];
|
||||
u16 v6_words[8];
|
||||
u64 v6[2];
|
||||
struct {
|
||||
u32 v4;
|
||||
u32 v4_padding[3];
|
||||
};
|
||||
} _ip; // Network order
|
||||
|
||||
union
|
||||
{
|
||||
u32 _valid;
|
||||
struct {
|
||||
Port _port; // Host order
|
||||
u16 _family; // Host order
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
static const int IP4_BYTES = 4;
|
||||
static const int IP6_BYTES = 16;
|
||||
|
||||
typedef sockaddr_in6 SockAddr;
|
||||
|
||||
public:
|
||||
CAT_INLINE NetAddr() {}
|
||||
NetAddr(const char *ip_str, Port port = 0);
|
||||
NetAddr(const sockaddr_in6 &addr);
|
||||
NetAddr(const sockaddr_in &addr);
|
||||
NetAddr(const sockaddr *addr);
|
||||
NetAddr(int a, int b, int c, int d, Port port = 0);
|
||||
|
||||
public:
|
||||
NetAddr(const NetAddr &addr);
|
||||
NetAddr &operator=(const NetAddr &addr);
|
||||
|
||||
public:
|
||||
bool Wrap(const sockaddr_in6 &addr);
|
||||
bool Wrap(const sockaddr_in &addr);
|
||||
bool Wrap(const sockaddr *addr);
|
||||
|
||||
public:
|
||||
// Promote an IPv4 address to an IPv6 address if needed
|
||||
bool PromoteTo6();
|
||||
|
||||
// Demote an IPv6 address to an IPv4 address if possible,
|
||||
// otherwise marks address as invalid and returns false
|
||||
bool DemoteTo4();
|
||||
|
||||
CAT_INLINE bool Convert(bool To6) { if (To6) return PromoteTo6(); else return DemoteTo4(); }
|
||||
|
||||
public:
|
||||
CAT_INLINE bool Valid() const { return _valid != 0; }
|
||||
CAT_INLINE bool Is6() const { return _family == AF_INET6; }
|
||||
|
||||
CAT_INLINE const u32 GetIP4() const { return _ip.v4; }
|
||||
CAT_INLINE const u64 *GetIP6() const { return _ip.v6; }
|
||||
|
||||
CAT_INLINE Port GetPort() const { return _port; }
|
||||
CAT_INLINE void SetPort(Port port) { _port = port; }
|
||||
|
||||
// Mark the address as invalid
|
||||
CAT_INLINE void Invalidate() { _valid = 0; }
|
||||
|
||||
public:
|
||||
bool EqualsIPOnly(const NetAddr &addr) const;
|
||||
bool operator==(const NetAddr &addr) const;
|
||||
bool operator!=(const NetAddr &addr) const;
|
||||
|
||||
public:
|
||||
// To validate external input; don't want clients connecting
|
||||
// to their local network instead of the actual game server.
|
||||
bool IsInternetRoutable();
|
||||
|
||||
// Returns true if the address is routable on local network or Internet.
|
||||
// Returns false if the address is IPv4 multicast, loopback, or weird.
|
||||
bool IsRoutable();
|
||||
|
||||
public:
|
||||
bool SetFromString(const char *ip_str, Port port = 0);
|
||||
std::string IPToString() const;
|
||||
|
||||
bool SetFromRawIP(const u8 *ip_binary, int bytes);
|
||||
bool SetFromDotDecimals(int a, int b, int c, int d, Port port = 0);
|
||||
|
||||
public:
|
||||
bool Unwrap(SockAddr &addr, int &addr_len, bool PromoteToIP6 = false) const;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
//// Helper Functions
|
||||
|
||||
// Run startup and cleanup functions needed under some OS
|
||||
bool StartupSockets(); // returns false on error
|
||||
void CleanupSockets();
|
||||
|
||||
// inout_OnlyIPv4: Indicates that only IPv4 is requested by caller
|
||||
// Sets OnlyIPv4 if IPv6 will be unsupported
|
||||
// Returns true on success
|
||||
bool CreateSocket(int type, int protocol, bool SupportIPv4, Socket &out_s, bool &inout_OnlyIPv4);
|
||||
|
||||
// Returns true on success
|
||||
bool NetBind(Socket s, Port port, bool OnlyIPv4);
|
||||
|
||||
// Returns 0 on failure
|
||||
Port GetBoundPort(Socket s);
|
||||
|
||||
|
||||
//// Error Codes
|
||||
|
||||
// Returns a string describing the last error from Winsock2 API
|
||||
std::string SocketGetLastErrorString();
|
||||
std::string SocketGetErrorString(int code);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SOCKETS_HPP
|
||||
116
DependentExtensions/cat/net/SphynxClient.hpp
Normal file
116
DependentExtensions/cat/net/SphynxClient.hpp
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SPHYNX_CLIENT_HPP
|
||||
#define CAT_SPHYNX_CLIENT_HPP
|
||||
|
||||
#include <cat/net/SphynxTransport.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreementInitiator.hpp>
|
||||
#include <cat/threads/Thread.hpp>
|
||||
#include <cat/threads/WaitableFlag.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
namespace sphynx {
|
||||
|
||||
|
||||
//// sphynx::Client
|
||||
|
||||
class Client : Thread, public UDPEndpoint, public Transport
|
||||
{
|
||||
static const int HANDSHAKE_TICK_RATE = 100; // milliseconds
|
||||
static const int INITIAL_HELLO_POST_INTERVAL = 200; // milliseconds
|
||||
static const int CONNECT_TIMEOUT = 6000; // milliseconds
|
||||
static const u32 MTU_PROBE_INTERVAL = 8000; // 8 seconds
|
||||
static const int CLIENT_THREAD_KILL_TIMEOUT = 10000; // 10 seconds
|
||||
|
||||
static const int SESSION_KEY_BYTES = 32;
|
||||
char _session_key[SESSION_KEY_BYTES];
|
||||
|
||||
KeyAgreementInitiator _key_agreement_initiator;
|
||||
u8 _server_public_key[PUBLIC_KEY_BYTES];
|
||||
u8 _cached_challenge[CHALLENGE_BYTES];
|
||||
|
||||
WaitableFlag _kill_flag;
|
||||
|
||||
protected:
|
||||
u32 _last_send_mstsc;
|
||||
NetAddr _server_addr;
|
||||
bool _connected;
|
||||
AuthenticatedEncryption _auth_enc;
|
||||
|
||||
// Last time a packet was received from the server -- for disconnect timeouts
|
||||
u32 _last_recv_tsc;
|
||||
|
||||
public:
|
||||
Client();
|
||||
virtual ~Client();
|
||||
|
||||
bool SetServerKey(ThreadPoolLocalStorage *tls, const void *server_key, int key_bytes, const char *session_key);
|
||||
|
||||
bool Connect(const char *hostname, Port port);
|
||||
bool Connect(const NetAddr &addr);
|
||||
|
||||
void Disconnect();
|
||||
|
||||
protected:
|
||||
bool IsConnected() { return _connected; }
|
||||
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnConnectFail() = 0;
|
||||
virtual void OnConnect(ThreadPoolLocalStorage *tls) = 0;
|
||||
virtual void OnTimestampDeltaUpdate(u32 rtt, s32 delta) {}
|
||||
virtual void OnMessage(ThreadPoolLocalStorage *tls, BufferStream msg, u32 bytes) = 0;
|
||||
virtual void OnDisconnect() = 0;
|
||||
virtual void OnTick(ThreadPoolLocalStorage *tls, u32 now) = 0;
|
||||
|
||||
private:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &src, u8 *data, u32 bytes);
|
||||
virtual void OnWrite(u32 bytes);
|
||||
|
||||
private:
|
||||
bool PostHello();
|
||||
void OnUnreachable(const NetAddr &src);
|
||||
|
||||
// Return false to remove resolve from cache
|
||||
bool OnResolve(const char *hostname, const NetAddr *array, int array_length);
|
||||
|
||||
virtual bool PostPacket(u8 *buffer, u32 buf_bytes, u32 msg_bytes, u32 skip_bytes);
|
||||
|
||||
private:
|
||||
bool ThreadFunction(void *param);
|
||||
};
|
||||
|
||||
|
||||
} // namespace sphynx
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SPHYNX_CLIENT_HPP
|
||||
706
DependentExtensions/cat/net/SphynxCollexion.hpp
Normal file
706
DependentExtensions/cat/net/SphynxCollexion.hpp
Normal file
@ -0,0 +1,706 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SPHYNX_COLLEXION_HPP
|
||||
#define CAT_SPHYNX_COLLEXION_HPP
|
||||
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
#include <cat/threads/RegionAllocator.hpp>
|
||||
#include <cat/net/SphynxTransport.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
namespace sphynx {
|
||||
|
||||
|
||||
/*
|
||||
The purpose of sphynx::Collexion and sphynx::CollexionIterator is to
|
||||
store lists of Connexion object references and iterate through them.
|
||||
|
||||
Since the number of clients may be in the thousands, I feel it is
|
||||
important to scale effectively. So in the Collexion data structure,
|
||||
insertion and removal are O(1) operations. Also locks should be held
|
||||
for the smallest amount of time possible, so I have taken care to make
|
||||
locks short and reduce the amount of locking. For example, the iterator
|
||||
caches large blocks of data instead of locking for each iteration.
|
||||
|
||||
The design is optimized for cache usage, re-using common code to benefit
|
||||
from code cache and allocating and accessing table entries on cache line
|
||||
boundaries to double memory performance over a naive approach.
|
||||
*/
|
||||
|
||||
|
||||
//// sphynx::Collexion
|
||||
|
||||
template<class T>
|
||||
class CollexionIterator;
|
||||
|
||||
template<class T>
|
||||
struct CollexionElement
|
||||
{
|
||||
// Number of active enumerators using this element
|
||||
// If references are held it cannot be deleted
|
||||
// so the KILL flag is set on the 'next' member and
|
||||
// the final enumerator to reduce the reference count
|
||||
// to zero is responsible for removal.
|
||||
u32 refcnt;
|
||||
|
||||
// Bitfield:
|
||||
// 1 bit: COLLISION FLAG
|
||||
// 1 bit: KILL FLAG
|
||||
// 30 bits: Table index to next element in list + 1
|
||||
u32 next;
|
||||
|
||||
// Data at this table element
|
||||
T *conn;
|
||||
};
|
||||
|
||||
struct CollexionElement2
|
||||
{
|
||||
// Previous table element in list + 1
|
||||
u32 last;
|
||||
|
||||
// Hash of data pointer from main entry (so it doesn't need to be recalculated during growth)
|
||||
u32 hash;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class Collexion
|
||||
{
|
||||
static const u32 COLLIDE_MASK = 0x80000000;
|
||||
static const u32 KILL_MASK = 0x40000000;
|
||||
static const u32 NEXT_MASK = 0x3fffffff;
|
||||
static const u32 MIN_ALLOCATED = 32;
|
||||
|
||||
private:
|
||||
// Number of used table elements
|
||||
u32 _used;
|
||||
|
||||
// Number of allocated table elements
|
||||
u32 _allocated;
|
||||
|
||||
// First table index in list of active elements
|
||||
u32 _first;
|
||||
|
||||
// Primary table
|
||||
CollexionElement<T> *_table;
|
||||
|
||||
// Secondary table, split off so that primary table elements will
|
||||
// fit on a cache line. Contains data that is only accessed rarely.
|
||||
CollexionElement2 *_table2;
|
||||
|
||||
// Table lock
|
||||
Mutex _lock;
|
||||
|
||||
protected:
|
||||
// Attempt to double size of hash table (does not hold lock)
|
||||
bool DoubleTable();
|
||||
|
||||
// Hash a pointer to a 32-bit table key
|
||||
static CAT_INLINE u32 HashPtr(T *ptr)
|
||||
{
|
||||
u64 key = 0xBADdecafDEADbeef;
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
key ^= *(u64*)&ptr;
|
||||
#else
|
||||
key ^= *(u32*)&ptr;
|
||||
#endif
|
||||
|
||||
key = (~key) + (key << 18);
|
||||
key = key ^ (key >> 31);
|
||||
key = key * 21;
|
||||
key = key ^ (key >> 11);
|
||||
key = key + (key << 6);
|
||||
key = key ^ (key >> 22);
|
||||
return (u32)key;
|
||||
}
|
||||
|
||||
// Common functions shared by interface for good code cache usage:
|
||||
|
||||
// Unlink a table key
|
||||
void Unlink(u32 key);
|
||||
|
||||
// Fill an iterator with the next set of data
|
||||
// Returns false if no data remains to fill
|
||||
void Fill(CollexionIterator<T> &iter, u32 first);
|
||||
|
||||
// Find a hash table key based on data
|
||||
u32 Find(T *conn);
|
||||
|
||||
public:
|
||||
// Ctor zeros everything
|
||||
Collexion()
|
||||
{
|
||||
_first = 0;
|
||||
_used = 0;
|
||||
_allocated = 0;
|
||||
_table = 0;
|
||||
_table2 = 0;
|
||||
}
|
||||
|
||||
// Dtor releases dangling memory
|
||||
~Collexion();
|
||||
|
||||
// Returns true if table is empty
|
||||
CAT_INLINE bool IsEmpty() { return _used == 0; }
|
||||
|
||||
// Insert Connexion object, return false if already present or out of memory
|
||||
bool Insert(T *conn);
|
||||
|
||||
// Remove Connexion object from list if it exists
|
||||
bool Remove(T *conn);
|
||||
|
||||
// Begin iterating through list
|
||||
void Begin(CollexionIterator<T> &iter);
|
||||
|
||||
// Iterate
|
||||
void Next(CollexionIterator<T> &iter, bool refill = true);
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::CollexionIterator
|
||||
|
||||
template<class T>
|
||||
class CollexionIterator
|
||||
{
|
||||
friend class Collexion<T>;
|
||||
|
||||
static const u32 MAX_CACHE = 256;
|
||||
|
||||
// Parent Collexion object
|
||||
Collexion<T> *_parent;
|
||||
|
||||
// First and last hash table indices in parent
|
||||
u32 _first, _last;
|
||||
|
||||
// Stores the size of the parent when snapshot was taken,
|
||||
// will invalidate _first and _last if table changed size
|
||||
u32 _prev_allocated;
|
||||
|
||||
// Connexion object cache, to avoid locking and unlocking a lot
|
||||
T *_cache[MAX_CACHE];
|
||||
|
||||
// Offset into cache and total elements in cache
|
||||
// Will grab another cache once offset reaches total
|
||||
u32 _offset, _total;
|
||||
|
||||
public:
|
||||
// Smart pointer -style accessors
|
||||
CAT_INLINE T *Get() throw() { return _cache[_offset]; }
|
||||
CAT_INLINE T *operator->() throw() { return _cache[_offset]; }
|
||||
CAT_INLINE T &operator*() throw() { return *_cache[_offset]; }
|
||||
CAT_INLINE operator T*() { return _cache[_offset]; }
|
||||
|
||||
public:
|
||||
// Ctor: Grabs first cache of Connexions
|
||||
CollexionIterator(Collexion<T> &begin);
|
||||
|
||||
// Dtor: Calls Release()
|
||||
~CollexionIterator();
|
||||
|
||||
// Iterate to next Connexion object in list
|
||||
CollexionIterator &operator++();
|
||||
|
||||
// Releases reference to any outstanding Connexions
|
||||
void Release();
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::Collexion
|
||||
|
||||
template<class T>
|
||||
bool Collexion<T>::DoubleTable()
|
||||
{
|
||||
u32 new_allocated = _allocated << 1;
|
||||
if (new_allocated < MIN_ALLOCATED) new_allocated = MIN_ALLOCATED;
|
||||
|
||||
// Allocate secondary table
|
||||
u32 new_bytes2 = sizeof(CollexionElement2) * new_allocated;
|
||||
CollexionElement2 *new_table2 = reinterpret_cast<CollexionElement2*>(
|
||||
RegionAllocator::ii->Acquire(new_bytes2) );
|
||||
|
||||
if (!new_table2) return false;
|
||||
|
||||
// Allocate primary table
|
||||
u32 new_bytes = sizeof(CollexionElement<T>) * new_allocated;
|
||||
CollexionElement<T> *new_table = reinterpret_cast<CollexionElement<T> *>(
|
||||
RegionAllocator::ii->Acquire(new_bytes) );
|
||||
|
||||
if (!new_table)
|
||||
{
|
||||
RegionAllocator::ii->Release(new_table2);
|
||||
return false;
|
||||
}
|
||||
|
||||
CAT_CLR(new_table, new_bytes);
|
||||
|
||||
u32 new_first = 0;
|
||||
|
||||
if (_table && _table2)
|
||||
{
|
||||
// For each entry in the old table,
|
||||
u32 ii = _first, mask = _allocated - 1;
|
||||
|
||||
while (ii)
|
||||
{
|
||||
--ii;
|
||||
CollexionElement<T> *oe = &_table[ii];
|
||||
u32 hash = _table2[ii].hash;
|
||||
u32 key = hash & mask;
|
||||
|
||||
// While collisions occur,
|
||||
while (new_table[key].conn)
|
||||
{
|
||||
// Mark collision
|
||||
new_table[key].next |= COLLIDE_MASK;
|
||||
|
||||
// Walk collision list
|
||||
key = (key * COLLISION_MULTIPLIER + COLLISION_INCREMENTER) & mask;
|
||||
}
|
||||
|
||||
// Fill new table element
|
||||
new_table[key].conn = oe->conn;
|
||||
new_table2[key].hash = hash;
|
||||
// new_table[key].refcnt is already zero
|
||||
|
||||
// Link new element to new list
|
||||
if (new_first)
|
||||
{
|
||||
new_table[key].next |= new_first;
|
||||
new_table2[new_first - 1].last = key;
|
||||
}
|
||||
// new_table[key].next is already zero so no need to zero it here
|
||||
new_first = key + 1;
|
||||
|
||||
// Get next old table entry
|
||||
ii = oe->next & NEXT_MASK;
|
||||
}
|
||||
|
||||
// Zero head->last
|
||||
new_table2[new_first - 1].last = 0;
|
||||
}
|
||||
|
||||
// Resulting linked list starting with _first-1 will extend until e->next == 0
|
||||
|
||||
if (_table2) RegionAllocator::ii->Release(_table2);
|
||||
if (_table) RegionAllocator::ii->Release(_table);
|
||||
|
||||
_table = new_table;
|
||||
_table2 = new_table2;
|
||||
_allocated = new_allocated;
|
||||
_first = new_first;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
Collexion<T>::~Collexion()
|
||||
{
|
||||
if (_table2)
|
||||
{
|
||||
RegionAllocator::ii->Release(_table2);
|
||||
}
|
||||
|
||||
// If table doesn't exist, return
|
||||
if (!_table) return;
|
||||
|
||||
// For each allocated table entry,
|
||||
for (u32 ii = 0; ii < _allocated; ++ii)
|
||||
{
|
||||
// Get Connexion object
|
||||
T *conn = _table[ii].conn;
|
||||
|
||||
// If object is valid, release it
|
||||
if (conn) conn->ReleaseRef();
|
||||
}
|
||||
|
||||
// Release table memory
|
||||
RegionAllocator::ii->Release(_table);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool Collexion<T>::Insert(T *conn)
|
||||
{
|
||||
u32 hash = HashPtr(conn);
|
||||
conn->AddRef();
|
||||
|
||||
AutoMutex lock(_lock);
|
||||
|
||||
// If more than half of the table will be used,
|
||||
if (_used >= (_allocated >> 1))
|
||||
{
|
||||
// Double the size of the table (O(1) allocation pattern)
|
||||
// Growing pains are softened by careful design
|
||||
if (!DoubleTable())
|
||||
{
|
||||
// On growth failure, return false
|
||||
lock.Release();
|
||||
|
||||
conn->ReleaseRef();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Mask off high bits to make table key from hash
|
||||
u32 mask = _allocated - 1;
|
||||
u32 key = hash & mask;
|
||||
|
||||
// While empty table entry not found,
|
||||
while (_table[key].conn)
|
||||
{
|
||||
// If Connexion object is already in the table,
|
||||
if (_table[key].conn == conn)
|
||||
{
|
||||
// Return false on duplicate
|
||||
lock.Release();
|
||||
|
||||
conn->ReleaseRef();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark as a collision
|
||||
_table[key].next |= COLLIDE_MASK;
|
||||
|
||||
// Walk collision list
|
||||
key = (key * COLLISION_MULTIPLIER + COLLISION_INCREMENTER) & mask;
|
||||
}
|
||||
|
||||
// Fill new element
|
||||
_table[key].conn = conn;
|
||||
_table[key].refcnt = 0;
|
||||
_table2[key].hash = hash;
|
||||
_table2[key].last = 0;
|
||||
|
||||
// Link new element to front of list
|
||||
if (_first) _table2[_first - 1].last = key + 1;
|
||||
_table[key].next = (_table[key].next & COLLIDE_MASK) | _first;
|
||||
_first = key + 1;
|
||||
|
||||
++_used;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Collexion<T>::Unlink(u32 key)
|
||||
{
|
||||
// Clear reference
|
||||
_table[key].conn = 0;
|
||||
|
||||
// Unlink from active list
|
||||
u32 next = _table[key].next & NEXT_MASK;
|
||||
u32 last = _table2[key].last;
|
||||
|
||||
if (last) _table[last-1].next = (_table[last-1].next & ~NEXT_MASK) | next;
|
||||
else _first = next;
|
||||
if (next) _table2[next-1].last = last;
|
||||
|
||||
// If this key was a leaf on a collision wind,
|
||||
if (!(_table[key].next & COLLIDE_MASK))
|
||||
{
|
||||
u32 mask = _allocated - 1;
|
||||
|
||||
do
|
||||
{
|
||||
// Go backwards through the collision list one step
|
||||
key = ((key + COLLISION_INCRINVERSE) * COLLISION_MULTINVERSE) & mask;
|
||||
|
||||
// Stop where collision list stops
|
||||
if (!(_table[key].next & COLLIDE_MASK))
|
||||
break;
|
||||
|
||||
// Turn off collision key for previous entry
|
||||
_table[key].next &= ~COLLIDE_MASK;
|
||||
|
||||
} while (!_table[key].conn);
|
||||
}
|
||||
|
||||
// Update number of used elements
|
||||
--_used;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool Collexion<T>::Remove(T *conn)
|
||||
{
|
||||
u32 hash = HashPtr(conn);
|
||||
|
||||
AutoMutex lock(_lock);
|
||||
|
||||
// If table doesn't exist,
|
||||
if (!_allocated) return false;
|
||||
|
||||
// Mask off high bits to make table key from hash
|
||||
u32 mask = _allocated - 1;
|
||||
u32 key = hash & mask;
|
||||
|
||||
// While target table entry not found,
|
||||
for (;;)
|
||||
{
|
||||
// If target was found,
|
||||
if (_table[key].conn == conn)
|
||||
{
|
||||
if (_table[key].refcnt)
|
||||
{
|
||||
// Mark it killed so iterator can clean it up when it's finished
|
||||
_table[key].next |= KILL_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
Unlink(key);
|
||||
|
||||
lock.Release();
|
||||
|
||||
conn->ReleaseRef();
|
||||
}
|
||||
|
||||
// Return success
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(_table[key].next & COLLIDE_MASK))
|
||||
{
|
||||
break; // End of collision list
|
||||
}
|
||||
|
||||
// Walk collision list
|
||||
key = (key * COLLISION_MULTIPLIER + COLLISION_INCREMENTER) & mask;
|
||||
}
|
||||
|
||||
// Return failure: not found
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Collexion<T>::Fill(CollexionIterator<T> &iter, u32 first)
|
||||
{
|
||||
u32 key = first;
|
||||
|
||||
// Find first list element that does not want to die
|
||||
while (key && (_table[key-1].next & KILL_MASK))
|
||||
{
|
||||
// Go to next
|
||||
key = _table[key-1].next & NEXT_MASK;
|
||||
}
|
||||
|
||||
iter._offset = 0;
|
||||
|
||||
// If no elements in table,
|
||||
if (!key)
|
||||
{
|
||||
// Return empty set
|
||||
iter._cache[0] = 0;
|
||||
iter._total = 0;
|
||||
iter._first = 0;
|
||||
iter._last = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember size of hash table in case it grows before iterator is done
|
||||
iter._prev_allocated = _allocated;
|
||||
|
||||
// Remember first key for next iteration
|
||||
iter._first = key;
|
||||
|
||||
// For each of the first MAX_CACHE elements in the table, copy the data pointer to cache
|
||||
u32 ii = 0, final = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// If element does not want to die,
|
||||
if (!(_table[key-1].next & KILL_MASK))
|
||||
{
|
||||
// Copy data pointer
|
||||
iter._cache[ii] = _table[key-1].conn;
|
||||
|
||||
// Increment reference count for element
|
||||
_table[key-1].refcnt++;
|
||||
|
||||
// Remember key as the next iteration starting point
|
||||
final = key;
|
||||
|
||||
// Check if copy is complete
|
||||
if (++ii >= CollexionIterator<T>::MAX_CACHE) break;
|
||||
}
|
||||
|
||||
// Go to next key
|
||||
key = _table[key-1].next & NEXT_MASK;
|
||||
|
||||
} while (key);
|
||||
|
||||
// Record number of elements written
|
||||
iter._total = ii;
|
||||
|
||||
// Remember next key for next iteration
|
||||
iter._last = final;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Collexion<T>::Begin(CollexionIterator<T> &iter)
|
||||
{
|
||||
iter._parent = this;
|
||||
|
||||
AutoMutex lock(_lock);
|
||||
|
||||
Fill(iter, _first);
|
||||
}
|
||||
|
||||
// Find a hash table key based on data
|
||||
template<class T>
|
||||
u32 Collexion<T>::Find(T *conn)
|
||||
{
|
||||
u32 mask = _allocated - 1;
|
||||
u32 key = HashPtr(conn) & mask;
|
||||
|
||||
// Find the object in the collision list starting at the expected location
|
||||
while (_table[key].conn != conn)
|
||||
{
|
||||
// If at the end of the collision list,
|
||||
if (!(_table[key].next & COLLIDE_MASK))
|
||||
break; // Should never happen
|
||||
|
||||
// Walk collision list
|
||||
key = (key * COLLISION_MULTIPLIER + COLLISION_INCREMENTER) & mask;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void Collexion<T>::Next(CollexionIterator<T> &iter, bool refill)
|
||||
{
|
||||
T *release_list[CollexionIterator<T>::MAX_CACHE];
|
||||
u32 release_ii = 0;
|
||||
|
||||
u32 key = iter._first;
|
||||
u32 last = iter._last;
|
||||
|
||||
// If iteration is done,
|
||||
if (!key) return;
|
||||
|
||||
AutoMutex lock(_lock);
|
||||
|
||||
// If hash table changed size (rare),
|
||||
if (iter._prev_allocated != _allocated)
|
||||
{
|
||||
// iter._first and iter._last are invalid
|
||||
// ...but we can find them again based on the cached pointers!
|
||||
key = Find(iter._cache[0]) + 1;
|
||||
last = Find(iter._cache[iter._total - 1]) + 1;
|
||||
}
|
||||
|
||||
last = _table[last-1].next & NEXT_MASK;
|
||||
|
||||
// Release any table elements that want to die now
|
||||
do
|
||||
{
|
||||
u32 flags = _table[key-1].next;
|
||||
|
||||
// If reference count is now zero for this element,
|
||||
if (0 == --_table[key-1].refcnt)
|
||||
{
|
||||
// If element wants to die,
|
||||
if (flags & KILL_MASK)
|
||||
{
|
||||
// Prepare to release data after lock is released
|
||||
release_list[release_ii++] = _table[key-1].conn;
|
||||
|
||||
Unlink(key-1);
|
||||
}
|
||||
}
|
||||
|
||||
key = flags & NEXT_MASK;
|
||||
|
||||
} while (key != last);
|
||||
|
||||
// Fill iterator starting with next key
|
||||
if (refill) Fill(iter, key);
|
||||
|
||||
lock.Release();
|
||||
|
||||
if (!refill)
|
||||
{
|
||||
// Return empty set
|
||||
iter._cache[0] = 0;
|
||||
iter._total = 0;
|
||||
iter._offset = 0;
|
||||
iter._first = 0;
|
||||
iter._last = 0;
|
||||
}
|
||||
|
||||
// Release data awaiting destruction
|
||||
for (u32 ii = 0; ii < release_ii; ++ii)
|
||||
{
|
||||
release_list[ii]->ReleaseRef();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// sphynx::CollexionIterator
|
||||
|
||||
template<class T>
|
||||
CollexionIterator<T>::CollexionIterator(Collexion<T> &begin)
|
||||
{
|
||||
begin.Begin(*this);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
CollexionIterator<T>::~CollexionIterator()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
CollexionIterator<T> &CollexionIterator<T>::operator++()
|
||||
{
|
||||
if (++_offset >= _total)
|
||||
{
|
||||
_parent->Next(*this, true);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void CollexionIterator<T>::Release()
|
||||
{
|
||||
if (_parent)
|
||||
{
|
||||
_parent->Next(*this, false);
|
||||
_parent = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace sphynx
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SPHYNX_COLLEXION_HPP
|
||||
300
DependentExtensions/cat/net/SphynxServer.hpp
Normal file
300
DependentExtensions/cat/net/SphynxServer.hpp
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SPHYNX_SERVER_HPP
|
||||
#define CAT_SPHYNX_SERVER_HPP
|
||||
|
||||
#include <cat/net/SphynxTransport.hpp>
|
||||
#include <cat/threads/RWLock.hpp>
|
||||
#include <cat/threads/Thread.hpp>
|
||||
#include <cat/threads/WaitableFlag.hpp>
|
||||
#include <cat/net/SphynxCollexion.hpp>
|
||||
#include <cat/crypt/cookie/CookieJar.hpp>
|
||||
#include <cat/crypt/tunnel/KeyAgreementResponder.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
namespace sphynx {
|
||||
|
||||
|
||||
/*
|
||||
Designed for server hardware with many processors.
|
||||
|
||||
In order to handle many users, the Sphynx server opens up a single UDP port
|
||||
to accept new connections, and several other UDP data ports for data.
|
||||
|
||||
For retransmissions and detecting link loss due to timeout, the server runs
|
||||
several additional threads that wake up periodically to perform timed tasks.
|
||||
|
||||
Server uses thread pool to receive packets on connect and worker ports,
|
||||
meaning that packets are processed by any free CPU as soon as they arrive.
|
||||
|
||||
Sphynx Server
|
||||
UDP Hello Port [1]
|
||||
+ In case this thread spins constantly, only use one CPU for new
|
||||
connections since in-game experience is more important than login
|
||||
+ Assigns users to a data port after handshake completes
|
||||
|
||||
UDP Data Ports [4 * (CPU Count)]
|
||||
+ Spread users evenly across several ports since
|
||||
only one packet can be processed from a single port at a time
|
||||
+ Any free CPU will process incoming packets as fast as possible
|
||||
|
||||
ServerTimer threads [(CPU Count) / 2]
|
||||
+ In case these threads spin constantly, they only consume
|
||||
half of the CPU resources available
|
||||
+ Wake up every X milliseconds according to Transport::TICK_RATE
|
||||
+ Detect link loss due to silence timeout
|
||||
+ Update transport layer
|
||||
+ Retransmit lost messages
|
||||
+ Re-evaluate bandwidth and transmit queued messages
|
||||
*/
|
||||
|
||||
|
||||
//// sphynx::Connexion
|
||||
|
||||
// Derive from sphynx::Connexion and sphynx::Server to define server behavior
|
||||
class Connexion : public Transport, public ThreadRefObject
|
||||
{
|
||||
friend class Server;
|
||||
friend class Map;
|
||||
friend class ServerWorker;
|
||||
friend class ServerTimer;
|
||||
|
||||
public:
|
||||
Connexion();
|
||||
virtual ~Connexion() {}
|
||||
|
||||
private:
|
||||
volatile u32 _destroyed;
|
||||
|
||||
u32 _key; // Map hash table index, unique for each active connection
|
||||
Connexion *_next_delete;
|
||||
ServerWorker *_server_worker;
|
||||
|
||||
u8 _first_challenge[64]; // First challenge seen from this client address
|
||||
u8 _cached_answer[128]; // Cached answer to this first challenge, to avoid eating server CPU time
|
||||
|
||||
private:
|
||||
// Return false to destroy this object
|
||||
bool Tick(ThreadPoolLocalStorage *tls, u32 now);
|
||||
|
||||
void OnRawData(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes);
|
||||
|
||||
virtual bool PostPacket(u8 *buffer, u32 buf_bytes, u32 msg_bytes, u32 skip_bytes);
|
||||
|
||||
public:
|
||||
CAT_INLINE bool IsValid() { return _destroyed == 0; }
|
||||
CAT_INLINE u32 GetKey() { return _key; }
|
||||
|
||||
void Destroy();
|
||||
|
||||
protected:
|
||||
NetAddr _client_addr;
|
||||
|
||||
// Last time a packet was received from this user -- for disconnect timeouts
|
||||
u32 _last_recv_tsc;
|
||||
|
||||
bool _seen_encrypted;
|
||||
AuthenticatedEncryption _auth_enc;
|
||||
|
||||
protected:
|
||||
virtual void OnConnect(ThreadPoolLocalStorage *tls) = 0;
|
||||
virtual void OnDestroy() = 0;
|
||||
virtual void OnTick(ThreadPoolLocalStorage *tls, u32 now) = 0;
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::Map
|
||||
|
||||
class Map
|
||||
{
|
||||
protected:
|
||||
CAT_INLINE u32 hash_addr(const NetAddr &addr, u32 salt);
|
||||
|
||||
public:
|
||||
struct Slot
|
||||
{
|
||||
Connexion *connection;
|
||||
bool collision;
|
||||
Slot *next;
|
||||
};
|
||||
|
||||
protected:
|
||||
u32 _hash_salt;
|
||||
CAT_ALIGNED(16) Slot _table[HASH_TABLE_SIZE];
|
||||
RWLock _table_lock;
|
||||
|
||||
public:
|
||||
Map();
|
||||
virtual ~Map();
|
||||
|
||||
// Lookup client by address
|
||||
Connexion *Lookup(const NetAddr &addr);
|
||||
|
||||
// Lookup client by key
|
||||
Connexion *Lookup(u32 key);
|
||||
|
||||
// May return false if network address in Connexion is already in the map.
|
||||
// This averts a potential race condition but should never happen during
|
||||
// normal operation, so the Connexion allocation by caller won't be wasted.
|
||||
bool Insert(Connexion *conn);
|
||||
|
||||
// Destroy a list described by the 'next' member of Slot
|
||||
void DestroyList(Map::Slot *kill_list);
|
||||
|
||||
void Tick(ThreadPoolLocalStorage *tls);
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::ServerWorker
|
||||
|
||||
class ServerWorker : public UDPEndpoint
|
||||
{
|
||||
friend class Map;
|
||||
|
||||
protected:
|
||||
Map *_conn_map;
|
||||
ServerTimer *_server_timer;
|
||||
|
||||
protected:
|
||||
volatile u32 _session_count;
|
||||
|
||||
public:
|
||||
ServerWorker(Map *conn_map, ServerTimer *server_timer);
|
||||
virtual ~ServerWorker();
|
||||
|
||||
void IncrementPopulation();
|
||||
void DecrementPopulation();
|
||||
u32 GetPopulation() { return _session_count; }
|
||||
|
||||
protected:
|
||||
void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &src, u8 *data, u32 bytes);
|
||||
void OnWrite(u32 bytes) {}
|
||||
void OnClose();
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::ServerTimer
|
||||
|
||||
class ServerTimer : Thread
|
||||
{
|
||||
protected:
|
||||
Map *_conn_map;
|
||||
|
||||
protected:
|
||||
ServerWorker **_workers;
|
||||
int _worker_count;
|
||||
|
||||
protected:
|
||||
Map::Slot *_insert_head;
|
||||
Mutex _insert_lock;
|
||||
|
||||
protected:
|
||||
Map::Slot *_active_head;
|
||||
|
||||
public:
|
||||
ServerTimer(Map *conn_map, ServerWorker **workers, int worker_count);
|
||||
virtual ~ServerTimer();
|
||||
|
||||
CAT_INLINE bool Valid() { return _worker_count > 0; }
|
||||
|
||||
public:
|
||||
void InsertSlot(Map::Slot *slot);
|
||||
|
||||
protected:
|
||||
CAT_INLINE void Tick(ThreadPoolLocalStorage *tls);
|
||||
bool ThreadFunction(void *param);
|
||||
|
||||
protected:
|
||||
static const int TIMER_THREAD_KILL_TIMEOUT = 10000;
|
||||
|
||||
WaitableFlag _kill_flag;
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::Server
|
||||
|
||||
class Server : public UDPEndpoint
|
||||
{
|
||||
public:
|
||||
Server();
|
||||
virtual ~Server();
|
||||
|
||||
bool StartServer(ThreadPoolLocalStorage *tls, Port port, u8 *public_key, int public_bytes, u8 *private_key, int private_bytes, const char *session_key);
|
||||
|
||||
u32 GetTotalPopulation();
|
||||
|
||||
static bool GenerateKeyPair(ThreadPoolLocalStorage *tls, const char *public_key_file,
|
||||
const char *private_key_file, u8 *public_key,
|
||||
int public_bytes, u8 *private_key, int private_bytes);
|
||||
|
||||
private:
|
||||
static const int SESSION_KEY_BYTES = 32;
|
||||
char _session_key[SESSION_KEY_BYTES];
|
||||
|
||||
Port _server_port;
|
||||
Map _conn_map;
|
||||
|
||||
CookieJar _cookie_jar;
|
||||
KeyAgreementResponder _key_agreement_responder;
|
||||
u8 _public_key[PUBLIC_KEY_BYTES];
|
||||
|
||||
static const int WORKER_LIMIT = 32; // Maximum number of workers
|
||||
ServerWorker **_workers;
|
||||
int _worker_count;
|
||||
|
||||
ServerTimer **_timers;
|
||||
int _timer_count;
|
||||
|
||||
private:
|
||||
ServerWorker *FindLeastPopulatedPort();
|
||||
|
||||
void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &src, u8 *data, u32 bytes);
|
||||
void OnWrite(u32 bytes);
|
||||
void OnClose();
|
||||
|
||||
protected:
|
||||
// Must return a new instance of your Connexion derivation
|
||||
virtual Connexion *NewConnexion() = 0;
|
||||
|
||||
// IP address filter: Return true to allow the connection to be made
|
||||
virtual bool AcceptNewConnexion(const NetAddr &src) = 0;
|
||||
|
||||
// Lookup client by key
|
||||
Connexion *Lookup(u32 key);
|
||||
};
|
||||
|
||||
|
||||
} // namespace sphynx
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SPHYNX_SERVER_HPP
|
||||
455
DependentExtensions/cat/net/SphynxTransport.hpp
Normal file
455
DependentExtensions/cat/net/SphynxTransport.hpp
Normal file
@ -0,0 +1,455 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_SPHYNX_TRANSPORT_HPP
|
||||
#define CAT_SPHYNX_TRANSPORT_HPP
|
||||
|
||||
#include <cat/net/ThreadPoolSockets.hpp>
|
||||
#include <cat/threads/Mutex.hpp>
|
||||
#include <cat/crypt/tunnel/AuthenticatedEncryption.hpp>
|
||||
#include <cat/parse/BufferStream.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
namespace sphynx {
|
||||
|
||||
|
||||
/*
|
||||
Based on what I have envisioned needing for my game, the following protocol is being
|
||||
used after spending weeks looking at alternatives and false-starts. It provides signaled
|
||||
disconnects, fragmentation, MTU discovery, time synchronization, three reliable ordered
|
||||
streams, one unordered reliable stream, and unreliable delivery.
|
||||
|
||||
The Transport object that implements a sender/receiver in the protocol requires 276 bytes
|
||||
of memory per server connection, plus 32 bytes per message fragment in flight, plus buffers
|
||||
for queued send/recv packets, and it keeps two mutexes for thread-safety. A lockless memory
|
||||
allocator is used to allocate all buffers except the fragmented message reassembly buffer.
|
||||
|
||||
Packet format on top of UDP header:
|
||||
|
||||
E { HDR(2 bytes)|ACK-ID(3 bytes)|DATA || ... || MAC(8 bytes) } || IV(3 bytes)
|
||||
|
||||
E: ChaCha-12 stream cipher.
|
||||
IV: Initialization vector used by security layer (Randomly initialized).
|
||||
MAC: Message authentication code used by security layer (HMAC-MD5).
|
||||
|
||||
HDR|ACK-ID|DATA: A message block inside the datagram. The HDR and ACK-ID
|
||||
fields employ compression to use as little as 1 byte together.
|
||||
|
||||
Each message follows the same format. A two-byte header followed by data:
|
||||
|
||||
--- Message Header (16 bits) ---
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||
<-- LSB ----------------- MSB -->
|
||||
| BHI |I|R| SOP | BLO |
|
||||
---------------------------------
|
||||
|
||||
DATA_BYTES: BHI | BLO = Number of bytes in data part of message.
|
||||
If BHI = "111"b, the BLO byte is omitted and the receiver can
|
||||
assume that the rest of the packet contains just one message.
|
||||
I: 1=Followed by ACK-ID field. 0=ACK-ID is one higher than the last.
|
||||
R: 1=Reliable. 0=Unreliable.
|
||||
SOP: Super opcodes:
|
||||
0=Data (reliable or unreliable)
|
||||
1=Fragment (reliable)
|
||||
2=ACK (unreliable)
|
||||
3=MTU Probe (unreliable)
|
||||
4=MTU Set (unordered reliable)
|
||||
5=Time Ping (unreliable)
|
||||
6=Time Pong (unreliable)
|
||||
7=Disconnect (unreliable)
|
||||
|
||||
When the I bit is set, the data part is preceded by an ACK-ID,
|
||||
which is then applied to all following reliable messages.
|
||||
This additional size is NOT accounted for in the DATA_BYTES field.
|
||||
|
||||
When the FRAG opcode used for the first time in an ordered stream,
|
||||
the data part begins with a 16-bit Fragment Header.
|
||||
This additional size IS accounted for in the DATA_BYTES field.
|
||||
|
||||
Often times there is just one message in a datagram. To compress
|
||||
the header in this case, when BHI = 7 the receiver assumes that
|
||||
only one message is in the packet and uses the payload length to
|
||||
determine the length of the single message. BLO byte is omitted.
|
||||
|
||||
This *could* also be used on the final message in a cluster,
|
||||
but it cannot be done without a memcpy to cover up the extra
|
||||
header byte, which I don't consider worthwhile...
|
||||
|
||||
------------- ACK-ID Field (24 bits) ------------
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
|
||||
<-- LSB --------------------------------- MSB -->
|
||||
| S | IDA (5) |C| IDB (7) |C| IDC (8) |
|
||||
-------------------------------------------------
|
||||
|
||||
C: 1=Continues to next byte.
|
||||
S: 0=Unordered stream, 1-3: Ordered streams.
|
||||
ID: IDC | IDB | IDA (20 bits)
|
||||
|
||||
On retransmission, the ACK-ID field uses no compression
|
||||
since the receiver state cannot be determined.
|
||||
|
||||
--- Fragment Header (16 bits) ---
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f
|
||||
<-- LSB ----------------- MSB -->
|
||||
| TOTAL_BYTES(16) |
|
||||
---------------------------------
|
||||
|
||||
TOTAL_BYTES: Total bytes in data part of fragmented message,
|
||||
not including this header.
|
||||
*/
|
||||
|
||||
/*
|
||||
ACK message format:
|
||||
|
||||
Header: I=0, R=0, SOP=SOP_ACK
|
||||
Data: ROLLUP(3) || RANGE1 || RANGE2 || ... ROLLUP(3) || RANGE1 || RANGE2 || ...
|
||||
|
||||
ROLLUP = Next expected ACK-ID. Acknowledges every ID before this one.
|
||||
|
||||
RANGE1:
|
||||
START || END
|
||||
|
||||
START = First inclusive ACK-ID in a range to acknowledge.
|
||||
END = Final inclusive ACK-ID in a range to acknowledge.
|
||||
|
||||
Negative acknowledgment can be inferred from the holes in the RANGEs.
|
||||
|
||||
------------ ROLLUP Field (24 bits) -------------
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
|
||||
<-- LSB --------------------------------- MSB -->
|
||||
|1| S | IDA (5) | IDB (8) | IDC (8) |
|
||||
-------------------------------------------------
|
||||
|
||||
1: Indicates start of ROLLUP field.
|
||||
S: 0=Unordered stream, 1-3: Ordered streams.
|
||||
ID: IDC | IDB | IDA (21 bits)
|
||||
|
||||
ROLLUP is always 3 bytes since we cannot tell how far ahead the remote host is now.
|
||||
|
||||
--------- RANGE START Field (24 bits) -----------
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
|
||||
<-- LSB --------------------------------- MSB -->
|
||||
|0|E| IDA (5) |C| IDB (7) |C| IDC (8) |
|
||||
-------------------------------------------------
|
||||
|
||||
0: Indicates start of RANGE field.
|
||||
C: 1=Continues to next byte.
|
||||
E: 1=Has end field. 0=One ID in range.
|
||||
ID: IDC | IDB | IDA (20 bits) + last ack id in message
|
||||
|
||||
---------- RANGE END Field (24 bits) ------------
|
||||
0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7
|
||||
<-- LSB --------------------------------- MSB -->
|
||||
| IDA (7) |C| IDB (7) |C| IDC (8) |
|
||||
-------------------------------------------------
|
||||
|
||||
C: 1=Continues to next byte.
|
||||
ID: IDC | IDB | IDA (22 bits) + START.ID
|
||||
*/
|
||||
|
||||
class Connexion;
|
||||
class Map;
|
||||
class Server;
|
||||
class ServerWorker;
|
||||
class ServerTimer;
|
||||
class Client;
|
||||
class Transport;
|
||||
|
||||
#if defined(CAT_WORD_32)
|
||||
#define CAT_PACK_TRANSPORT_STATE_STRUCTURES /* For 32-bit version, this allows fragments to fit in 32 bytes */
|
||||
#else // 64-bit version:
|
||||
//#define CAT_PACK_TRANSPORT_STATE_STRUCTURES /* No advantage for 64-bit version */
|
||||
#endif
|
||||
|
||||
//#define CAT_TRANSPORT_DEBUG_LOGGING /* Enables info messages on console */
|
||||
#define CAT_VERBOSE_VALIDATION /* Enables input error messages on console */
|
||||
|
||||
// Protocol constants
|
||||
static const u32 PROTOCOL_MAGIC = 0xC47D0001;
|
||||
static const int PUBLIC_KEY_BYTES = 64;
|
||||
static const int PRIVATE_KEY_BYTES = 32;
|
||||
static const int CHALLENGE_BYTES = PUBLIC_KEY_BYTES;
|
||||
static const int ANSWER_BYTES = PUBLIC_KEY_BYTES*2;
|
||||
static const int HASH_TABLE_SIZE = 32768; // Power-of-2
|
||||
static const int HASH_TABLE_MASK = HASH_TABLE_SIZE - 1;
|
||||
static const int MAX_POPULATION = HASH_TABLE_SIZE / 2;
|
||||
|
||||
// (multiplier-1) divisible by all prime factors of table size
|
||||
// (multiplier-1) is a multiple of 4 if table size is a multiple of 4
|
||||
// These constants are from Press, Teukolsky, Vetterling and Flannery's
|
||||
// "Numerical Recipes in FORTRAN: The Art of Scientific Computing"
|
||||
static const u32 COLLISION_MULTIPLIER = 71*5861 * 4 + 1;
|
||||
static const u32 COLLISION_INCREMENTER = 1013904223;
|
||||
|
||||
// If multiplier changes, this needs to be recalculated (multiplicative inverse of above)
|
||||
static const u32 COLLISION_MULTINVERSE = 4276115653;
|
||||
static const u32 COLLISION_INCRINVERSE = 0 - COLLISION_INCREMENTER;
|
||||
|
||||
|
||||
// Handshake types
|
||||
enum HandshakeType
|
||||
{
|
||||
C2S_HELLO,
|
||||
S2C_COOKIE,
|
||||
C2S_CHALLENGE,
|
||||
S2C_ANSWER,
|
||||
S2C_ERROR
|
||||
};
|
||||
|
||||
// Handshake errors
|
||||
enum HandshakeError
|
||||
{
|
||||
ERR_SERVER_FULL
|
||||
};
|
||||
|
||||
// Stream modes
|
||||
enum StreamMode
|
||||
{
|
||||
STREAM_UNORDERED = 0, // Reliable, unordered stream 0
|
||||
STREAM_1 = 1, // Reliable, ordered stream 1
|
||||
STREAM_2 = 2, // Reliable, ordered stream 2
|
||||
STREAM_3 = 3 // Reliable, ordered stream 3
|
||||
};
|
||||
|
||||
// Super Opcodes
|
||||
enum SuperOpcode
|
||||
{
|
||||
SOP_DATA, // 0=Data (reliable or unreliable)
|
||||
SOP_FRAG, // 1=Fragment (reliable)
|
||||
SOP_ACK, // 2=ACK (unreliable)
|
||||
SOP_MTU_PROBE, // 3=MTU Probe (unreliable)
|
||||
SOP_MTU_SET, // 4=MTU Set (unordered reliable)
|
||||
SOP_TIME_PING, // 5=Time Ping (unreliable)
|
||||
SOP_TIME_PONG, // 6=Time Pong (unreliable)
|
||||
SOP_DISCO, // 7=Disconnect (unreliable)
|
||||
};
|
||||
|
||||
|
||||
//// sphynx::Transport
|
||||
|
||||
#if defined(CAT_PACK_TRANSPORT_STATE_STRUCTURES)
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
#endif // CAT_PACK_TRANSPORT_STATE_STRUCTURES
|
||||
|
||||
// Receive state: Receive queue
|
||||
struct RecvQueue
|
||||
{
|
||||
static const u32 FRAG_FLAG = 0x80000000;
|
||||
static const u32 BYTE_MASK = 0x7fffffff;
|
||||
|
||||
RecvQueue *next; // Next in queue
|
||||
RecvQueue *prev; // Previous in queue
|
||||
u32 id; // Acknowledgment id
|
||||
u32 bytes; // High bit: Fragment?
|
||||
|
||||
// Message contents follow
|
||||
};
|
||||
|
||||
// Send state: Send queue
|
||||
struct SendQueue
|
||||
{
|
||||
SendQueue *next; // Next in queue
|
||||
SendQueue *prev; // Previous in queue
|
||||
u32 ts_firstsend; // Millisecond-resolution timestamp when it was first sent
|
||||
u32 ts_lastsend; // Millisecond-resolution timestamp when it was last sent
|
||||
union
|
||||
{
|
||||
u32 sent_bytes; // In send queue: Number of sent bytes while fragmenting a large message
|
||||
u32 id; // In sent list: Acknowledgment id
|
||||
};
|
||||
u16 bytes; // Data bytes
|
||||
u16 frag_count; // Number of fragments remaining to be delivered
|
||||
u16 sop; // Super opcode of message
|
||||
|
||||
// Message contents follow
|
||||
};
|
||||
|
||||
struct SendFrag : public SendQueue
|
||||
{
|
||||
SendQueue *full_data; // Object containing message data
|
||||
u16 offset; // Fragment data offset
|
||||
};
|
||||
|
||||
// Temporary send node structure, nestled in the encryption overhead of outgoing packets
|
||||
struct TempSendNode // Size <= 11 bytes = AuthenticatedEncryption::OVERHEAD_BYTES
|
||||
{
|
||||
static const u32 SINGLE_FLAG = 0x8000;
|
||||
static const u32 BYTE_MASK = 0x7fff;
|
||||
|
||||
TempSendNode *next;
|
||||
u16 negative_offset; // Number of bytes before this structure, and single flag
|
||||
};
|
||||
|
||||
#if defined(CAT_PACK_TRANSPORT_STATE_STRUCTURES)
|
||||
#pragma pack(pop)
|
||||
#endif // CAT_PACK_TRANSPORT_STATE_STRUCTURES
|
||||
|
||||
class Transport
|
||||
{
|
||||
protected:
|
||||
static const u8 BHI_MASK = 7;
|
||||
static const u8 BHI_SINGLE_MESSAGE = 7;
|
||||
static const u8 I_MASK = 1 << 3;
|
||||
static const u8 R_MASK = 1 << 4;
|
||||
static const u32 SOP_SHIFT = 5;
|
||||
|
||||
static const u32 NUM_STREAMS = 4; // Number of reliable streams
|
||||
static const u32 MIN_RTT = 50; // Minimum milliseconds for RTT
|
||||
|
||||
static const int TIMEOUT_DISCONNECT = 15000; // 15 seconds
|
||||
static const int SILENCE_LIMIT = 9333; // 9.333 seconds: Time silent before sending a keep-alive (0-length unordered reliable message)
|
||||
|
||||
static const int TICK_RATE = 20; // 20 milliseconds
|
||||
|
||||
static const u32 MINIMUM_MTU = 576; // Dialup
|
||||
static const u32 MEDIUM_MTU = 1400; // Highspeed with unexpected overhead, maybe VPN
|
||||
static const u32 MAXIMUM_MTU = 1500; // Highspeed
|
||||
|
||||
static const u32 IPV6_OPTIONS_BYTES = 40; // TODO: Not sure about this
|
||||
static const u32 IPV6_HEADER_BYTES = 40 + IPV6_OPTIONS_BYTES;
|
||||
|
||||
static const u32 IPV4_OPTIONS_BYTES = 40;
|
||||
static const u32 IPV4_HEADER_BYTES = 20 + IPV4_OPTIONS_BYTES;
|
||||
|
||||
static const u32 UDP_HEADER_BYTES = 8;
|
||||
|
||||
static const u32 FRAG_THRESHOLD = 32; // Fragment if FRAG_THRESHOLD bytes would be in each fragment
|
||||
|
||||
static const u32 MAX_MESSAGE_DATALEN = 65535-1; // Maximum number of bytes in the data part of a message (-1 for the opcode)
|
||||
|
||||
protected:
|
||||
// Maximum transfer unit (MTU) in UDP payload bytes, excluding the IP and UDP headers and encryption overhead
|
||||
u32 _max_payload_bytes;
|
||||
|
||||
public:
|
||||
void InitializePayloadBytes(bool ip6);
|
||||
|
||||
protected:
|
||||
// Receive state: Next expected ack id to receive
|
||||
u32 _next_recv_expected_id[NUM_STREAMS];
|
||||
|
||||
// Receive state: Synchronization objects
|
||||
volatile bool _got_reliable[NUM_STREAMS];
|
||||
Mutex _recv_lock; // Just needs to protect writes OnDatagram() from messing up reads on tick
|
||||
|
||||
// Receive state: Fragmentation
|
||||
u8 *_fragment_buffer[NUM_STREAMS]; // Buffer for accumulating fragment
|
||||
u32 _fragment_length[NUM_STREAMS]; // Number of bytes in fragment buffer
|
||||
u32 _fragment_offset[NUM_STREAMS]; // Current write offset in buffer
|
||||
|
||||
static const u32 FRAG_MIN = 0; // Min bytes for a fragmented message
|
||||
static const u32 FRAG_MAX = 65535; // Max bytes for a fragmented message
|
||||
|
||||
// Receive state: Receive queue head
|
||||
RecvQueue *_recv_queue_head[NUM_STREAMS], *_recv_queue_tail[NUM_STREAMS];
|
||||
|
||||
private:
|
||||
void RunQueue(ThreadPoolLocalStorage *tls, u32 ack_id, u32 stream);
|
||||
void QueueRecv(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes, u32 ack_id, u32 stream, u32 super_opcode);
|
||||
|
||||
protected:
|
||||
// Send state: Synchronization objects
|
||||
Mutex _send_lock;
|
||||
|
||||
// Send state: Next ack id to use
|
||||
u32 _next_send_id[NUM_STREAMS];
|
||||
|
||||
// Send state: Estimated round-trip time
|
||||
u32 _rtt; // milliseconds
|
||||
|
||||
// Send state: Last rollup ack id from remote receiver
|
||||
u32 _send_next_remote_expected[NUM_STREAMS];
|
||||
|
||||
// Send state: Combined writes
|
||||
u8 *_send_buffer;
|
||||
u32 _send_buffer_bytes;
|
||||
u32 _send_buffer_stream, _send_buffer_ack_id; // Used to compress ACK-ID by setting I=0 after the first reliable message
|
||||
u32 _send_buffer_msg_count; // Used to compress datagrams with a single message by omitting the header's BLO field
|
||||
|
||||
// Queue of messages that are waiting to be sent
|
||||
SendQueue *_send_queue_head[NUM_STREAMS], *_send_queue_tail[NUM_STREAMS];
|
||||
|
||||
// List of messages that are waiting to be acknowledged
|
||||
SendQueue *_sent_list_head[NUM_STREAMS], *_sent_list_tail[NUM_STREAMS];
|
||||
|
||||
bool _disconnected;
|
||||
|
||||
private:
|
||||
void TransmitQueued();
|
||||
void Retransmit(u32 stream, SendQueue *node, u32 now); // Does not hold the send lock!
|
||||
void WriteACK();
|
||||
void OnACK(u8 *data, u32 data_bytes);
|
||||
void OnMTUSet(u8 *data, u32 data_bytes);
|
||||
|
||||
public:
|
||||
Transport();
|
||||
virtual ~Transport();
|
||||
|
||||
public:
|
||||
// ata_bytes: Length of msg_data
|
||||
bool WriteUnreliable(u8 msg_opcode, const void *msg_data = 0, u32 data_bytes = 0);
|
||||
bool WriteReliable(StreamMode, u8 msg_opcode, const void *msg_data = 0, u32 data_bytes = 0, SuperOpcode super_opcode = SOP_DATA);
|
||||
void FlushWrite();
|
||||
|
||||
protected:
|
||||
// Notify transport layer of disconnect to halt message processing
|
||||
CAT_INLINE void TransportDisconnected() { _disconnected = true; }
|
||||
CAT_INLINE bool IsDisconnected() { return _disconnected; }
|
||||
|
||||
void TickTransport(ThreadPoolLocalStorage *tls, u32 now);
|
||||
void OnDatagram(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes);
|
||||
|
||||
private:
|
||||
void OnFragment(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes, u32 stream);
|
||||
void CombineNextWrite();
|
||||
|
||||
protected:
|
||||
// skip_bytes: Number of bytes to skip at the start of the buffer
|
||||
// buf_bytes and msg_bytes contain the skipped bytes
|
||||
virtual bool PostPacket(u8 *data, u32 buf_bytes, u32 msg_bytes, u32 skip_bytes) = 0;
|
||||
virtual void OnTimestampDeltaUpdate(u32 rtt, s32 delta) {}
|
||||
virtual void OnMessage(ThreadPoolLocalStorage *tls, BufferStream msg, u32 bytes) = 0;
|
||||
virtual void OnDisconnect() = 0;
|
||||
|
||||
protected:
|
||||
bool PostMTUProbe(ThreadPoolLocalStorage *tls, u16 payload_bytes);
|
||||
bool PostTimePing();
|
||||
bool PostTimePong(u32 client_ts);
|
||||
bool PostDisconnect();
|
||||
};
|
||||
|
||||
|
||||
} // namespace sphynx
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_SPHYNX_TRANSPORT_HPP
|
||||
95
DependentExtensions/cat/net/ThreadPoolSockets.hpp
Normal file
95
DependentExtensions/cat/net/ThreadPoolSockets.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// TODO: Half-open connections can easily DoS the TCP server right now.
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
#include <cat/threads/ThreadPool.hpp>
|
||||
#include <cat/net/Sockets.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnexion;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
void ReportUnexpectedSocketError(int error);
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
|
||||
#if defined (CAT_OS_WINDOWS) // Windows-style IOCP
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
#include <cat/net/win/TCPServer.hpp>
|
||||
#include <cat/net/win/TCPConnexion.hpp>
|
||||
#include <cat/net/win/TCPClient.hpp>
|
||||
#include <cat/net/win/UDPEndpoint.hpp>
|
||||
|
||||
#elif defined(CAT_OS_LINUX) // Linux-style eventfd
|
||||
|
||||
#include <cat/net/linux/TCPServer.hpp>
|
||||
#include <cat/net/linux/TCPConnexion.hpp>
|
||||
#include <cat/net/linux/TCPClient.hpp>
|
||||
#include <cat/net/linux/UDPEndpoint.hpp>
|
||||
|
||||
#elif defined(CAT_OS_OSX) || defined(CAT_OS_BSD) // BSD-style kevent
|
||||
|
||||
#include <cat/net/bsd/TCPServer.hpp>
|
||||
#include <cat/net/bsd/TCPConnexion.hpp>
|
||||
#include <cat/net/bsd/TCPClient.hpp>
|
||||
#include <cat/net/bsd/UDPEndpoint.hpp>
|
||||
|
||||
#else // Fall-back
|
||||
|
||||
#include <cat/net/generic/TCPServer.hpp>
|
||||
#include <cat/net/generic/TCPConnexion.hpp>
|
||||
#include <cat/net/generic/TCPClient.hpp>
|
||||
#include <cat/net/generic/UDPEndpoint.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
348
DependentExtensions/cat/net/bsd/TCPClient.hpp
Normal file
348
DependentExtensions/cat/net/bsd/TCPClient.hpp
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// TODO: Half-open connections can easily DoS the TCP server right now.
|
||||
// TODO: Port to Linux(eventfd) and BSD/MacOSX(kevent)
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
#include <cat/threads/ThreadPool.hpp>
|
||||
#include <cat/net/Sockets.hpp>
|
||||
|
||||
#if defined(CAT_MS_SOCKET_API)
|
||||
# include <MSWSock.h>
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnection;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
|
||||
//// Buffer Management
|
||||
|
||||
// Generate a buffer to pass to Post()
|
||||
u8 *GetPostBuffer(u32 bytes);
|
||||
|
||||
void *ResizePostBuffer(void *buffer, u32 newBytes);
|
||||
|
||||
// Release a buffer provided by GetPostBuffer()
|
||||
// Note: Once the buffer is submitted to Post() this is unnecessary
|
||||
void ReleasePostBuffer(void *buffer);
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
242
DependentExtensions/cat/net/bsd/TCPConnection.hpp
Normal file
242
DependentExtensions/cat/net/bsd/TCPConnection.hpp
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
347
DependentExtensions/cat/net/bsd/TCPServer.hpp
Normal file
347
DependentExtensions/cat/net/bsd/TCPServer.hpp
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnection;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
|
||||
//// Buffer Management
|
||||
|
||||
// Generate a buffer to pass to Post()
|
||||
u8 *GetPostBuffer(u32 bytes);
|
||||
|
||||
void *ResizePostBuffer(void *buffer, u32 newBytes);
|
||||
|
||||
// Release a buffer provided by GetPostBuffer()
|
||||
// Note: Once the buffer is submitted to Post() this is unnecessary
|
||||
void ReleasePostBuffer(void *buffer);
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
319
DependentExtensions/cat/net/bsd/UDPEndpoint.hpp
Normal file
319
DependentExtensions/cat/net/bsd/UDPEndpoint.hpp
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
#define CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
348
DependentExtensions/cat/net/generic/TCPClient.hpp
Normal file
348
DependentExtensions/cat/net/generic/TCPClient.hpp
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// TODO: Half-open connections can easily DoS the TCP server right now.
|
||||
// TODO: Port to Linux(eventfd) and BSD/MacOSX(kevent)
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
#include <cat/threads/ThreadPool.hpp>
|
||||
#include <cat/net/Sockets.hpp>
|
||||
|
||||
#if defined(CAT_MS_SOCKET_API)
|
||||
# include <MSWSock.h>
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnection;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
|
||||
//// Buffer Management
|
||||
|
||||
// Generate a buffer to pass to Post()
|
||||
u8 *GetPostBuffer(u32 bytes);
|
||||
|
||||
void *ResizePostBuffer(void *buffer, u32 newBytes);
|
||||
|
||||
// Release a buffer provided by GetPostBuffer()
|
||||
// Note: Once the buffer is submitted to Post() this is unnecessary
|
||||
void ReleasePostBuffer(void *buffer);
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
242
DependentExtensions/cat/net/generic/TCPConnection.hpp
Normal file
242
DependentExtensions/cat/net/generic/TCPConnection.hpp
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
347
DependentExtensions/cat/net/generic/TCPServer.hpp
Normal file
347
DependentExtensions/cat/net/generic/TCPServer.hpp
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnection;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
|
||||
//// Buffer Management
|
||||
|
||||
// Generate a buffer to pass to Post()
|
||||
u8 *GetPostBuffer(u32 bytes);
|
||||
|
||||
void *ResizePostBuffer(void *buffer, u32 newBytes);
|
||||
|
||||
// Release a buffer provided by GetPostBuffer()
|
||||
// Note: Once the buffer is submitted to Post() this is unnecessary
|
||||
void ReleasePostBuffer(void *buffer);
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
319
DependentExtensions/cat/net/generic/UDPEndpoint.hpp
Normal file
319
DependentExtensions/cat/net/generic/UDPEndpoint.hpp
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
#define CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
348
DependentExtensions/cat/net/linux/TCPClient.hpp
Normal file
348
DependentExtensions/cat/net/linux/TCPClient.hpp
Normal file
@ -0,0 +1,348 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// TODO: Half-open connections can easily DoS the TCP server right now.
|
||||
// TODO: Port to Linux(eventfd) and BSD/MacOSX(kevent)
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
#include <cat/threads/ThreadPool.hpp>
|
||||
#include <cat/net/Sockets.hpp>
|
||||
|
||||
#if defined(CAT_MS_SOCKET_API)
|
||||
# include <MSWSock.h>
|
||||
# include <cat/port/WindowsInclude.hpp>
|
||||
#endif
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnection;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
|
||||
//// Buffer Management
|
||||
|
||||
// Generate a buffer to pass to Post()
|
||||
u8 *GetPostBuffer(u32 bytes);
|
||||
|
||||
void *ResizePostBuffer(void *buffer, u32 newBytes);
|
||||
|
||||
// Release a buffer provided by GetPostBuffer()
|
||||
// Note: Once the buffer is submitted to Post() this is unnecessary
|
||||
void ReleasePostBuffer(void *buffer);
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
242
DependentExtensions/cat/net/linux/TCPConnection.hpp
Normal file
242
DependentExtensions/cat/net/linux/TCPConnection.hpp
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
347
DependentExtensions/cat/net/linux/TCPServer.hpp
Normal file
347
DependentExtensions/cat/net/linux/TCPServer.hpp
Normal file
@ -0,0 +1,347 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_SOCKETS_HPP
|
||||
#define CAT_THREAD_POOL_SOCKETS_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
Thread Pool Sockets library
|
||||
|
||||
Provides a framework for rapidly developing TCP/UDP server and client objects
|
||||
that make use of high performance APIs under various server and desktop
|
||||
operating systems.
|
||||
|
||||
All network events are processed by a thread pool managed by ThreadPool.
|
||||
*/
|
||||
|
||||
class TCPServer;
|
||||
class TCPConnection;
|
||||
class TCPClient;
|
||||
class UDPEndpoint;
|
||||
|
||||
|
||||
//// Buffer Management
|
||||
|
||||
// Generate a buffer to pass to Post()
|
||||
u8 *GetPostBuffer(u32 bytes);
|
||||
|
||||
void *ResizePostBuffer(void *buffer, u32 newBytes);
|
||||
|
||||
// Release a buffer provided by GetPostBuffer()
|
||||
// Note: Once the buffer is submitted to Post() this is unnecessary
|
||||
void ReleasePostBuffer(void *buffer);
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_SOCKETS_HPP
|
||||
319
DependentExtensions/cat/net/linux/UDPEndpoint.hpp
Normal file
319
DependentExtensions/cat/net/linux/UDPEndpoint.hpp
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
#define CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
#include <MSWSock.h>
|
||||
#include <cat/port/WindowsInclude.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// Overlapped Sockets
|
||||
|
||||
// AcceptEx() OVERLAPPED structure
|
||||
struct AcceptExOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address either!
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
|
||||
void Set(Socket s);
|
||||
};
|
||||
|
||||
// WSARecvFrom() OVERLAPPED structure
|
||||
struct RecvFromOverlapped
|
||||
{
|
||||
TypedOverlapped tov;
|
||||
|
||||
// Not necessarily and IPv6 address,
|
||||
// but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
|
||||
// data follows...
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnection() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnection;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPServer();
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
virtual TCPConnection *InstantiateServerConnection() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
private:
|
||||
bool QueueAcceptEx();
|
||||
bool QueueAccepts();
|
||||
|
||||
void OnAcceptExComplete(int error, AcceptExOverlapped *overlapped);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection();
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true iff the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPClient();
|
||||
virtual ~TCPClient();
|
||||
|
||||
bool ValidClient();
|
||||
|
||||
bool Connect(const NetAddr &remoteServerAddress);
|
||||
void DisconnectServer();
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer() = 0;
|
||||
virtual bool OnReadFromServer(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToServer(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueConnectEx(const NetAddr &remoteServerAddress);
|
||||
void OnConnectExComplete(int error);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
void *_queueBuffer;
|
||||
u32 _queueBytes;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued();
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool PostToServer(void *buffer, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
UDPEndpoint();
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
bool Valid();
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(Port port = 0, bool ignoreUnreachable = true);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling Post() with addr.PromoteTo6()
|
||||
bool Post(const NetAddr &addr, void *data, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual void OnWrite(u32 bytes) = 0;
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
private:
|
||||
bool QueueWSARecvFrom(RecvFromOverlapped *recvOv);
|
||||
void OnWSARecvFromComplete(ThreadPoolLocalStorage *tls, int error, RecvFromOverlapped *recvOv, u32 bytes);
|
||||
|
||||
bool QueueWSASendTo(const NetAddr &addr, TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendToComplete(int error, u32 bytes);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_THREAD_POOL_UDP_ENDPOINT_HPP
|
||||
126
DependentExtensions/cat/net/win/TCPClient.hpp
Normal file
126
DependentExtensions/cat/net/win/TCPClient.hpp
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_TCP_CLIENT_HPP
|
||||
#define CAT_TCP_CLIENT_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
class TCPClient
|
||||
|
||||
Object that represents a TCPClient bound to a single port
|
||||
|
||||
ValidClient() : Returns true if the client socket is valid
|
||||
|
||||
Connect() : Connects to the given address
|
||||
DisconnectServer() : Disconnects from the server
|
||||
PostToServer() : Send a message to the server (will fail if not connected)
|
||||
|
||||
OnConnectToServer() : Called when connection is accepted
|
||||
OnReadFromServer() : Return false to disconnect the server in response to data
|
||||
OnWriteToServer() : Informs the derived class that data has been sent
|
||||
OnDisconnectFromServer() : Informs the derived class that the server has disconnected
|
||||
*/
|
||||
class TCPClient : public ThreadRefObject
|
||||
{
|
||||
// Remembers if socket is IPv6 so that user-provided
|
||||
// addresses can be promoted if necessary.
|
||||
bool _ipv6;
|
||||
Socket _socket;
|
||||
volatile u32 _disconnecting; // Disconnect flag
|
||||
|
||||
public:
|
||||
TCPClient(int priorityLevel);
|
||||
virtual ~TCPClient();
|
||||
|
||||
CAT_INLINE bool Valid() { return _socket != SOCKET_ERROR; }
|
||||
|
||||
void Disconnect();
|
||||
bool Connect(bool onlySupportIPv4, const NetAddr &remoteServerAddress);
|
||||
|
||||
public:
|
||||
bool Post(u8 *data, u32 data_bytes, u32 skip_bytes = 0);
|
||||
|
||||
private:
|
||||
bool ConnectEx(const NetAddr &remoteServerAddress);
|
||||
bool Read(AsyncBuffer *buffer = 0);
|
||||
bool Disco(AsyncBuffer *buffer = 0);
|
||||
|
||||
private:
|
||||
bool OnConnectEx(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
bool OnRead(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
bool OnWrite(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
bool OnDisco(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnConnectToServer(ThreadPoolLocalStorage *tls) = 0;
|
||||
virtual bool OnReadFromServer(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual bool OnWriteToServer(ThreadPoolLocalStorage *tls, AsyncBuffer *buffer, u32 bytes) = 0; // true = delete AsyncBuffer object
|
||||
virtual void OnDisconnectFromServer() = 0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
class TCPClientQueued
|
||||
|
||||
Base class for a TCP client that needs to queue up data for sending before
|
||||
a connection has been established. e.g. Uplink for a proxy server.
|
||||
|
||||
PostQueuedToServer() : Call in OnConnectToServer() to post the queued messages.
|
||||
*/
|
||||
class TCPClientQueued : public TCPClient
|
||||
{
|
||||
private:
|
||||
volatile bool _queuing;
|
||||
|
||||
Mutex _queueLock;
|
||||
AsyncBuffer *_queueBuffer;
|
||||
|
||||
protected:
|
||||
void PostQueuedToServer();
|
||||
|
||||
public:
|
||||
TCPClientQueued(int priorityLevel);
|
||||
virtual ~TCPClientQueued();
|
||||
|
||||
bool Post(u8 *data, u32 data_bytes, u32 skip_bytes = 0);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_TCP_CLIENT_HPP
|
||||
102
DependentExtensions/cat/net/win/TCPConnection.hpp
Normal file
102
DependentExtensions/cat/net/win/TCPConnection.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_TCP_CONNECTION_HPP
|
||||
#define CAT_TCP_CONNECTION_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnection
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
DisconnectClient() : Disconnect the client
|
||||
PostToClient() : Send a message to the client
|
||||
ValidServerConnection() : Returns true iff the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnection : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
friend class ThreadPool;
|
||||
|
||||
public:
|
||||
TCPConnection(int priorityLevel);
|
||||
virtual ~TCPConnection();
|
||||
|
||||
bool ValidServerConnection();
|
||||
|
||||
void DisconnectClient();
|
||||
bool PostToClient(void *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual void OnWriteToClient(u32 bytes) = 0;
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
|
||||
private:
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
TypedOverlapped *_recvOv;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
private:
|
||||
bool AcceptConnection(Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
bool QueueWSARecv();
|
||||
void OnWSARecvComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueWSASend(TypedOverlapped *sendOv, u32 bytes);
|
||||
void OnWSASendComplete(int error, u32 bytes);
|
||||
|
||||
bool QueueDisconnectEx();
|
||||
void OnDisconnectExComplete(int error);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_TCP_CONNECTION_HPP
|
||||
98
DependentExtensions/cat/net/win/TCPConnexion.hpp
Normal file
98
DependentExtensions/cat/net/win/TCPConnexion.hpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_TCP_CONNEXION_HPP
|
||||
#define CAT_TCP_CONNEXION_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
class TCPConnexion
|
||||
|
||||
Object that represents a TCPServer's connection from a TCPClient
|
||||
|
||||
Object is instantiated just before accepting a connection
|
||||
|
||||
Disconnect() : Disconnect the client
|
||||
Post() : Send a message to the client
|
||||
Valid() : Returns true if the connection is valid
|
||||
|
||||
OnConnectFromClient() : Return false to deny this connection
|
||||
OnReadFromClient() : Return false to disconnect the client in response to a message
|
||||
OnWriteToClient() : Informs the derived class that data has been sent
|
||||
OnDisconectFromClient() : Informs the derived class that the client has disconnected
|
||||
*/
|
||||
class TCPConnexion : public ThreadRefObject
|
||||
{
|
||||
friend class TCPServer;
|
||||
|
||||
Socket _socket;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
volatile u32 _disconnecting;
|
||||
|
||||
bool Accept(ThreadPoolLocalStorage *tls, Socket listenSocket, Socket acceptSocket,
|
||||
LPFN_DISCONNECTEX lpfnDisconnectEx, const NetAddr &acceptAddress,
|
||||
const NetAddr &remoteClientAddress);
|
||||
|
||||
public:
|
||||
TCPConnexion(int priorityLevel);
|
||||
virtual ~TCPConnexion();
|
||||
|
||||
CAT_INLINE bool Valid() { return _socket != SOCKET_ERROR; }
|
||||
|
||||
void Disconnect();
|
||||
bool Post(u8 *data, u32 data_bytes, u32 skip_bytes = 0);
|
||||
|
||||
private:
|
||||
bool Read(AsyncBuffer *buffer = 0);
|
||||
bool Disco(AsyncBuffer *buffer = 0);
|
||||
|
||||
private:
|
||||
bool OnRead(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
bool OnWrite(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
bool OnDisco(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual bool OnConnectFromClient(ThreadPoolLocalStorage *tls, const NetAddr &remoteClientAddress) = 0; // false = disconnect
|
||||
virtual bool OnReadFromClient(ThreadPoolLocalStorage *tls, u8 *data, u32 bytes) = 0; // false = disconnect
|
||||
virtual bool OnWriteToClient(ThreadPoolLocalStorage *tls, AsyncBuffer *buffer, u32 bytes) = 0; // true = delete AsyncBuffer
|
||||
virtual void OnDisconnectFromClient() = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_TCP_CONNEXION_HPP
|
||||
97
DependentExtensions/cat/net/win/TCPServer.hpp
Normal file
97
DependentExtensions/cat/net/win/TCPServer.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_TCP_SERVER_HPP
|
||||
#define CAT_TCP_SERVER_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
class TCPServer
|
||||
|
||||
Object that represents a TCP server bound to a single port
|
||||
|
||||
Overload InstantiateServerConnexion() to subclass connections with the server
|
||||
*/
|
||||
class TCPServer : public ThreadRefObject
|
||||
{
|
||||
friend class TCPConnexion;
|
||||
|
||||
Socket _socket;
|
||||
LPFN_ACCEPTEX _lpfnAcceptEx;
|
||||
LPFN_GETACCEPTEXSOCKADDRS _lpfnGetAcceptExSockAddrs;
|
||||
LPFN_DISCONNECTEX _lpfnDisconnectEx;
|
||||
Port _port;
|
||||
|
||||
struct AcceptTag
|
||||
{
|
||||
Socket acceptSocket;
|
||||
|
||||
// Space pre-allocated to receive addresses
|
||||
// NOTE: This is not necessarily how the addresses are organized in memory
|
||||
struct
|
||||
{
|
||||
// Not necessarily an IPv6 address
|
||||
sockaddr_in6 addr[2];
|
||||
u8 padding[2*16];
|
||||
} addresses;
|
||||
};
|
||||
|
||||
bool PostAccept(AsyncBuffer *buffer = 0);
|
||||
bool QueueAccepts();
|
||||
|
||||
public:
|
||||
TCPServer(int priorityLevel);
|
||||
virtual ~TCPServer();
|
||||
|
||||
bool ValidServer();
|
||||
Port GetPort();
|
||||
|
||||
bool Bind(bool onlySupportIPv4, Port port = 0);
|
||||
void Close();
|
||||
|
||||
protected:
|
||||
// Return true to release overlapped object memory, or return false to keep it
|
||||
virtual bool OnAccept(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual TCPConnexion *InstantiateServerConnexion() = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_TCP_SERVER_HPP
|
||||
105
DependentExtensions/cat/net/win/UDPEndpoint.hpp
Normal file
105
DependentExtensions/cat/net/win/UDPEndpoint.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_UDP_ENDPOINT_HPP
|
||||
#define CAT_UDP_ENDPOINT_HPP
|
||||
|
||||
/*
|
||||
Windows version of thread pool sockets with IO Completion Ports
|
||||
|
||||
Included from <cat/net/ThreadPoolSockets.hpp>
|
||||
Do not include directly
|
||||
*/
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
class UDPEndpoint
|
||||
|
||||
Object that represents a UDP endpoint bound to a single port
|
||||
*/
|
||||
class UDPEndpoint : public ThreadRefObject
|
||||
{
|
||||
Socket _socket;
|
||||
Port _port;
|
||||
volatile u32 _closing;
|
||||
bool _ipv6;
|
||||
|
||||
struct RecvFromTag
|
||||
{
|
||||
// Not necessarily an IPv6 address, but we allocate enough space for one
|
||||
int addrLen;
|
||||
sockaddr_in6 addr;
|
||||
};
|
||||
|
||||
public:
|
||||
UDPEndpoint(int priorityLevel);
|
||||
virtual ~UDPEndpoint();
|
||||
|
||||
CAT_INLINE bool Valid() { return _socket != SOCKET_ERROR; }
|
||||
Port GetPort();
|
||||
|
||||
// Is6() result is only valid AFTER Bind()
|
||||
CAT_INLINE bool Is6() { return _ipv6; }
|
||||
CAT_INLINE bool IsClosed() { return _closing != 0; }
|
||||
|
||||
// For servers: Bind() with ignoreUnreachable = true ((default))
|
||||
// For clients: Bind() with ignoreUnreachable = false and call this
|
||||
// after the first packet from the server is received.
|
||||
bool IgnoreUnreachable();
|
||||
|
||||
// Disabled by default; useful for MTU discovery
|
||||
bool DontFragment(bool df = true);
|
||||
|
||||
void Close(); // Invalidates this object
|
||||
bool Bind(bool onlySupportIPv4, Port port = 0, bool ignoreUnreachable = true, int kernelReceiveBufferBytes = 0);
|
||||
bool QueueWSARecvFrom();
|
||||
|
||||
// If Is6() == true, the address must be promoted to IPv6
|
||||
// before calling PostWrite() with addr.PromoteTo6()
|
||||
// skip_bytes: Number of bytes to skip at the start of the post buffer
|
||||
bool Post(const NetAddr &addr, u8 *data, u32 data_bytes, u32 skip_bytes = 0);
|
||||
|
||||
private:
|
||||
bool Read(AsyncBuffer *buffer = 0);
|
||||
|
||||
bool OnReadComplete(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
bool OnWriteComplete(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes);
|
||||
|
||||
protected:
|
||||
virtual void OnRead(ThreadPoolLocalStorage *tls, const NetAddr &addr, u8 *data, u32 bytes) = 0; // false = close
|
||||
virtual bool OnWrite(ThreadPoolLocalStorage *tls, AsyncBuffer *buffer, u32 bytes) { return true; } // false = do not delete AsyncBase object
|
||||
virtual void OnClose() = 0;
|
||||
virtual void OnUnreachable(const NetAddr &addr) {} // Only IP is valid
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_UDP_ENDPOINT_HPP
|
||||
214
DependentExtensions/cat/parse/BitStream.hpp
Normal file
214
DependentExtensions/cat/parse/BitStream.hpp
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Not currently being maintained.
|
||||
|
||||
// FIXME: Big-endian code is untested
|
||||
// FIXME: Not suitable for storing large buffers > 500 MB in size
|
||||
|
||||
#ifndef CAT_BIT_STREAM_HPP
|
||||
#define CAT_BIT_STREAM_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
//// BitStream manipulators ////
|
||||
|
||||
namespace bs_bit
|
||||
{
|
||||
template<u32 N_BITS> struct set
|
||||
{
|
||||
u32 bits;
|
||||
set(u32 c_bits) : bits(c_bits) { }
|
||||
};
|
||||
|
||||
template<u32 N_BITS> struct get
|
||||
{
|
||||
u32 &ref;
|
||||
get(u32 &c_ref) : ref(c_ref) { }
|
||||
};
|
||||
}
|
||||
|
||||
namespace bs_byte
|
||||
{
|
||||
struct set
|
||||
{
|
||||
u32 bytes;
|
||||
const void *ref;
|
||||
|
||||
set(u32 b, const void *r) : ref(r), bytes(b) { }
|
||||
};
|
||||
|
||||
struct get
|
||||
{
|
||||
u32 bytes;
|
||||
void *ref;
|
||||
|
||||
get(u32 b, void *r) : ref(r), bytes(b) { }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//// BitStream ////
|
||||
|
||||
class BitStream
|
||||
{
|
||||
bool fixed_buffer;
|
||||
u8 *buffer;
|
||||
u32 buffer_bytes;
|
||||
bool read_underrun;
|
||||
|
||||
// grow to be able to write a number of bits
|
||||
void grow(u32 bits);
|
||||
|
||||
public:
|
||||
u32 read_offset, write_offset; // in bits
|
||||
|
||||
public:
|
||||
BitStream(u32 bytes = 0, void *vbuffer = 0);
|
||||
~BitStream();
|
||||
|
||||
// free unused buffer space
|
||||
void shrink();
|
||||
|
||||
public:
|
||||
u8 *get() { return buffer; }
|
||||
|
||||
bool aligned() { return read_offset % 8 == 0; }
|
||||
u8 *peek() { return buffer + read_offset / 8; }
|
||||
|
||||
public:
|
||||
// returns true iff the buffer is valid
|
||||
bool valid() { return buffer != 0; }
|
||||
|
||||
// returns count of remaining readable bits
|
||||
int unread() { return write_offset - read_offset; }
|
||||
|
||||
// returns true if a recent read operation would have overrun the buffer
|
||||
bool underrun();
|
||||
|
||||
// skip ahead a number of bits
|
||||
void skip(u32 bits);
|
||||
|
||||
public:
|
||||
// insertion
|
||||
void write1(u8 data); // data MUST be 1 or 0
|
||||
|
||||
template<class T> void write(T data)
|
||||
{
|
||||
grow(sizeof(T) * 8);
|
||||
|
||||
u32 byte_offset = write_offset / 8;
|
||||
u32 shift = write_offset % 8;
|
||||
|
||||
if (shift)
|
||||
{
|
||||
buffer[byte_offset] |= (u8)(data << shift);
|
||||
data = data >> (8 - shift);
|
||||
++byte_offset;
|
||||
}
|
||||
|
||||
*(T*)(buffer + byte_offset) = data;
|
||||
|
||||
write_offset += sizeof(T) * 8;
|
||||
}
|
||||
template<> void write(s8 data) { write((u8)data); }
|
||||
template<> void write(s16 data) { write((u16)data); }
|
||||
template<> void write(s32 data) { write((u32)data); }
|
||||
template<> void write(s64 data) { write((u64)data); }
|
||||
template<> void write(float data) { write(*(u32*)&data); }
|
||||
template<> void write(double data) { write(*(u64*)&data); }
|
||||
|
||||
void writeBits(u32 data, int count);
|
||||
void writeBytes(const void *data, u32 byte_count);
|
||||
|
||||
public:
|
||||
// stream-mode insertion
|
||||
BitStream &operator<<(const char *data) { writeBytes(data, (u32)strlen(data)); return *this; }
|
||||
|
||||
template<class T> BitStream &operator<<(T data) { write(data); return *this; }
|
||||
|
||||
template<u32 N_BITS> BitStream &operator<<(const bs_bit::set<N_BITS> &n) { writeBits(n.bits, N_BITS); return *this; }
|
||||
template<> BitStream &operator<<(const bs_bit::set<1> &n) { write1((u8)n.bits); return *this; }
|
||||
template<> BitStream &operator<<(const bs_bit::set<8> &n) { write((u8)n.bits); return *this; }
|
||||
template<> BitStream &operator<<(const bs_bit::set<16> &n) { write((u16)n.bits); return *this; }
|
||||
template<> BitStream &operator<<(const bs_bit::set<32> &n) { write((u32)n.bits); return *this; }
|
||||
|
||||
BitStream &operator<<(const bs_byte::set &n) { writeBytes(n.ref, n.bytes); return *this; }
|
||||
|
||||
public:
|
||||
// extraction
|
||||
u8 read1();
|
||||
|
||||
template<class T> void read(T &data)
|
||||
{
|
||||
const u32 bits = sizeof(T) * 8;
|
||||
|
||||
if (read_offset + bits > write_offset)
|
||||
{
|
||||
read_underrun = true;
|
||||
return;
|
||||
}
|
||||
|
||||
u32 byte_offset = read_offset / 8;
|
||||
u32 shift = read_offset % 8;
|
||||
|
||||
if (shift)
|
||||
data = (*(T*)(buffer + byte_offset + 1) << (8 - shift)) | (buffer[byte_offset] >> shift);
|
||||
else
|
||||
data = *(T*)(buffer + byte_offset);
|
||||
|
||||
read_offset += bits;
|
||||
}
|
||||
template<> void read(float &data) { read((u32&)data); }
|
||||
template<> void read(double &data) { write(*(u64*)&data); }
|
||||
template<class T> T read() { T temp; read(temp); return temp; }
|
||||
|
||||
u32 readBits(u32 count);
|
||||
void readBytes(void *data, u32 byte_count);
|
||||
|
||||
public:
|
||||
// stream-mode extraction
|
||||
template<class T> BitStream &operator>>(T &data) { read(data); return *this; }
|
||||
|
||||
template<u32 N_BITS> BitStream &operator>>(const bs_bit::get<N_BITS> &n) { n.ref = readBits(N_BITS); return *this; }
|
||||
template<> BitStream &operator>>(const bs_bit::get<1> &n) { n.ref = read1(); return *this; }
|
||||
template<> BitStream &operator>>(const bs_bit::get<8> &n) { n.ref = read<u8>(); return *this; }
|
||||
template<> BitStream &operator>>(const bs_bit::get<16> &n) { n.ref = read<u16>(); return *this; }
|
||||
template<> BitStream &operator>>(const bs_bit::get<32> &n) { read(n.ref); return *this; }
|
||||
|
||||
BitStream &operator>>(const bs_byte::get &n) { readBytes(n.ref, n.bytes); return *this; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BIT_STREAM_HPP
|
||||
|
||||
114
DependentExtensions/cat/parse/BufferStream.hpp
Normal file
114
DependentExtensions/cat/parse/BufferStream.hpp
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BUFFER_STREAM_HPP
|
||||
#define CAT_BUFFER_STREAM_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
BufferStream
|
||||
|
||||
Extremely light-weight wrapper for a buffer data insertion and extraction.
|
||||
|
||||
Performs automatic endian conversion into and out of the buffer (sometimes).
|
||||
|
||||
Performs no checking for buffer overruns.
|
||||
This class does not add any security to your code; it just makes it shorter.
|
||||
Use at your peril.
|
||||
*/
|
||||
class BufferStream
|
||||
{
|
||||
protected:
|
||||
u8 *_buffer;
|
||||
|
||||
public:
|
||||
CAT_INLINE BufferStream(u8 *buffer) { _buffer = buffer; }
|
||||
CAT_INLINE BufferStream &operator=(u8 *buffer) { _buffer = buffer; }
|
||||
|
||||
CAT_INLINE u32 GetOffset(void *buffer) { return (u32)(_buffer - reinterpret_cast<u8*>( buffer )); }
|
||||
|
||||
public:
|
||||
// Auto-cast to u8* or char*
|
||||
CAT_INLINE operator u8*() { return _buffer; }
|
||||
CAT_INLINE char *c_str() { return reinterpret_cast<char*>( _buffer ); }
|
||||
|
||||
CAT_INLINE BufferStream &operator++() { _buffer++; return *this; }
|
||||
CAT_INLINE BufferStream &operator+=(int skip_bytes) { _buffer += skip_bytes; return *this; }
|
||||
|
||||
public:
|
||||
// Insertion
|
||||
CAT_INLINE BufferStream &operator<<(s8 data) { *_buffer++ = (u8)data; return *this; }
|
||||
CAT_INLINE BufferStream &operator<<(s16 data) { *(u16*)_buffer = getLE16((u16)data); _buffer += 2; return *this; }
|
||||
CAT_INLINE BufferStream &operator<<(s32 data) { *(u32*)_buffer = getLE32((u32)data); _buffer += 4; return *this; }
|
||||
CAT_INLINE BufferStream &operator<<(s64 data) { *(u64*)_buffer = getLE64((u64)data); _buffer += 8; return *this; }
|
||||
|
||||
CAT_INLINE BufferStream &operator<<(u8 data) { *_buffer++ = data; return *this; }
|
||||
CAT_INLINE BufferStream &operator<<(u16 data) { *(u16*)_buffer = getLE16(data); _buffer += 2; return *this; }
|
||||
CAT_INLINE BufferStream &operator<<(u32 data) { *(u32*)_buffer = getLE32(data); _buffer += 4; return *this; }
|
||||
CAT_INLINE BufferStream &operator<<(u64 data) { *(u64*)_buffer = getLE64(data); _buffer += 8; return *this; }
|
||||
|
||||
CAT_INLINE void write(const void *data, u32 bytes)
|
||||
{
|
||||
memcpy(_buffer, data, bytes);
|
||||
_buffer += bytes;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE BufferStream &operator<<(const T &data) { write(&data, sizeof(T)); return *this; }
|
||||
|
||||
public:
|
||||
// Extraction
|
||||
CAT_INLINE BufferStream &operator>>(s8 &data) { data = (s8)*_buffer++; return *this; }
|
||||
CAT_INLINE BufferStream &operator>>(s16 &data) { data = (s16)getLE16(*(u16*)_buffer); _buffer += 2; return *this; }
|
||||
CAT_INLINE BufferStream &operator>>(s32 &data) { data = (s32)getLE32(*(u32*)_buffer); _buffer += 4; return *this; }
|
||||
CAT_INLINE BufferStream &operator>>(s64 &data) { data = (s64)getLE64(*(u64*)_buffer); _buffer += 8; return *this; }
|
||||
|
||||
CAT_INLINE BufferStream &operator>>(u8 &data) { data = *_buffer++; return *this; }
|
||||
CAT_INLINE BufferStream &operator>>(u16 &data) { data = getLE16(*(u16*)_buffer); _buffer += 2; return *this; }
|
||||
CAT_INLINE BufferStream &operator>>(u32 &data) { data = getLE32(*(u32*)_buffer); _buffer += 4; return *this; }
|
||||
CAT_INLINE BufferStream &operator>>(u64 &data) { data = getLE64(*(u64*)_buffer); _buffer += 8; return *this; }
|
||||
|
||||
CAT_INLINE void read(void *data, u32 bytes)
|
||||
{
|
||||
memcpy(data, _buffer, bytes);
|
||||
_buffer += bytes;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
CAT_INLINE BufferStream &operator>>(T &data) { read(&data, sizeof(T)); return *this; }
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BUFFER_STREAM_HPP
|
||||
105
DependentExtensions/cat/parse/BufferTok.hpp
Normal file
105
DependentExtensions/cat/parse/BufferTok.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_BUFFER_TOK_HPP
|
||||
#define CAT_BUFFER_TOK_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
/*
|
||||
MyBuf = " 123 5 : 6 "
|
||||
|
||||
BufferTok bt(MyBuf, 256);
|
||||
|
||||
int a, b, c;
|
||||
bt() >> a; // empty delimiter means white space and newlines
|
||||
bt(':') >> b >> c;
|
||||
if (!bt) // out of buffer space
|
||||
*/
|
||||
|
||||
// Tokenize a buffer
|
||||
class BufferTok
|
||||
{
|
||||
const char *buffer;
|
||||
int len;
|
||||
|
||||
char delimiter;
|
||||
bool newline;
|
||||
|
||||
u32 readNext(char *token, u32 tokenBufferSize);
|
||||
|
||||
public:
|
||||
BufferTok(const char *buffer, int len);
|
||||
|
||||
// Returns true when the buffer is empty
|
||||
inline bool operator!() { return len <= 0; }
|
||||
|
||||
// Returns true when the buffer extraction is stuck on a new line
|
||||
// Use operator[] to reset this flag
|
||||
inline bool onNewline() { return newline; }
|
||||
|
||||
/*
|
||||
* operator(char)
|
||||
* Set the delimiter character
|
||||
*
|
||||
* This character is used to find the end of the current token
|
||||
* Newlines are always a delimiter
|
||||
*/
|
||||
BufferTok &operator()(char ch = 0);
|
||||
|
||||
/*
|
||||
* Same as operator(), see above
|
||||
*
|
||||
* Also resets the newline() flag, so that data can start being
|
||||
* read from the next line. If newline() wasn't set, it searches
|
||||
* for the next line to start reading.
|
||||
*/
|
||||
BufferTok &operator[](char ch);
|
||||
|
||||
/*
|
||||
* operator>>
|
||||
* Extract a token
|
||||
*
|
||||
* Strips whitespace and the end-of-token delimiter
|
||||
* Newlines are always a delimiter
|
||||
*
|
||||
* After the tokenizer encounters a newline, it will continue
|
||||
* returning no results with newline() flag set, until the
|
||||
* delimiter is reset with [], so incomplete lines don't wrap.
|
||||
*/
|
||||
BufferTok &operator>>(int &n);
|
||||
BufferTok &operator>>(char *n); // buffer must have at least 256 characters
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_BUFFER_TOK_HPP
|
||||
2108
DependentExtensions/cat/parse/FastDelegate.h
Normal file
2108
DependentExtensions/cat/parse/FastDelegate.h
Normal file
File diff suppressed because it is too large
Load Diff
54
DependentExtensions/cat/parse/MessageRouter.hpp
Normal file
54
DependentExtensions/cat/parse/MessageRouter.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_MESSAGE_ROUTER_HPP
|
||||
#define CAT_MESSAGE_ROUTER_HPP
|
||||
|
||||
#include <cat/parse/BitStream.hpp>
|
||||
#include <cat/port/FastDelegate.h>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
typedef fastdelegate::FastDelegate<void (BitStream &m)> MessageHandler;
|
||||
|
||||
class MessageRouter
|
||||
{
|
||||
MessageHandler handlers[256];
|
||||
|
||||
public:
|
||||
void Set(u8 opcode, const MessageHandler &handler);
|
||||
void Clear(u8 opcode);
|
||||
|
||||
void Invoke(u8 opcode, BitStream &msg);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_MESSAGE_ROUTER_HPP
|
||||
271
DependentExtensions/cat/port/AlignedAlloc.hpp
Normal file
271
DependentExtensions/cat/port/AlignedAlloc.hpp
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_ALIGNED_ALLOC_HPP
|
||||
#define CAT_ALIGNED_ALLOC_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <vector> // std::_Construct and std::_Destroy
|
||||
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Small to medium -size aligned heap allocator
|
||||
class Aligned
|
||||
{
|
||||
public:
|
||||
CAT_INLINE Aligned() {}
|
||||
|
||||
// Acquires memory aligned to a CPU cache-line byte boundary from the heap
|
||||
static void *Acquire(u32 bytes);
|
||||
|
||||
// Resizes an aligned pointer
|
||||
static void *Resize(void *ptr, u32 bytes);
|
||||
|
||||
// Release an aligned pointer
|
||||
static void Release(void *ptr);
|
||||
|
||||
template<class T>
|
||||
static inline void Delete(T *ptr)
|
||||
{
|
||||
ptr->~T();
|
||||
Release(ptr);
|
||||
}
|
||||
|
||||
static Aligned ii;
|
||||
};
|
||||
|
||||
#if 0
|
||||
// Use STLAlignedAllocator in place of the standard STL allocator
|
||||
// to make use of the Aligned in STL types.
|
||||
template<typename T>
|
||||
class STLAlignedAllocator
|
||||
{
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef std::size_t difference_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template<typename S>
|
||||
struct rebind
|
||||
{
|
||||
typedef STLAlignedAllocator<S> other;
|
||||
};
|
||||
|
||||
pointer address(reference X) const
|
||||
{
|
||||
return &X;
|
||||
}
|
||||
|
||||
const_pointer address(const_reference X) const
|
||||
{
|
||||
return &X;
|
||||
}
|
||||
|
||||
STLAlignedAllocator() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
STLAlignedAllocator(const STLAlignedAllocator<S> &cp) throw ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
STLAlignedAllocator<T> &operator=(const STLAlignedAllocator<S> &cp) throw ()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
pointer allocate(size_type Count, const void *Hint = 0)
|
||||
{
|
||||
return (pointer)Aligned::Acquire((u32)Count * sizeof(T));
|
||||
}
|
||||
|
||||
void deallocate(pointer Ptr, size_type Count)
|
||||
{
|
||||
Aligned::Release(Ptr);
|
||||
}
|
||||
|
||||
void construct(pointer Ptr, const T &Val)
|
||||
{
|
||||
std::_Construct(Ptr, Val);
|
||||
}
|
||||
|
||||
void destroy(pointer Ptr)
|
||||
{
|
||||
std::_Destroy(Ptr);
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return 0x00FFFFFF;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool operator==(STLAlignedAllocator <S> const &) const throw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool operator!=(STLAlignedAllocator <S> const &) const throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// Large-size aligned heap allocator
|
||||
class LargeAligned
|
||||
{
|
||||
public:
|
||||
// Acquires memory aligned to a CPU cache-line byte boundary from the heap
|
||||
static void *Acquire(u32 bytes);
|
||||
|
||||
// Release an aligned pointer
|
||||
static void Release(void *ptr);
|
||||
};
|
||||
|
||||
#if 0
|
||||
// Use STLAlignedAllocator in place of the standard STL allocator
|
||||
// to make use of the Aligned in STL types.
|
||||
template<typename T>
|
||||
class STLLargeAlignedAllocator
|
||||
{
|
||||
public:
|
||||
typedef std::size_t size_type;
|
||||
typedef std::size_t difference_type;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template<typename S>
|
||||
struct rebind
|
||||
{
|
||||
typedef STLLargeAlignedAllocator<S> other;
|
||||
};
|
||||
|
||||
pointer address(reference X) const
|
||||
{
|
||||
return &X;
|
||||
}
|
||||
|
||||
const_pointer address(const_reference X) const
|
||||
{
|
||||
return &X;
|
||||
}
|
||||
|
||||
STLLargeAlignedAllocator() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
STLLargeAlignedAllocator(const STLLargeAlignedAllocator<S> &cp) throw ()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
STLLargeAlignedAllocator<T> &operator=(const STLLargeAlignedAllocator<S> &cp) throw ()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
pointer allocate(size_type Count, const void *Hint = 0)
|
||||
{
|
||||
return (pointer)LargeAligned::Acquire((u32)Count * sizeof(T));
|
||||
}
|
||||
|
||||
void deallocate(pointer Ptr, size_type Count)
|
||||
{
|
||||
LargeAligned::Release(Ptr);
|
||||
}
|
||||
|
||||
void construct(pointer Ptr, const T &Val)
|
||||
{
|
||||
std::_Construct(Ptr, Val);
|
||||
}
|
||||
|
||||
void destroy(pointer Ptr)
|
||||
{
|
||||
std::_Destroy(Ptr);
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return 0x00FFFFFF;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool operator==(STLLargeAlignedAllocator <S> const &) const throw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool operator!=(STLLargeAlignedAllocator <S> const &) const throw()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
u32 GetCacheLineBytes();
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
// Provide placement new constructor and delete pair to allow for
|
||||
// an easy syntax to create objects from the RegionAllocator:
|
||||
// T *a = new (Aligned()) T();
|
||||
// The object can be freed with:
|
||||
// Aligned::Delete(a);
|
||||
// Which insures that the destructor is called before freeing memory
|
||||
CAT_INLINE void *operator new[](std::size_t bytes, cat::Aligned &) throw()
|
||||
{
|
||||
return cat::Aligned::Acquire((int)bytes);
|
||||
}
|
||||
|
||||
// Placement "delete": Does not call destructor
|
||||
CAT_INLINE void operator delete(void *ptr, cat::Aligned &) throw()
|
||||
{
|
||||
cat::Aligned::Release(ptr);
|
||||
}
|
||||
|
||||
#endif // CAT_ENDIAN_NEUTRAL_HPP
|
||||
185
DependentExtensions/cat/port/EndianNeutral.hpp
Normal file
185
DependentExtensions/cat/port/EndianNeutral.hpp
Normal file
@ -0,0 +1,185 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_ENDIAN_NEUTRAL_HPP
|
||||
#define CAT_ENDIAN_NEUTRAL_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// getLE() converts from little-endian word to native byte-order word
|
||||
// getBE() converts from big-endian word to native byte-order word
|
||||
|
||||
template<typename T>
|
||||
CAT_INLINE T NoChangeNeeded(const T t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
#if defined(CAT_ENDIAN_LITTLE)
|
||||
|
||||
# define swapLE(n) NoChangeNeeded(n)
|
||||
# define getLE(n) NoChangeNeeded(n)
|
||||
# define getLE16(n) NoChangeNeeded(n)
|
||||
# define getLE32(n) NoChangeNeeded(n)
|
||||
# define getLE64(n) NoChangeNeeded(n)
|
||||
|
||||
CAT_INLINE u16 swapBE(u16 &n) { return n = CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 swapBE(u32 &n) { return n = CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 swapBE(u64 &n) { return n = CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getBE(u16 n) { return CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getBE(u32 n) { return CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getBE(u64 n) { return CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getBE16(u16 n) { return CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getBE32(u32 n) { return CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getBE64(u64 n) { return CAT_BOSWAP64(n); }
|
||||
CAT_INLINE s16 swapBE(s16 &n) { return n = CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 swapBE(s32 &n) { return n = CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 swapBE(s64 &n) { return n = CAT_BOSWAP64((u64)n); }
|
||||
CAT_INLINE s16 getBE(s16 n) { return CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 getBE(s32 n) { return CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 getBE(s64 n) { return CAT_BOSWAP64((u64)n); }
|
||||
|
||||
CAT_INLINE float getBE(float n) {
|
||||
Float32 c = n;
|
||||
c.i = CAT_BOSWAP32(c.i);
|
||||
return c.f;
|
||||
}
|
||||
|
||||
#elif defined(CAT_ENDIAN_BIG)
|
||||
|
||||
# define swapBE(n) NoChangeNeeded(n)
|
||||
# define getBE(n) NoChangeNeeded(n)
|
||||
# define getBE16(n) NoChangeNeeded(n)
|
||||
# define getBE32(n) NoChangeNeeded(n)
|
||||
# define getBE64(n) NoChangeNeeded(n)
|
||||
|
||||
CAT_INLINE u16 swapLE(u16 &n) { return n = CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 swapLE(u32 &n) { return n = CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 swapLE(u64 &n) { return n = CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getLE(u16 n) { return CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getLE(u32 n) { return CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getLE(u64 n) { return CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getLE16(u16 n) { return CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getLE32(u32 n) { return CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getLE64(u64 n) { return CAT_BOSWAP64(n); }
|
||||
CAT_INLINE s16 swapLE(s16 &n) { return n = CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 swapLE(s32 &n) { return n = CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 swapLE(s64 &n) { return n = CAT_BOSWAP64((u64)n); }
|
||||
CAT_INLINE s16 getLE(s16 n) { return CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 getLE(s32 n) { return CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 getLE(s64 n) { return CAT_BOSWAP64((u64)n); }
|
||||
|
||||
CAT_INLINE float getLE(float n) {
|
||||
Float32 c = n;
|
||||
c.i = CAT_BOSWAP32(c.i);
|
||||
return c.f;
|
||||
}
|
||||
|
||||
#elif defined(CAT_ENDIAN_UNKNOWN)
|
||||
|
||||
class RuntimeEndianDetector
|
||||
{
|
||||
public:
|
||||
bool _big_endian, _little_endian;
|
||||
|
||||
RuntimeEndianDetector();
|
||||
};
|
||||
|
||||
class Endianness
|
||||
{
|
||||
public:
|
||||
static RuntimeEndianDetector detector;
|
||||
static CAT_INLINE bool IsBigEndian() { return detector._big_endian; }
|
||||
static CAT_INLINE bool IsLittleEndian() { return detector._little_endian; }
|
||||
};
|
||||
|
||||
CAT_INLINE u16 swapBE(u16 &n) { return Endianness::IsBigEndian() ? n : n = CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 swapBE(u32 &n) { return Endianness::IsBigEndian() ? n : n = CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 swapBE(u64 &n) { return Endianness::IsBigEndian() ? n : n = CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getBE(u16 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getBE(u32 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getBE(u64 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getBE16(u16 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getBE32(u32 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getBE64(u64 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP64(n); }
|
||||
CAT_INLINE s16 swapBE(s16 &n) { return Endianness::IsBigEndian() ? n : n = CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 swapBE(s32 &n) { return Endianness::IsBigEndian() ? n : n = CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 swapBE(s64 &n) { return Endianness::IsBigEndian() ? n : n = CAT_BOSWAP64((u64)n); }
|
||||
CAT_INLINE s16 getBE(s16 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 getBE(s32 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 getBE(s64 n) { return Endianness::IsBigEndian() ? n : CAT_BOSWAP64((u64)n); }
|
||||
|
||||
CAT_INLINE float getBE(float n)
|
||||
{
|
||||
if (Endianness::IsBigEndian())
|
||||
return n;
|
||||
else
|
||||
{
|
||||
Float32 c = n;
|
||||
c.i = CAT_BOSWAP32(c.i);
|
||||
return c.f;
|
||||
}
|
||||
}
|
||||
|
||||
CAT_INLINE u16 swapLE(u16 &n) { return Endianness::IsLittleEndian() ? n : n = CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 swapLE(u32 &n) { return Endianness::IsLittleEndian() ? n : n = CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 swapLE(u64 &n) { return Endianness::IsLittleEndian() ? n : n = CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getLE(u16 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getLE(u32 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getLE(u64 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP64(n); }
|
||||
CAT_INLINE u16 getLE16(u16 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP16(n); }
|
||||
CAT_INLINE u32 getLE32(u32 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP32(n); }
|
||||
CAT_INLINE u64 getLE64(u64 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP64(n); }
|
||||
CAT_INLINE s16 swapLE(s16 &n) { return Endianness::IsLittleEndian() ? n : n = CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 swapLE(s32 &n) { return Endianness::IsLittleEndian() ? n : n = CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 swapLE(s64 &n) { return Endianness::IsLittleEndian() ? n : n = CAT_BOSWAP64((u64)n); }
|
||||
CAT_INLINE s16 getLE(s16 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP16((u16)n); }
|
||||
CAT_INLINE s32 getLE(s32 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP32((u32)n); }
|
||||
CAT_INLINE s64 getLE(s64 n) { return Endianness::IsLittleEndian() ? n : CAT_BOSWAP64((u64)n); }
|
||||
|
||||
CAT_INLINE float getLE(float n)
|
||||
{
|
||||
if (Endianness::IsLittleEndian())
|
||||
return n;
|
||||
else
|
||||
{
|
||||
Float32 c = n;
|
||||
c.i = CAT_BOSWAP32(c.i);
|
||||
return c.f;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_ENDIAN_NEUTRAL_HPP
|
||||
40
DependentExtensions/cat/port/WindowsInclude.hpp
Normal file
40
DependentExtensions/cat/port/WindowsInclude.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_WINDOWS_INCLUDE_HPP
|
||||
#define CAT_WINDOWS_INCLUDE_HPP
|
||||
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0502 /* Windows XP SP2 or later */
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#endif // CAT_WINDOWS_INCLUDE_HPP
|
||||
76
DependentExtensions/cat/rand/IRandom.hpp
Normal file
76
DependentExtensions/cat/rand/IRandom.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_I_RANDOM_HPP
|
||||
#define CAT_I_RANDOM_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Pseudo-random number generators will derive from IRandom and implement its public methods
|
||||
// WARNING: Not seeded by default. Be sure to call Initialize() before Generate()
|
||||
class IRandom
|
||||
{
|
||||
public:
|
||||
virtual ~IRandom() {}
|
||||
|
||||
// Generate a 32-bit random number
|
||||
virtual u32 Generate() = 0;
|
||||
|
||||
// Generate a variable number of random bytes
|
||||
virtual void Generate(void *buffer, int bytes) = 0;
|
||||
|
||||
public:
|
||||
// Generate a 32-bit random number in the range [low..high] inclusive
|
||||
u32 GenerateUnbiased(u32 low, u32 high)
|
||||
{
|
||||
u32 range = high - low;
|
||||
|
||||
// Round range up to the next pow(2)-1 using a Stanford Bit Twiddling Hack
|
||||
u32 v = range - 1;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
|
||||
// Generate an unbiased random number in the inclusive range [0..(high-low)]
|
||||
u32 x;
|
||||
do x = Generate() & v;
|
||||
while (x > range);
|
||||
|
||||
return low + x;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_I_RANDOM_HPP
|
||||
90
DependentExtensions/cat/rand/MersenneTwister.hpp
Normal file
90
DependentExtensions/cat/rand/MersenneTwister.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Algorithm by Makoto Matsumoto
|
||||
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
|
||||
*/
|
||||
|
||||
#ifndef CAT_MERSENNE_TWISTER_HPP
|
||||
#define CAT_MERSENNE_TWISTER_HPP
|
||||
|
||||
#include <cat/rand/IRandom.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Noncryptographic pseudo-random number generator
|
||||
class MersenneTwister : public IRandom
|
||||
{
|
||||
static const u32 MEXP = 19937;
|
||||
static const u32 N128 = MEXP/128 + 1;
|
||||
static const u32 N64 = N128 * 2;
|
||||
static const u32 N32 = N128 * 4;
|
||||
static const u32 POS1 = 122;
|
||||
static const u32 SL1 = 18;
|
||||
static const u32 SL2 = 1;
|
||||
static const u32 SL2BITS = SL2*8;
|
||||
static const u32 SR1 = 11;
|
||||
static const u32 SR2 = 1;
|
||||
static const u32 SR2BITS = SR2*8;
|
||||
static const u32 MSK1 = 0xdfffffefU;
|
||||
static const u32 MSK2 = 0xddfecb7fU;
|
||||
static const u32 MSK3 = 0xbffaffffU;
|
||||
static const u32 MSK4 = 0xbffffff6U;
|
||||
|
||||
struct MT128 {
|
||||
u32 u[4];
|
||||
};
|
||||
|
||||
MT128 state[19937/128 + 1];
|
||||
u32 *state32;
|
||||
u32 used;
|
||||
|
||||
CAT_INLINE void shiftLeft128(MT128 *r, MT128 *n, u32 bits);
|
||||
CAT_INLINE void shiftRight128(MT128 *r, MT128 *n, u32 bits);
|
||||
|
||||
void enforcePeriod(); // make corrections to ensure that the generator has the full period
|
||||
void round(MT128 *a, MT128 *b, MT128 *c, MT128 *d); // a = MTMIX(a,b,c,d)
|
||||
void update(); // permute the existing state into a new one
|
||||
|
||||
public:
|
||||
MersenneTwister();
|
||||
|
||||
bool Initialize(u32 seed);
|
||||
bool Initialize(u32 *seeds, u32 words);
|
||||
bool Initialize();
|
||||
|
||||
u32 Generate(); // generate a 32-bit number
|
||||
void Generate(void *buffer, int bytes); // generate a series of random numbers
|
||||
};
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_MERSENNE_TWISTER_HPP
|
||||
66
DependentExtensions/cat/rand/StdRand.hpp
Normal file
66
DependentExtensions/cat/rand/StdRand.hpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CAT_STDRAND_HPP
|
||||
#define CAT_STDRAND_HPP
|
||||
|
||||
#include <cat/Platform.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
|
||||
// Microsoft VC++ 7.0 stdlib srand(), rand(), old RANDU()
|
||||
class StandardRand
|
||||
{
|
||||
protected:
|
||||
s32 seed;
|
||||
|
||||
public:
|
||||
StandardRand(u32 ns = 0) { seed = ns; }
|
||||
|
||||
inline void srand32(u32 ns) { seed = ns; } // 32-bit version
|
||||
inline void srand16(u16 ns) { seed = ns; } // 16-bit version (yup)
|
||||
|
||||
u16 rand(); // Linear Congruential Generator: X = X * M + A (mod N)
|
||||
u16 randu(); // RANDU LCG: X = X * M (mod N)
|
||||
float sfrand(); // Fast [-1.f,1.f] generator from Inigo Quilez (2005)
|
||||
};
|
||||
|
||||
|
||||
// Non-linear congruential 32-bit random mixing function for given x, y and seed
|
||||
// This function is used in every example of Perlin noise I found online for some reason!
|
||||
u32 NLCRand32(int x, int y, u32 seed);
|
||||
|
||||
// Uses NLCRand32 as a front-end, and then maps the output to a number between -1 and 1
|
||||
float NLCRandNorm(int x, int y, u32 seed);
|
||||
|
||||
|
||||
|
||||
} // namespace cat
|
||||
|
||||
#endif // CAT_STDRAND_HPP
|
||||
118
DependentExtensions/cat/src/Framework.cpp
Normal file
118
DependentExtensions/cat/src/Framework.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/AllFramework.hpp>
|
||||
using namespace cat;
|
||||
|
||||
static DNSClient *dns_client = 0;
|
||||
|
||||
// Framework Initialize
|
||||
bool cat::InitializeFramework(const char *settings_file, const char *service_name)
|
||||
{
|
||||
// Initialize clock subsystem
|
||||
if (!Clock::Initialize())
|
||||
{
|
||||
FatalStop("Clock subsystem failed to initialize");
|
||||
}
|
||||
|
||||
// Initialize custom memory allocator subsystem
|
||||
if (!RegionAllocator::ref()->Valid())
|
||||
{
|
||||
FatalStop("Custom memory allocator failed to initialize");
|
||||
}
|
||||
|
||||
// Initialize logging subsystem with INFO reporting level
|
||||
Logging::ref()->Initialize(LVL_INFO);
|
||||
if (service_name) Logging::ii->EnableServiceMode(service_name);
|
||||
|
||||
// Initialize disk settings subsystem
|
||||
Settings::ref()->readSettingsFromFile(settings_file);
|
||||
|
||||
// Read logging subsystem settings
|
||||
Logging::ref()->ReadSettings();
|
||||
|
||||
// Start the CSPRNG subsystem
|
||||
if (!FortunaFactory::ref()->Initialize())
|
||||
{
|
||||
FATAL("Framework") << "Unable to initialize the CSPRNG";
|
||||
ShutdownFramework(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the socket subsystem
|
||||
if (!StartupSockets())
|
||||
{
|
||||
FATAL("Framework") << "Unable to initialize Sockets: " << SocketGetLastErrorString();
|
||||
ShutdownFramework(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the worker threads
|
||||
if (!ThreadPool::ref()->Startup())
|
||||
{
|
||||
FATAL("Framework") << "Unable to initialize the ThreadPool";
|
||||
ShutdownFramework(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create DNSClient
|
||||
if (!DNSClient::ref())
|
||||
{
|
||||
FATAL("Framework") << "Out of memory: Unable to create the DNSClient";
|
||||
ShutdownFramework(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add a reference so that DNSClient cannot be destroyed
|
||||
DNSClient::ii->AddRef();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Framework Shutdown
|
||||
void cat::ShutdownFramework(bool WriteSettings)
|
||||
{
|
||||
// Shutdown DNS client
|
||||
DNSClient::ref()->Shutdown();
|
||||
|
||||
// Terminate worker threads
|
||||
ThreadPool::ref()->Shutdown();
|
||||
|
||||
// Terminate sockets
|
||||
CleanupSockets();
|
||||
|
||||
// Terminate the entropy collection thread in the CSPRNG
|
||||
FortunaFactory::ref()->Shutdown();
|
||||
|
||||
// Write settings to disk if requested
|
||||
if (WriteSettings)
|
||||
Settings::ref()->write();
|
||||
|
||||
// Cleanup clock subsystem
|
||||
Clock::Shutdown();
|
||||
}
|
||||
769
DependentExtensions/cat/src/codec/RangeCoder.cpp
Normal file
769
DependentExtensions/cat/src/codec/RangeCoder.cpp
Normal file
@ -0,0 +1,769 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/codec/RangeCoder.hpp>
|
||||
#include <cat/hash/MurmurHash2.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
using namespace cat;
|
||||
using namespace std;
|
||||
|
||||
const u64 Top = (u64)1 << 56;
|
||||
const u64 MaxRange = (u64)1 << 48;
|
||||
|
||||
#define SYMBOL_LUT_BITS 8
|
||||
#define SYMBOL_LUT_SHIFT (16 - SYMBOL_LUT_BITS)
|
||||
#define SYMBOL_LUT_BYTES (1 << SYMBOL_LUT_BITS)
|
||||
|
||||
#define SYMBOL_BYTES(total) (SYMBOL_LUT_BYTES + (total) - 1)
|
||||
#define STATIC_TABLE_BYTES(total) (4 + 2 + 2 + 256 + 256 + 2 * (total) * SYMBOL_BYTES(total) + (total) * (16 * 4))
|
||||
|
||||
#define GET_SYMBOL_LUT(frequencies, total, index) ((const u8 *)((frequencies) + (index) * SYMBOL_BYTES(total)))
|
||||
#define GET_SYMBOL_BASE(frequencies, total, index) ((const u16 *)(GET_SYMBOL_LUT((frequencies), (total), (index)) + SYMBOL_LUT_BYTES*2))
|
||||
|
||||
|
||||
//// TextStatsCollector
|
||||
|
||||
TextStatsCollector::TextStatsCollector()
|
||||
{
|
||||
CAT_OBJCLR(frequencies);
|
||||
CAT_OBJCLR(seen);
|
||||
last = 0;
|
||||
total = 0;
|
||||
|
||||
// The '\0' null terminator is always symbol 0 and always present
|
||||
seen[0] = 1;
|
||||
total = 1;
|
||||
frequencies[0][0] = 1;
|
||||
}
|
||||
|
||||
void TextStatsCollector::Tally(u8 x)
|
||||
{
|
||||
u32 &tf = frequencies[last][x];
|
||||
|
||||
// Increment frequency in table and check for overflow
|
||||
// 2^24 is used as the limit so that there can be no cumulative
|
||||
// overflow if all the frequencies are added together.
|
||||
if (++tf >= 0x01000000)
|
||||
{
|
||||
// For each symbol that follows the last symbol,
|
||||
for (int ii = 0; ii < 256; ++ii)
|
||||
{
|
||||
u32 &tm = frequencies[last][ii];
|
||||
|
||||
// Divide the frequencies by two
|
||||
if (tm > 1) tm >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!seen[x])
|
||||
{
|
||||
++total;
|
||||
seen[x] = 1;
|
||||
}
|
||||
|
||||
last = x;
|
||||
}
|
||||
|
||||
bool TextStatsCollector::GenerateMinimalStaticTable(const char *TableName, std::ostream &osout)
|
||||
{
|
||||
u32 bytes = STATIC_TABLE_BYTES(total);
|
||||
u8 *output = new u8[bytes + 3];
|
||||
if (!output)
|
||||
{
|
||||
osout << "Out of memory";
|
||||
return false;
|
||||
}
|
||||
|
||||
TableFormat *table = (TableFormat *)output;
|
||||
|
||||
// Write char2index table and some index2char
|
||||
u32 ii, jj;
|
||||
for (jj = 0, ii = 0; ii < 256; ++ii)
|
||||
{
|
||||
if (seen[ii])
|
||||
{
|
||||
table->index2char[jj] = ii;
|
||||
table->char2index[ii] = jj;
|
||||
++jj;
|
||||
}
|
||||
else
|
||||
{
|
||||
table->char2index[ii] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Write remainder of index2char table
|
||||
while (jj < 256)
|
||||
{
|
||||
table->index2char[jj++] = 0;
|
||||
}
|
||||
|
||||
// Generate normalized frequency table
|
||||
u16 *freq = table->frequencies;
|
||||
|
||||
for (ii = 0; ii < total; ++ii)
|
||||
{
|
||||
u32 sum = 0, adjcum = 0;
|
||||
u32 work[256];
|
||||
|
||||
u32 tlast = table->index2char[ii];
|
||||
for (jj = 0; jj < total; ++jj)
|
||||
{
|
||||
sum += frequencies[tlast][table->index2char[jj]];
|
||||
work[jj] = sum;
|
||||
}
|
||||
|
||||
char *dict = (char*)freq;
|
||||
//memcpy(dict, frequent_words[table->index2char[ii]], DICTIONARY_WORDS * DICTIONARY_CHARS);
|
||||
|
||||
//u8 *lut_low = (u8*)(dict + DICTIONARY_WORDS * DICTIONARY_CHARS);
|
||||
u8 *lut_low = (u8*)freq;
|
||||
u8 *lut_high = lut_low + SYMBOL_LUT_BYTES;
|
||||
freq += SYMBOL_LUT_BYTES;
|
||||
|
||||
u16 *symbol_freqs = freq;
|
||||
u32 smax = work[total-1];
|
||||
|
||||
for (jj = 0; jj < total-1; ++jj)
|
||||
{
|
||||
// Normalize the cumulative frequency to the range [0, 2^16)
|
||||
u32 adjcum_new;
|
||||
if (smax)
|
||||
adjcum_new = (u32)(((u64)work[jj] << 32) / smax) >> 16;
|
||||
else
|
||||
adjcum_new = (u32)(((u64)(jj+1) << 32) / total) >> 16;
|
||||
|
||||
// Insure monotonic increase
|
||||
if (adjcum >= adjcum_new) adjcum_new = adjcum + 1;
|
||||
|
||||
adjcum = adjcum_new;
|
||||
*freq++ = (u16)adjcum_new;
|
||||
}
|
||||
|
||||
// It is possible that very unlikely symbols at the end will cause
|
||||
// an overflow since monotonicity is enforced. Detect that overflow
|
||||
// and correct it by borrowing from earlier symbols.
|
||||
if (adjcum >= 0x10000)
|
||||
{
|
||||
u32 count = adjcum - 0xFFFF;
|
||||
u32 last = 0;
|
||||
u32 cumsub = 0;
|
||||
|
||||
for (jj = 0; jj < total-1; ++jj)
|
||||
{
|
||||
u32 slack = symbol_freqs[jj] - last;
|
||||
|
||||
if (slack >= 0x100)
|
||||
cumsub = count;
|
||||
|
||||
symbol_freqs[jj] -= cumsub;
|
||||
}
|
||||
}
|
||||
|
||||
// Write LUT
|
||||
u8 symbol = 0, last_high = 0, last_low = 0;
|
||||
u32 high = 0;
|
||||
|
||||
for (jj = 0; jj < SYMBOL_LUT_BYTES; ++jj)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
high = symbol_freqs[symbol] >> SYMBOL_LUT_SHIFT;
|
||||
|
||||
if (high > jj || symbol >= total - 1)
|
||||
break;
|
||||
|
||||
last_high = symbol++;
|
||||
}
|
||||
|
||||
lut_low[jj] = last_low;
|
||||
lut_high[jj] = last_high;
|
||||
last_low = last_high;
|
||||
}
|
||||
}
|
||||
|
||||
// Write header
|
||||
table->total = total;
|
||||
table->log2total = (u16)(std::log((double)total)/std::log((double)2) * 32768.0f / 8.0f);
|
||||
table->hash = MurmurHash32(output + 4, bytes - 4, 0);
|
||||
|
||||
// Convert it to C code
|
||||
osout << "// To include this table, do something like this:" << endl;
|
||||
osout << "// #include \"" << TableName << ".stats\"" << endl << endl;
|
||||
osout << "static const u32 _" << TableName << "[] = {" << endl;
|
||||
|
||||
u32 words = (bytes + 3)/4;
|
||||
u32 *output32 = (u32*)output;
|
||||
int line = 0;
|
||||
|
||||
while (words--)
|
||||
{
|
||||
//if (!line) osout << " ";
|
||||
|
||||
osout << "0x" << hex << *output32++;
|
||||
|
||||
// Cases for commas and newlines
|
||||
if (words)
|
||||
{
|
||||
osout << ',';
|
||||
if (++line >= 16)
|
||||
{
|
||||
osout << endl;
|
||||
line = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
osout << "};" << endl << endl;
|
||||
|
||||
osout << "static const TextStatsCollector::TableFormat *" << TableName
|
||||
<< " = (const TextStatsCollector::TableFormat*)_" << TableName << ';' << endl;
|
||||
|
||||
// Free memory from workspace
|
||||
delete []output;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for errors in the in-memory version of the table that was generated
|
||||
bool TextStatsCollector::VerifyTableIntegrity(const TableFormat *table)
|
||||
{
|
||||
u32 total = table->total;
|
||||
u32 bytes = STATIC_TABLE_BYTES(total);
|
||||
|
||||
if (MurmurHash32(&table->total, bytes - 4, 0) != table->hash)
|
||||
return false;
|
||||
|
||||
if (table->total > 256)
|
||||
return false;
|
||||
|
||||
int used = 0;
|
||||
for (int ii = 0; ii < 256; ++ii)
|
||||
{
|
||||
u8 index = table->char2index[ii];
|
||||
if (index)
|
||||
{
|
||||
if (table->index2char[index] != ii)
|
||||
return false;
|
||||
|
||||
++used;
|
||||
}
|
||||
}
|
||||
|
||||
if (used + 1 != (int)total)
|
||||
return false;
|
||||
|
||||
u16 flog = (u16)(std::log((double)total)/std::log((double)2) * 32768.0f / 8.0f);
|
||||
if (flog != table->log2total)
|
||||
return false;
|
||||
|
||||
used = 0;
|
||||
for (int ii = 0; ii < 256; ++ii)
|
||||
{
|
||||
if (table->index2char[ii])
|
||||
++used;
|
||||
}
|
||||
|
||||
if (used + 1 != (int)total)
|
||||
return false;
|
||||
|
||||
for (u32 ii = 0; ii < total; ++ii)
|
||||
{
|
||||
u32 last = 0;
|
||||
|
||||
for (u32 jj = 0; jj < total - 1; ++jj)
|
||||
{
|
||||
u32 x = GET_SYMBOL_BASE(table->frequencies, total, ii)[jj];
|
||||
|
||||
if (last >= x)
|
||||
return false;
|
||||
|
||||
//u32 range = x - last;
|
||||
|
||||
last = x;
|
||||
}
|
||||
|
||||
const u8 *lut_low = GET_SYMBOL_LUT(table->frequencies, total, ii);
|
||||
const u8 *lut_high = lut_low + SYMBOL_LUT_BYTES;
|
||||
|
||||
for (u32 jj = 0; jj < SYMBOL_LUT_BYTES; ++jj)
|
||||
{
|
||||
if (lut_low[jj] > lut_high[jj])
|
||||
return false;
|
||||
|
||||
if (lut_low[jj] >= total - 1)
|
||||
return false;
|
||||
|
||||
if (lut_high[jj] >= total - 1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//// RangeEncoder
|
||||
|
||||
// Intializing constructor
|
||||
RangeEncoder::RangeEncoder(void *output_i, int limit_i)
|
||||
{
|
||||
output = (u8*)output_i;
|
||||
remaining = limit = limit_i;
|
||||
|
||||
range = 0;
|
||||
}
|
||||
|
||||
// Copy Constructor
|
||||
// See header for usage
|
||||
RangeEncoder::RangeEncoder(RangeEncoder &cp)
|
||||
{
|
||||
output = cp.output;
|
||||
limit = cp.limit;
|
||||
remaining = cp.remaining;
|
||||
low = cp.low;
|
||||
range = cp.range;
|
||||
}
|
||||
|
||||
// Overwrite one context with another. Using context references instead
|
||||
// of working on the contexts directly is probably more efficient.
|
||||
RangeEncoder &RangeEncoder::operator=(RangeEncoder &cp)
|
||||
{
|
||||
output = cp.output;
|
||||
limit = cp.limit;
|
||||
remaining = cp.remaining;
|
||||
low = cp.low;
|
||||
range = cp.range;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Write out bytes as needed
|
||||
void RangeEncoder::Normalize()
|
||||
{
|
||||
while ((low ^ (low + range)) < Top ||
|
||||
range < MaxRange && ((range = -(s64)low & (MaxRange - 1)),1))
|
||||
{
|
||||
// If we're out of room, fail
|
||||
if (!remaining)
|
||||
{
|
||||
output = 0;
|
||||
return;
|
||||
}
|
||||
--remaining;
|
||||
|
||||
// Store the shifted out byte
|
||||
*output++ = (u8)(low >> 56);
|
||||
range <<= 8;
|
||||
low <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab symbol low frequency and range from the table
|
||||
void RangeEncoder::GetTableSymbol(const TextStatsCollector::TableFormat *stats, u32 &last, u8 ch, u16 &symbol_low, u16 &symbol_range)
|
||||
{
|
||||
u8 symbol = stats->char2index[ch];
|
||||
const u16 *base = GET_SYMBOL_BASE(stats->frequencies, stats->total, last);
|
||||
|
||||
if (symbol)
|
||||
{
|
||||
symbol_low = base[symbol - 1];
|
||||
if (symbol == stats->total - 1)
|
||||
symbol_range = (u16)(0x10000 - symbol_low);
|
||||
else
|
||||
symbol_range = base[symbol] - symbol_low;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol_low = 0;
|
||||
symbol_range = base[0];
|
||||
}
|
||||
|
||||
last = symbol;
|
||||
}
|
||||
|
||||
// Encode the given text with the given statistics
|
||||
// NOTE: May be up to one byte longer than the original message
|
||||
void RangeEncoder::Text(const char *msg, const TextStatsCollector::TableFormat *stats)
|
||||
{
|
||||
u8 *backup_output = output;
|
||||
int backup_remaining = remaining;
|
||||
u64 backup_low = low, backup_range = range;
|
||||
const char *backup_msg = msg;
|
||||
|
||||
BiasedBit(0, 0xFF000000);
|
||||
|
||||
// Encode with order-1 statistics
|
||||
u16 symbol_low, symbol_range;
|
||||
u32 last = 0;
|
||||
|
||||
do
|
||||
{
|
||||
Normalize();
|
||||
|
||||
GetTableSymbol(stats, last, (u8)*msg++, symbol_low, symbol_range);
|
||||
|
||||
range >>= 16;
|
||||
low += symbol_low * range;
|
||||
range *= symbol_range;
|
||||
} while (symbol_low);
|
||||
|
||||
int len = (int)(msg - backup_msg);
|
||||
|
||||
// If the tables failed, fall back to uniform distribution
|
||||
if ((backup_remaining - remaining) > (len * stats->log2total) >> 15)
|
||||
{
|
||||
// Restore state
|
||||
output = backup_output;
|
||||
remaining = backup_remaining;
|
||||
low = backup_low;
|
||||
range = backup_range;
|
||||
msg = backup_msg;
|
||||
|
||||
BiasedBit(1, 0xFF000000);
|
||||
|
||||
// Uniform range encode
|
||||
u8 ch;
|
||||
do
|
||||
{
|
||||
Normalize();
|
||||
|
||||
ch = (u8)*msg++;
|
||||
range /= stats->total;
|
||||
low += stats->char2index[ch] * range;
|
||||
} while (ch);
|
||||
}
|
||||
}
|
||||
|
||||
// Compress a biased bit given the frequency it is set
|
||||
// frequency = average times out of 2^32 trials the bit will be 0
|
||||
void RangeEncoder::BiasedBit(u32 b, u32 frequency)
|
||||
{
|
||||
if (!range)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
low = (u64)frequency << 32;
|
||||
range = (u64)(-(s32)frequency) << 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = 0;
|
||||
range = (u64)frequency << 32;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Normalize();
|
||||
|
||||
range >>= 32;
|
||||
|
||||
if (b)
|
||||
{
|
||||
low += frequency * range;
|
||||
range *= (u32)(-(s32)frequency);
|
||||
}
|
||||
else
|
||||
{
|
||||
range *= frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Encode a field that takes on [0, total) values with equal likelihood
|
||||
void RangeEncoder::Range(u32 symbol, u32 total)
|
||||
{
|
||||
if (!range)
|
||||
{
|
||||
range = 0xFFFFFFFFFFFFFFFFLL / total;
|
||||
low = symbol * range;
|
||||
}
|
||||
else
|
||||
{
|
||||
Normalize();
|
||||
|
||||
range /= total;
|
||||
low += symbol * range;
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the final byte(s) needed to encode the symbols
|
||||
void RangeEncoder::Finish()
|
||||
{
|
||||
// Output a minimal number of bytes, up to 2
|
||||
|
||||
Normalize();
|
||||
|
||||
if (!low) return;
|
||||
|
||||
if (!remaining)
|
||||
output = 0;
|
||||
else
|
||||
{
|
||||
--remaining;
|
||||
low += range - 1;
|
||||
*output++ = (u8)(low >> 56);
|
||||
|
||||
if (range < Top)
|
||||
{
|
||||
low <<= 8;
|
||||
|
||||
if (!remaining)
|
||||
{
|
||||
output = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*output++ = (u8)(low >> 56);
|
||||
--remaining;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// RangeDecoder
|
||||
|
||||
// Intializing constructor
|
||||
RangeDecoder::RangeDecoder(const void *message, int bytes)
|
||||
{
|
||||
const u8 *m8 = (const u8*)message;
|
||||
|
||||
range = 0;
|
||||
|
||||
// Read up to 8 bytes of the frequency code
|
||||
if (bytes < 8)
|
||||
{
|
||||
code = 0;
|
||||
remaining = 0;
|
||||
|
||||
u8 *code8 = (u8*)&code;
|
||||
|
||||
switch (bytes)
|
||||
{
|
||||
#if defined(CAT_ENDIAN_LITTLE)
|
||||
case 7: code8[1] = m8[6];
|
||||
case 6: code8[2] = m8[5];
|
||||
case 5: code8[3] = m8[4];
|
||||
case 4: *(u32*)&code8[4] = getBE(*(u32*)m8);
|
||||
break;
|
||||
case 3: code8[5] = m8[2];
|
||||
case 2: code8[6] = m8[1];
|
||||
case 1: code8[7] = m8[0];
|
||||
#elif defined(CAT_ENDIAN_BIG)
|
||||
case 7: code8[6] = m8[6];
|
||||
case 6: code8[5] = m8[5];
|
||||
case 5: code8[4] = m8[4];
|
||||
case 4: *(u32*)code8 = *(u32*)m8;
|
||||
break;
|
||||
case 3: code8[2] = m8[2];
|
||||
case 2: code8[1] = m8[1];
|
||||
case 1: code8[0] = m8[0];
|
||||
#else
|
||||
#error "Fix this you lazy bastard"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
code = getBE(*(u64*)m8);
|
||||
input = m8 + 8;
|
||||
remaining = bytes - 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Read in bytes as needed
|
||||
void RangeDecoder::Normalize()
|
||||
{
|
||||
while ((low ^ (low + range)) < Top ||
|
||||
range < MaxRange && ((range = -(s64)low & (MaxRange - 1)),1))
|
||||
{
|
||||
code <<= 8;
|
||||
if (remaining)
|
||||
{
|
||||
code |= *input++;
|
||||
--remaining;
|
||||
}
|
||||
|
||||
low <<= 8;
|
||||
range <<= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Grab symbol low frequency and range from the table
|
||||
u8 RangeDecoder::GetTableSymbol(const TextStatsCollector::TableFormat *stats, u32 &last, u16 freq, u16 &symbol_low, u16 &symbol_range)
|
||||
{
|
||||
const u8 *lut = GET_SYMBOL_LUT(stats->frequencies, stats->total, last);
|
||||
const u16 *base = (const u16 *)(lut + SYMBOL_LUT_BYTES * 2);
|
||||
u32 lut_bits = freq >> SYMBOL_LUT_SHIFT;
|
||||
|
||||
// Binary search for the symbol
|
||||
u32 below = lut[lut_bits], above = lut[SYMBOL_LUT_BYTES + lut_bits];
|
||||
|
||||
while (below != above)
|
||||
{
|
||||
u32 pivot = (above - below + 1) / 2 + below;
|
||||
if (freq >= base[pivot])
|
||||
below = pivot;
|
||||
else
|
||||
above = pivot - 1;
|
||||
}
|
||||
|
||||
u8 symbol;
|
||||
|
||||
// Offset it for the unlisted zero element
|
||||
if (below || freq >= base[0])
|
||||
{
|
||||
symbol_low = base[below];
|
||||
++below;
|
||||
|
||||
if ((int)below == stats->total - 1)
|
||||
symbol_range = (u16)(0x10000 - symbol_low);
|
||||
else
|
||||
symbol_range = base[below] - symbol_low;
|
||||
symbol = (u8)below;
|
||||
}
|
||||
else
|
||||
{
|
||||
symbol_low = 0;
|
||||
symbol_range = base[0];
|
||||
symbol = 0;
|
||||
}
|
||||
|
||||
last = symbol;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
// Decode the given text with the given statistics
|
||||
int RangeDecoder::Text(char *msg, int buffer_size, const TextStatsCollector::TableFormat *stats)
|
||||
{
|
||||
u16 symbol_low, symbol_range;
|
||||
u32 last = 0;
|
||||
char *init_msg = msg;
|
||||
|
||||
if (BiasedBit(0xFF000000))
|
||||
{
|
||||
// Selected uniform model
|
||||
while (--buffer_size > 0)
|
||||
{
|
||||
Normalize();
|
||||
|
||||
range /= stats->total;
|
||||
u8 symbol = (u8)((code - low) / range);
|
||||
low += symbol * range;
|
||||
last = stats->index2char[symbol];
|
||||
if (!last) break;
|
||||
*msg++ = (char)last;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Selected order-1 static model
|
||||
while (--buffer_size > 0)
|
||||
{
|
||||
Normalize();
|
||||
|
||||
range >>= 16;
|
||||
u16 x = (u16)((code - low) / range);
|
||||
|
||||
u8 symbol = GetTableSymbol(stats, last, x, symbol_low, symbol_range);
|
||||
low += symbol_low * range;
|
||||
range *= symbol_range;
|
||||
if (!symbol) break;
|
||||
*msg++ = (char)stats->index2char[symbol];
|
||||
--buffer_size;
|
||||
}
|
||||
}
|
||||
|
||||
*msg = '\0';
|
||||
return (int)(msg - init_msg);
|
||||
}
|
||||
|
||||
// Decompress a biased bit given the frequency it is set
|
||||
// frequency = average times out of 2^32 trials the bit will be 0
|
||||
u32 RangeDecoder::BiasedBit(u32 frequency)
|
||||
{
|
||||
if (!range)
|
||||
{
|
||||
// Treat the first encoding specially.
|
||||
if ((u32)(code >> 32) < frequency)
|
||||
{
|
||||
low = 0;
|
||||
range = (u64)frequency << 32;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = (u64)frequency << 32;
|
||||
range = (u64)(-(s32)frequency) << 32;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Normalize();
|
||||
|
||||
range >>= 32;
|
||||
u32 x = (u32)((code - low) / range);
|
||||
|
||||
if (x < frequency)
|
||||
{
|
||||
range *= frequency;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
low += frequency * range;
|
||||
range *= (u32)(-(s32)frequency);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decode a field that takes on [0, total) values with equal likelihood
|
||||
u32 RangeDecoder::Range(u32 total)
|
||||
{
|
||||
u32 symbol;
|
||||
|
||||
if (!range)
|
||||
{
|
||||
range = 0xFFFFFFFFFFFFFFFFLL / total;
|
||||
symbol = (u32)(code / range);
|
||||
low = symbol * range;
|
||||
}
|
||||
else
|
||||
{
|
||||
Normalize();
|
||||
|
||||
range /= total;
|
||||
symbol = (u32)((code - low) / range);
|
||||
low += symbol * range;
|
||||
}
|
||||
|
||||
return symbol;
|
||||
}
|
||||
72
DependentExtensions/cat/src/crypt/SecureCompare.cpp
Normal file
72
DependentExtensions/cat/src/crypt/SecureCompare.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/SecureCompare.hpp>
|
||||
|
||||
namespace cat {
|
||||
|
||||
bool SecureEqual(const void *vA, const void *vB, int bytes)
|
||||
{
|
||||
const u8 *A = (const u8*)vA;
|
||||
const u8 *B = (const u8*)vB;
|
||||
u64 fail = 0;
|
||||
|
||||
// Accumulate failures, 8 bytes at a time
|
||||
int qwords = bytes >> 3;
|
||||
|
||||
if (qwords)
|
||||
{
|
||||
const u64 *A64 = (const u64 *)A;
|
||||
const u64 *B64 = (const u64 *)B;
|
||||
|
||||
for (int ii = 0; ii < qwords; ++ii)
|
||||
fail |= A64[ii] ^ B64[ii];
|
||||
|
||||
A = (const u8 *)&A64[qwords];
|
||||
B = (const u8 *)&B64[qwords];
|
||||
}
|
||||
|
||||
// Accumulate failures, bytes at a time
|
||||
bytes &= 7;
|
||||
|
||||
switch (bytes)
|
||||
{
|
||||
case 7: fail |= A[6] ^ B[6];
|
||||
case 6: fail |= A[5] ^ B[5];
|
||||
case 5: fail |= A[4] ^ B[4];
|
||||
case 4: fail |= *(const u32 *)A ^ *(const u32 *)B;
|
||||
break;
|
||||
case 3: fail |= A[2] ^ B[2];
|
||||
case 2: fail |= A[1] ^ B[1];
|
||||
case 1: fail |= A[0] ^ B[0];
|
||||
}
|
||||
|
||||
return fail == 0;
|
||||
}
|
||||
|
||||
} // namespace cat
|
||||
169
DependentExtensions/cat/src/crypt/cookie/CookieJar.cpp
Normal file
169
DependentExtensions/cat/src/crypt/cookie/CookieJar.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/cookie/CookieJar.hpp>
|
||||
#include <cat/time/Clock.hpp>
|
||||
#include <cat/math/BitMath.hpp>
|
||||
using namespace cat;
|
||||
|
||||
// Initialize to a random 512-bit key on startup
|
||||
void CookieJar::Initialize(FortunaOutput *csprng)
|
||||
{
|
||||
csprng->Generate(key, sizeof(key));
|
||||
}
|
||||
|
||||
u32 CookieJar::Salsa6(u32 *x)
|
||||
{
|
||||
// 6 rounds of Salsa20
|
||||
for (int ii = 6; ii > 0; ii -= 2)
|
||||
{
|
||||
x[4] ^= CAT_ROL32(x[0] + x[12], 7);
|
||||
x[8] ^= CAT_ROL32(x[4] + x[0], 9);
|
||||
x[12] ^= CAT_ROL32(x[8] + x[4], 13);
|
||||
x[0] ^= CAT_ROL32(x[12] + x[8], 18);
|
||||
x[9] ^= CAT_ROL32(x[5] + x[1], 7);
|
||||
x[13] ^= CAT_ROL32(x[9] + x[5], 9);
|
||||
x[1] ^= CAT_ROL32(x[13] + x[9], 13);
|
||||
x[5] ^= CAT_ROL32(x[1] + x[13], 18);
|
||||
x[14] ^= CAT_ROL32(x[10] + x[6], 7);
|
||||
x[2] ^= CAT_ROL32(x[14] + x[10], 9);
|
||||
x[6] ^= CAT_ROL32(x[2] + x[14], 13);
|
||||
x[10] ^= CAT_ROL32(x[6] + x[2], 18);
|
||||
x[3] ^= CAT_ROL32(x[15] + x[11], 7);
|
||||
x[7] ^= CAT_ROL32(x[3] + x[15], 9);
|
||||
x[11] ^= CAT_ROL32(x[7] + x[3], 13);
|
||||
x[15] ^= CAT_ROL32(x[11] + x[7], 18);
|
||||
x[1] ^= CAT_ROL32(x[0] + x[3], 7);
|
||||
x[2] ^= CAT_ROL32(x[1] + x[0], 9);
|
||||
x[3] ^= CAT_ROL32(x[2] + x[1], 13);
|
||||
x[0] ^= CAT_ROL32(x[3] + x[2], 18);
|
||||
x[6] ^= CAT_ROL32(x[5] + x[4], 7);
|
||||
x[7] ^= CAT_ROL32(x[6] + x[5], 9);
|
||||
x[4] ^= CAT_ROL32(x[7] + x[6], 13);
|
||||
x[5] ^= CAT_ROL32(x[4] + x[7], 18);
|
||||
x[11] ^= CAT_ROL32(x[10] + x[9], 7);
|
||||
x[8] ^= CAT_ROL32(x[11] + x[10], 9);
|
||||
x[9] ^= CAT_ROL32(x[8] + x[11], 13);
|
||||
x[10] ^= CAT_ROL32(x[9] + x[8], 18);
|
||||
x[12] ^= CAT_ROL32(x[15] + x[14], 7);
|
||||
x[13] ^= CAT_ROL32(x[12] + x[15], 9);
|
||||
x[14] ^= CAT_ROL32(x[13] + x[12], 13);
|
||||
x[15] ^= CAT_ROL32(x[14] + x[13], 18);
|
||||
}
|
||||
|
||||
return x[0] ^ x[5] ^ x[10] ^ x[15];
|
||||
}
|
||||
|
||||
u32 CookieJar::Hash(u32 ip, u16 port, u32 epoch)
|
||||
{
|
||||
u32 x[16];
|
||||
|
||||
memcpy(x, key, sizeof(x));
|
||||
|
||||
x[4] += ip;
|
||||
x[6] += epoch;
|
||||
x[8] += port;
|
||||
x[10] += epoch;
|
||||
|
||||
return Salsa6(x);
|
||||
}
|
||||
|
||||
u32 CookieJar::Hash(const void *address_info, int bytes, u32 epoch)
|
||||
{
|
||||
u32 x[16];
|
||||
|
||||
memcpy(x, key, sizeof(x));
|
||||
|
||||
// Add address info to the key one word at a time
|
||||
const u32 *info32 = (const u32 *)address_info;
|
||||
u32 *y = &x[4];
|
||||
while (bytes >= 4)
|
||||
{
|
||||
*y++ += *info32++;
|
||||
bytes -= 4;
|
||||
}
|
||||
|
||||
// Add final 1..3 address info bytes to the key
|
||||
const u8 *info8 = (const u8 *)info32;
|
||||
switch (bytes)
|
||||
{
|
||||
case 3: *y += ((u32)info8[2] << 16) | *(const u16*)info8; break;
|
||||
case 2: *y += *(const u16*)info8; break;
|
||||
case 1: *y += info8[0]; break;
|
||||
}
|
||||
|
||||
x[6] += epoch;
|
||||
x[10] += epoch;
|
||||
|
||||
return Salsa6(x);
|
||||
}
|
||||
|
||||
u32 CookieJar::GetEpoch()
|
||||
{
|
||||
return Clock::msec_fast() / BIN_TIME;
|
||||
}
|
||||
|
||||
u32 CookieJar::ReconstructEpoch(u32 cookie)
|
||||
{
|
||||
u32 epoch = GetEpoch();
|
||||
|
||||
u32 cookie_bin = cookie & BIN_MASK;
|
||||
|
||||
// Attempt to reconstruct the epoch used to generate this cookie
|
||||
u32 cookie_epoch = (epoch & ~BIN_MASK) | cookie_bin;
|
||||
|
||||
// If the cookie's bin is ahead of the bin in this interval, then
|
||||
// this cookie must be from the previous interval to be valid.
|
||||
if (cookie_bin > (epoch & BIN_MASK)) cookie_epoch -= BIN_COUNT;
|
||||
|
||||
return cookie_epoch;
|
||||
}
|
||||
|
||||
u32 CookieJar::Generate(u32 ip, u16 port)
|
||||
{
|
||||
u32 epoch = GetEpoch();
|
||||
|
||||
return (Hash(ip, port, epoch) << 4) | (epoch & BIN_MASK);
|
||||
}
|
||||
|
||||
bool CookieJar::Verify(u32 ip, u16 port, u32 cookie)
|
||||
{
|
||||
return (Hash(ip, port, ReconstructEpoch(cookie)) << 4) == (cookie & ~BIN_MASK);
|
||||
}
|
||||
|
||||
u32 CookieJar::Generate(const void *address_info, int bytes)
|
||||
{
|
||||
u32 epoch = GetEpoch();
|
||||
|
||||
return (Hash(address_info, bytes, epoch) << 4) | (epoch & BIN_MASK);
|
||||
}
|
||||
|
||||
bool CookieJar::Verify(const void *address_info, int bytes, u32 cookie)
|
||||
{
|
||||
return (Hash(address_info, bytes, ReconstructEpoch(cookie)) << 4) == (cookie & ~BIN_MASK);
|
||||
}
|
||||
367
DependentExtensions/cat/src/crypt/hash/HMAC_MD5.cpp
Normal file
367
DependentExtensions/cat/src/crypt/hash/HMAC_MD5.cpp
Normal file
@ -0,0 +1,367 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/hash/HMAC_MD5.hpp>
|
||||
#include <cat/math/BitMath.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
using namespace cat;
|
||||
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
// NOTE: Uses little-endian integers instead of big-endian as in standard MD5
|
||||
#define ROUND(a, b, Fbcd, x, o, s, ac) \
|
||||
(a) += Fbcd + getLE(x[o]) + (u32)(ac); \
|
||||
(a) = CAT_ROL32((a), (s)); \
|
||||
(a) += (b);
|
||||
|
||||
#define FF(a, b, c, d, x,o, s, ac) ROUND(a, b, F(b,c,d), x, o, s, ac)
|
||||
#define GG(a, b, c, d, x,o, s, ac) ROUND(a, b, G(b,c,d), x, o, s, ac)
|
||||
#define HH(a, b, c, d, x,o, s, ac) ROUND(a, b, H(b,c,d), x, o, s, ac)
|
||||
#define II(a, b, c, d, x,o, s, ac) ROUND(a, b, I(b,c,d), x, o, s, ac)
|
||||
|
||||
|
||||
//// HMAC_MD5
|
||||
|
||||
void HMAC_MD5::HashComputation(const void *message, int blocks, u32 *NextState)
|
||||
{
|
||||
u32 *words = (u32*)message;
|
||||
|
||||
u32 a0 = State[0], b0 = State[1], c0 = State[2], d0 = State[3];
|
||||
|
||||
while (blocks--)
|
||||
{
|
||||
u32 a = a0, b = b0, c = c0, d = d0;
|
||||
|
||||
#ifdef CAT_AUDIT
|
||||
printf("AUDIT: MD5 ");
|
||||
for (int ii = 0; ii < 64; ++ii)
|
||||
{
|
||||
printf("%02x", ((u8*)words)[ii]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
// Round 1
|
||||
const int S11 = 7;
|
||||
const int S12 = 12;
|
||||
const int S13 = 17;
|
||||
const int S14 = 22;
|
||||
|
||||
FF(a, b, c, d, words, 0, S11, 0xd76aa478); // 1
|
||||
FF(d, a, b, c, words, 1, S12, 0xe8c7b756); // 2
|
||||
FF(c, d, a, b, words, 2, S13, 0x242070db); // 3
|
||||
FF(b, c, d, a, words, 3, S14, 0xc1bdceee); // 4
|
||||
FF(a, b, c, d, words, 4, S11, 0xf57c0faf); // 5
|
||||
FF(d, a, b, c, words, 5, S12, 0x4787c62a); // 6
|
||||
FF(c, d, a, b, words, 6, S13, 0xa8304613); // 7
|
||||
FF(b, c, d, a, words, 7, S14, 0xfd469501); // 8
|
||||
FF(a, b, c, d, words, 8, S11, 0x698098d8); // 9
|
||||
FF(d, a, b, c, words, 9, S12, 0x8b44f7af); // 10
|
||||
FF(c, d, a, b, words, 10, S13, 0xffff5bb1); // 11
|
||||
FF(b, c, d, a, words, 11, S14, 0x895cd7be); // 12
|
||||
FF(a, b, c, d, words, 12, S11, 0x6b901122); // 13
|
||||
FF(d, a, b, c, words, 13, S12, 0xfd987193); // 14
|
||||
FF(c, d, a, b, words, 14, S13, 0xa679438e); // 15
|
||||
FF(b, c, d, a, words, 15, S14, 0x49b40821); // 16
|
||||
|
||||
// Round 2
|
||||
const int S21 = 5;
|
||||
const int S22 = 9;
|
||||
const int S23 = 14;
|
||||
const int S24 = 20;
|
||||
|
||||
GG(a, b, c, d, words, 1, S21, 0xf61e2562); // 17
|
||||
GG(d, a, b, c, words, 6, S22, 0xc040b340); // 18
|
||||
GG(c, d, a, b, words, 11, S23, 0x265e5a51); // 19
|
||||
GG(b, c, d, a, words, 0, S24, 0xe9b6c7aa); // 20
|
||||
GG(a, b, c, d, words, 5, S21, 0xd62f105d); // 21
|
||||
GG(d, a, b, c, words, 10, S22, 0x2441453); // 22
|
||||
GG(c, d, a, b, words, 15, S23, 0xd8a1e681); // 23
|
||||
GG(b, c, d, a, words, 4, S24, 0xe7d3fbc8); // 24
|
||||
GG(a, b, c, d, words, 9, S21, 0x21e1cde6); // 25
|
||||
GG(d, a, b, c, words, 14, S22, 0xc33707d6); // 26
|
||||
GG(c, d, a, b, words, 3, S23, 0xf4d50d87); // 27
|
||||
GG(b, c, d, a, words, 8, S24, 0x455a14ed); // 28
|
||||
GG(a, b, c, d, words, 13, S21, 0xa9e3e905); // 29
|
||||
GG(d, a, b, c, words, 2, S22, 0xfcefa3f8); // 30
|
||||
GG(c, d, a, b, words, 7, S23, 0x676f02d9); // 31
|
||||
GG(b, c, d, a, words, 12, S24, 0x8d2a4c8a); // 32
|
||||
|
||||
// Round 3
|
||||
const int S31 = 4;
|
||||
const int S32 = 11;
|
||||
const int S33 = 16;
|
||||
const int S34 = 23;
|
||||
|
||||
HH(a, b, c, d, words, 5, S31, 0xfffa3942); // 33
|
||||
HH(d, a, b, c, words, 8, S32, 0x8771f681); // 34
|
||||
HH(c, d, a, b, words, 11, S33, 0x6d9d6122); // 35
|
||||
HH(b, c, d, a, words, 14, S34, 0xfde5380c); // 36
|
||||
HH(a, b, c, d, words, 1, S31, 0xa4beea44); // 37
|
||||
HH(d, a, b, c, words, 4, S32, 0x4bdecfa9); // 38
|
||||
HH(c, d, a, b, words, 7, S33, 0xf6bb4b60); // 39
|
||||
HH(b, c, d, a, words, 10, S34, 0xbebfbc70); // 40
|
||||
HH(a, b, c, d, words, 13, S31, 0x289b7ec6); // 41
|
||||
HH(d, a, b, c, words, 0, S32, 0xeaa127fa); // 42
|
||||
HH(c, d, a, b, words, 3, S33, 0xd4ef3085); // 43
|
||||
HH(b, c, d, a, words, 6, S34, 0x4881d05); // 44
|
||||
HH(a, b, c, d, words, 9, S31, 0xd9d4d039); // 45
|
||||
HH(d, a, b, c, words, 12, S32, 0xe6db99e5); // 46
|
||||
HH(c, d, a, b, words, 15, S33, 0x1fa27cf8); // 47
|
||||
HH(b, c, d, a, words, 2, S34, 0xc4ac5665); // 48
|
||||
|
||||
// Round 4
|
||||
const int S41 = 6;
|
||||
const int S42 = 10;
|
||||
const int S43 = 15;
|
||||
const int S44 = 21;
|
||||
|
||||
II(a, b, c, d, words, 0, S41, 0xf4292244); // 49
|
||||
II(d, a, b, c, words, 7, S42, 0x432aff97); // 50
|
||||
II(c, d, a, b, words, 14, S43, 0xab9423a7); // 51
|
||||
II(b, c, d, a, words, 5, S44, 0xfc93a039); // 52
|
||||
II(a, b, c, d, words, 12, S41, 0x655b59c3); // 53
|
||||
II(d, a, b, c, words, 3, S42, 0x8f0ccc92); // 54
|
||||
II(c, d, a, b, words, 10, S43, 0xffeff47d); // 55
|
||||
II(b, c, d, a, words, 1, S44, 0x85845dd1); // 56
|
||||
II(a, b, c, d, words, 8, S41, 0x6fa87e4f); // 57
|
||||
II(d, a, b, c, words, 15, S42, 0xfe2ce6e0); // 58
|
||||
II(c, d, a, b, words, 6, S43, 0xa3014314); // 59
|
||||
II(b, c, d, a, words, 13, S44, 0x4e0811a1); // 60
|
||||
II(a, b, c, d, words, 4, S41, 0xf7537e82); // 61
|
||||
II(d, a, b, c, words, 11, S42, 0xbd3af235); // 62
|
||||
II(c, d, a, b, words, 2, S43, 0x2ad7d2bb); // 63
|
||||
II(b, c, d, a, words, 9, S44, 0xeb86d391); // 64
|
||||
|
||||
a0 += a;
|
||||
b0 += b;
|
||||
c0 += c;
|
||||
d0 += d;
|
||||
|
||||
words += 16;
|
||||
}
|
||||
|
||||
NextState[0] = a0;
|
||||
NextState[1] = b0;
|
||||
NextState[2] = c0;
|
||||
NextState[3] = d0;
|
||||
}
|
||||
|
||||
HMAC_MD5::~HMAC_MD5()
|
||||
{
|
||||
CAT_OBJCLR(State);
|
||||
CAT_OBJCLR(Work);
|
||||
CAT_OBJCLR(CachedInitialState);
|
||||
CAT_OBJCLR(CachedFinalState);
|
||||
byte_counter = 0;
|
||||
used_bytes = 0;
|
||||
}
|
||||
|
||||
bool HMAC_MD5::SetKey(ICryptHash *parent)
|
||||
{
|
||||
State[0] = 0x27b70a85;
|
||||
State[1] = 0x2e1b2138;
|
||||
State[2] = 0x4d2c6dfc;
|
||||
State[3] = 0x53380d13;
|
||||
|
||||
static const int KEY_BYTES = WORK_BYTES / 2;
|
||||
|
||||
u8 Key[KEY_BYTES];
|
||||
|
||||
parent->Generate(Key, KEY_BYTES);
|
||||
|
||||
// Using the parent hash function, generate key bytes to fill half a block
|
||||
memcpy(Work, Key, KEY_BYTES);
|
||||
memset(Work + KEY_BYTES, 0x36, WORK_BYTES - KEY_BYTES); // Pad to fill a whole block
|
||||
|
||||
// Crunch one whole block
|
||||
HashComputation(Work, 1, State);
|
||||
|
||||
// Store this as the cached initial state
|
||||
memcpy(CachedInitialState, State, DIGEST_BYTES);
|
||||
|
||||
// Using the parent hash function, generate key bytes to fill half a block
|
||||
memcpy(Work, Key, KEY_BYTES);
|
||||
memset(Work + KEY_BYTES, 0x5c, WORK_BYTES - KEY_BYTES); // Pad to fill a whole block
|
||||
|
||||
// Crunch one whole block
|
||||
HashComputation(Work, 1, CachedFinalState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HMAC_MD5::RekeyFromMD5(HMAC_MD5 *parent)
|
||||
{
|
||||
memcpy(CachedInitialState, parent->CachedInitialState, sizeof(CachedInitialState));
|
||||
memcpy(CachedFinalState, parent->CachedFinalState, sizeof(CachedFinalState));
|
||||
}
|
||||
|
||||
bool HMAC_MD5::BeginMAC()
|
||||
{
|
||||
memcpy(State, CachedInitialState, DIGEST_BYTES);
|
||||
|
||||
byte_counter = WORK_BYTES;
|
||||
|
||||
used_bytes = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HMAC_MD5::Crunch(const void *_message, int bytes)
|
||||
{
|
||||
const u8 *buffer = (const u8*)_message;
|
||||
|
||||
byte_counter += bytes;
|
||||
|
||||
// If there are bytes left to hash from last time,
|
||||
if (used_bytes)
|
||||
{
|
||||
// If we still cannot overflow the workspace,
|
||||
if (used_bytes + bytes <= WORK_BYTES)
|
||||
{
|
||||
// Just append the new message bytes
|
||||
memcpy(Work + used_bytes, buffer, bytes);
|
||||
used_bytes += bytes;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill the rest of the workspace
|
||||
u32 copied = WORK_BYTES - used_bytes;
|
||||
|
||||
memcpy(Work + used_bytes, buffer, copied);
|
||||
|
||||
HashComputation(Work, 1, State);
|
||||
|
||||
// Eat those bytes of the message
|
||||
bytes -= copied;
|
||||
buffer += copied;
|
||||
}
|
||||
|
||||
// If the remaining bytes of the message overflows the workspace,
|
||||
if (bytes > WORK_BYTES)
|
||||
{
|
||||
int eat_bytes = bytes - 1;
|
||||
|
||||
// Hash directly from the message
|
||||
HashComputation(buffer, eat_bytes / WORK_BYTES, State);
|
||||
|
||||
// Eat those bytes of the message
|
||||
eat_bytes &= ~(WORK_BYTES-1);
|
||||
buffer += eat_bytes;
|
||||
bytes -= eat_bytes;
|
||||
}
|
||||
|
||||
// Copy what remains into the workspace
|
||||
memcpy(Work, buffer, bytes);
|
||||
used_bytes = bytes;
|
||||
}
|
||||
|
||||
void HMAC_MD5::End()
|
||||
{
|
||||
// NOTE: We should always have at least one message hash to perform here
|
||||
|
||||
if (used_bytes >= WORK_BYTES)
|
||||
{
|
||||
HashComputation(Work, 1, State);
|
||||
|
||||
Work[0] = 0x80;
|
||||
|
||||
used_bytes = 1;
|
||||
}
|
||||
else if (used_bytes > (WORK_BYTES - 9))
|
||||
{
|
||||
Work[used_bytes++] = 0x80;
|
||||
|
||||
// Pad with zeros
|
||||
CAT_CLR(Work + used_bytes, WORK_BYTES - used_bytes);
|
||||
|
||||
HashComputation(Work, 1, State);
|
||||
|
||||
used_bytes = 0;
|
||||
}
|
||||
|
||||
// Pad out zeros
|
||||
CAT_CLR(Work + used_bytes, (WORK_BYTES - 8) - used_bytes);
|
||||
|
||||
// Attach bit count to the end
|
||||
u64 bit_counter = byte_counter << 3;
|
||||
*(u32*)&Work[WORK_BYTES - 8] = getLE((u32)bit_counter);
|
||||
*(u32*)&Work[WORK_BYTES - 4] = getLE((u32)(bit_counter >> 32));
|
||||
|
||||
u32 *Output = (u32 *)Work;
|
||||
|
||||
// Intermediate hash, output to start of workspace
|
||||
HashComputation(Work, 1, Output);
|
||||
|
||||
memcpy(State, CachedFinalState, DIGEST_BYTES);
|
||||
|
||||
// Convert Intermediate State to an endian-neutral byte array
|
||||
swapLE(Output[0]);
|
||||
swapLE(Output[1]);
|
||||
swapLE(Output[2]);
|
||||
swapLE(Output[3]);
|
||||
|
||||
// Pad the hash-as-message as normal and crown it with a byte counter
|
||||
byte_counter = 16;
|
||||
Work[16] = 0x80;
|
||||
CAT_CLR(Work + 17, (WORK_BYTES - 8) - 17);
|
||||
|
||||
*(u32*)&Work[WORK_BYTES - 8] = getLE32(16 << 3);
|
||||
*(u32*)&Work[WORK_BYTES - 4] = 0;
|
||||
|
||||
// Final output hash
|
||||
HashComputation(Work, 1, State);
|
||||
|
||||
// Convert Final State to an endian-neutral byte array
|
||||
swapLE(State[0]);
|
||||
swapLE(State[1]);
|
||||
swapLE(State[2]);
|
||||
swapLE(State[3]);
|
||||
}
|
||||
|
||||
void HMAC_MD5::Generate(void *out, int bytes, int /*strengthening_rounds*/)
|
||||
{
|
||||
if (bytes > 16) bytes = 16;
|
||||
|
||||
memcpy(out, State, bytes);
|
||||
}
|
||||
|
||||
#undef F
|
||||
#undef G
|
||||
#undef H
|
||||
#undef I
|
||||
|
||||
#undef ROUND
|
||||
|
||||
#undef FF
|
||||
#undef GG
|
||||
#undef HH
|
||||
#undef II
|
||||
295
DependentExtensions/cat/src/crypt/hash/Skein.cpp
Normal file
295
DependentExtensions/cat/src/crypt/hash/Skein.cpp
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
using namespace cat;
|
||||
|
||||
Skein::~Skein()
|
||||
{
|
||||
CAT_OBJCLR(State);
|
||||
CAT_OBJCLR(Tweak);
|
||||
CAT_OBJCLR(Work);
|
||||
}
|
||||
|
||||
void Skein::GenerateInitialState(int bits)
|
||||
{
|
||||
u64 w[MAX_WORDS] = { getLE64(SCHEMA_VER), getLE64(static_cast<unsigned>(bits)), 0 };
|
||||
|
||||
CAT_OBJCLR(State);
|
||||
|
||||
// T1 = FIRST | FINAL | CFG
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | T1_MASK_FINAL | ((u64)BLK_TYPE_CFG << T1_POS_BLK_TYPE);
|
||||
|
||||
(this->*hash_func)(w, 1, 32, State);
|
||||
}
|
||||
|
||||
// Cached copies of initial state for different bit lengths
|
||||
static const u64 State0_160[4] = {
|
||||
0xa38a0d80a3687723ULL, 0xb73cdb6a5963ffc9ULL, 0x9633e8ea07a1b447ULL, 0xca0ed09ec9529c22ULL
|
||||
};
|
||||
|
||||
static const u64 State0_224[4] = {
|
||||
0xb80929699ae0f431ULL, 0xd340dc14a06929dcULL, 0xae866594bde4dc5aULL, 0x339767c25a60ea1dULL
|
||||
};
|
||||
|
||||
static const u64 State0_256[4] = {
|
||||
0x388512680e660046ULL, 0x4b72d5dec5a8ff01ULL, 0x281a9298ca5eb3a5ULL, 0x54ca5249f46070c4ULL
|
||||
};
|
||||
|
||||
static const u64 State0_384[8] = {
|
||||
0xe5bf4d02ba62494cULL, 0x7aa1eabcc3e6fc68ULL, 0xbbe5fc26e1038c5aULL, 0x53c9903e8f88e9faULL,
|
||||
0xf30d8dddfb940c83ULL, 0x500fda3c4865abecULL, 0x2226c67f745bc5e7ULL, 0x015da80077c639f7ULL
|
||||
};
|
||||
|
||||
static const u64 State0_512[8] = {
|
||||
0xa8d47980544a6e32ULL, 0x847511533e9b1a8aULL, 0x6faee870d8e81a00ULL, 0x58b0d9d6cb557f92ULL,
|
||||
0x9bbc0051dac1d4e9ULL, 0xb744e2b1d189e7caULL, 0x979350fa709c5ef3ULL, 0x0350125a92067bcdULL
|
||||
};
|
||||
|
||||
bool Skein::BeginKey(int bits)
|
||||
{
|
||||
if (bits <= 256) {
|
||||
digest_bytes = 256 / 8;
|
||||
digest_words = 256 / 64;
|
||||
hash_func = &Skein::HashComputation256;
|
||||
} else if (bits <= 512) {
|
||||
digest_bytes = 512 / 8;
|
||||
digest_words = 512 / 64;
|
||||
hash_func = &Skein::HashComputation512;
|
||||
} else return false;
|
||||
|
||||
// Try to use a cached copy of the initial state
|
||||
switch (bits)
|
||||
{
|
||||
case 160: memcpy(State, State0_160, sizeof(State0_160)); break;
|
||||
case 224: memcpy(State, State0_224, sizeof(State0_224)); break;
|
||||
case 256: memcpy(State, State0_256, sizeof(State0_256)); break;
|
||||
case 384: memcpy(State, State0_384, sizeof(State0_384)); break;
|
||||
case 512: memcpy(State, State0_512, sizeof(State0_512)); break;
|
||||
default: GenerateInitialState(bits);
|
||||
}
|
||||
|
||||
// T1 = FIRST | KEY
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | ((u64)BLK_TYPE_KEY << T1_POS_BLK_TYPE);
|
||||
|
||||
used_bytes = 0;
|
||||
output_prng_mode = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Skein::SetKey(ICryptHash *key_hash)
|
||||
{
|
||||
const Skein *parent = static_cast<const Skein *>(key_hash);
|
||||
if (!parent) return false;
|
||||
|
||||
memcpy(State, parent->State, sizeof(State));
|
||||
digest_bytes = parent->digest_bytes;
|
||||
digest_words = parent->digest_words;
|
||||
hash_func = parent->hash_func;
|
||||
|
||||
// The user will then call one of the Begin() functions below:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Skein::BeginMAC()
|
||||
{
|
||||
// T1 = FIRST | MSG
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | ((u64)BLK_TYPE_MSG << T1_POS_BLK_TYPE);
|
||||
|
||||
used_bytes = 0;
|
||||
output_prng_mode = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Skein::BeginKDF()
|
||||
{
|
||||
// T1 = FIRST | KDF
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | ((u64)BLK_TYPE_KDF << T1_POS_BLK_TYPE);
|
||||
|
||||
used_bytes = 0;
|
||||
output_prng_mode = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Skein::BeginPRNG()
|
||||
{
|
||||
// T1 = FIRST | NONCE
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | ((u64)BLK_TYPE_NONCE << T1_POS_BLK_TYPE);
|
||||
|
||||
used_bytes = 0;
|
||||
output_prng_mode = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Skein::Crunch(const void *_message, int bytes)
|
||||
{
|
||||
const u8 *buffer = (const u8*)_message;
|
||||
|
||||
// If there are bytes left to hash from last time,
|
||||
if (used_bytes)
|
||||
{
|
||||
// If we still cannot overflow the workspace,
|
||||
if (used_bytes + bytes <= digest_bytes)
|
||||
{
|
||||
// Just append the new message bytes
|
||||
memcpy(Work + used_bytes, buffer, bytes);
|
||||
used_bytes += bytes;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill the rest of the workspace
|
||||
u32 copied = digest_bytes - used_bytes;
|
||||
|
||||
memcpy(Work + used_bytes, buffer, copied);
|
||||
|
||||
(this->*hash_func)(Work, 1, digest_bytes, State);
|
||||
|
||||
// Eat those bytes of the message
|
||||
bytes -= copied;
|
||||
buffer += copied;
|
||||
}
|
||||
|
||||
// If the remaining bytes of the message overflows the workspace,
|
||||
if (bytes > digest_bytes)
|
||||
{
|
||||
int eat_bytes = bytes - 1;
|
||||
|
||||
// Hash directly from the message
|
||||
(this->*hash_func)(buffer, eat_bytes / digest_bytes, bytes, State);
|
||||
|
||||
// Eat those bytes of the message
|
||||
eat_bytes &= ~(digest_bytes-1);
|
||||
buffer += eat_bytes;
|
||||
bytes -= eat_bytes;
|
||||
}
|
||||
|
||||
// Copy what remains into the workspace
|
||||
memcpy(Work, buffer, bytes);
|
||||
used_bytes = bytes;
|
||||
}
|
||||
|
||||
void Skein::End()
|
||||
{
|
||||
// NOTE: We should always have at least one message hash to perform here
|
||||
|
||||
// Pad with zeroes
|
||||
CAT_CLR(Work + used_bytes, digest_bytes - used_bytes);
|
||||
|
||||
// Final message hash
|
||||
Tweak[1] |= T1_MASK_FINAL;
|
||||
(this->*hash_func)(Work, 1, used_bytes, State);
|
||||
|
||||
output_block_counter = 0;
|
||||
}
|
||||
|
||||
void Skein::Generate(void *out, int bytes, int strengthening_rounds)
|
||||
{
|
||||
// Put the Skein generator in counter mode and generate WORDS at a time
|
||||
u64 NextState[MAX_WORDS];
|
||||
u64 FinalMessage[MAX_WORDS] = {output_block_counter, 0};
|
||||
u64 *out64 = (u64 *)out;
|
||||
|
||||
// In strengthened mode, discard a number of rounds before producing real output
|
||||
while (strengthening_rounds-- >= 1)
|
||||
{
|
||||
// T1 = FIRST | FINAL | OUT
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | T1_MASK_FINAL | ((u64)BLK_TYPE_OUT << T1_POS_BLK_TYPE);
|
||||
|
||||
// Produce next output
|
||||
(this->*hash_func)(FinalMessage, 1, 8, NextState);
|
||||
|
||||
// Next counter
|
||||
FinalMessage[0] = ++output_block_counter;
|
||||
}
|
||||
|
||||
// In output mode, we hide the first block of each request
|
||||
if (output_prng_mode)
|
||||
{
|
||||
// T1 = FIRST | FINAL | OUT
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | T1_MASK_FINAL | ((u64)BLK_TYPE_OUT << T1_POS_BLK_TYPE);
|
||||
|
||||
// Produce next output
|
||||
(this->*hash_func)(FinalMessage, 1, 8, NextState);
|
||||
|
||||
// Next counter
|
||||
FinalMessage[0] = ++output_block_counter;
|
||||
}
|
||||
|
||||
while (bytes >= digest_bytes)
|
||||
{
|
||||
// T1 = FIRST | FINAL | OUT
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | T1_MASK_FINAL | ((u64)BLK_TYPE_OUT << T1_POS_BLK_TYPE);
|
||||
|
||||
// Produce next output
|
||||
(this->*hash_func)(FinalMessage, 1, 8, out64);
|
||||
|
||||
for (int ii = 0; ii < digest_words; ++ii)
|
||||
swapLE(out64[ii]);
|
||||
|
||||
// Next counter
|
||||
out64 += digest_words;
|
||||
bytes -= digest_bytes;
|
||||
FinalMessage[0] = ++output_block_counter;
|
||||
}
|
||||
|
||||
if (bytes > 0)
|
||||
{
|
||||
// T1 = FIRST | FINAL | OUT
|
||||
Tweak[0] = 0;
|
||||
Tweak[1] = T1_MASK_FIRST | T1_MASK_FINAL | ((u64)BLK_TYPE_OUT << T1_POS_BLK_TYPE);
|
||||
|
||||
// Produce final output
|
||||
(this->*hash_func)(FinalMessage, 1, 8, FinalMessage);
|
||||
|
||||
for (int ii = CAT_CEIL_UNIT(bytes, sizeof(u64)); ii >= 0; --ii)
|
||||
swapLE(FinalMessage[ii]);
|
||||
|
||||
// Copy however many bytes they wanted
|
||||
memcpy(out64, FinalMessage, bytes);
|
||||
|
||||
++output_block_counter;
|
||||
}
|
||||
|
||||
// In PRNG output mode, use the first hidden output block as the next state
|
||||
if (output_prng_mode)
|
||||
memcpy(State, NextState, digest_bytes);
|
||||
}
|
||||
194
DependentExtensions/cat/src/crypt/hash/Skein256.cpp
Normal file
194
DependentExtensions/cat/src/crypt/hash/Skein256.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
using namespace cat;
|
||||
|
||||
#define THREEFISH(R0, R1, R2, R3) \
|
||||
x0 += x1; x1 = CAT_ROL64(x1, R0); x1 ^= x0; \
|
||||
x2 += x3; x3 = CAT_ROL64(x3, R1); x3 ^= x2; \
|
||||
x0 += x3; x3 = CAT_ROL64(x3, R2); x3 ^= x0; \
|
||||
x2 += x1; x1 = CAT_ROL64(x1, R3); x1 ^= x2;
|
||||
|
||||
#define INJECTKEY(K0, K1, K2, K3, T0, T1, R) \
|
||||
x0 += (K0); \
|
||||
x1 += (K1) + (T0); \
|
||||
x2 += (K2) + (T1); \
|
||||
x3 += (K3) + (R);
|
||||
|
||||
void Skein::HashComputation256(const void *_message, int blocks, u32 byte_count, u64 *NextState)
|
||||
{
|
||||
const int BITS = 256;
|
||||
const int WORDS = BITS / 64;
|
||||
const int BYTES = BITS / 8;
|
||||
const u64 *message = (const u64 *)_message;
|
||||
|
||||
// Key schedule: Chaining
|
||||
u64 k[5];
|
||||
memcpy(k, State, BYTES);
|
||||
|
||||
// Key schedule: Tweak
|
||||
u64 t0 = Tweak[0];
|
||||
u64 t1 = Tweak[1];
|
||||
|
||||
do
|
||||
{
|
||||
t0 += byte_count;
|
||||
|
||||
// Parity extension
|
||||
u64 t2 = t0 ^ t1;
|
||||
k[4] = 0x1BD11BDAA9FC1A22LL ^ k[0] ^ k[1] ^ k[2] ^ k[3];
|
||||
|
||||
// First full key injection
|
||||
register u64 x0 = k[0] + getLE(message[0]);
|
||||
register u64 x1 = k[1] + getLE(message[1]) + t0;
|
||||
register u64 x2 = k[2] + getLE(message[2]) + t1;
|
||||
register u64 x3 = k[3] + getLE(message[3]);
|
||||
|
||||
// 72 rounds
|
||||
|
||||
// 10/26/09: Updated for SHA-3 competition Round 2
|
||||
enum {
|
||||
R_256_0_0=14, R_256_0_1=16,
|
||||
R_256_1_0=52, R_256_1_1=57,
|
||||
R_256_2_0=23, R_256_2_1=40,
|
||||
R_256_3_0= 5, R_256_3_1=37,
|
||||
R_256_4_0=25, R_256_4_1=33,
|
||||
R_256_5_0=46, R_256_5_1=12,
|
||||
R_256_6_0=58, R_256_6_1=22,
|
||||
R_256_7_0=32, R_256_7_1=32
|
||||
};
|
||||
|
||||
for (int round = 1; round <= 18; round += 6)
|
||||
{
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
|
||||
u64 k1 = k[(round)%5];
|
||||
u64 k2 = k[(round+1)%5];
|
||||
u64 k3 = k[(round+2)%5];
|
||||
u64 k4 = k[(round+3)%5];
|
||||
u64 k0 = k[(round+4)%5];
|
||||
|
||||
INJECTKEY(k1, k2, k3, k4, t1, t2, round);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k2, k3, k4, k0, t2, t0, round+1);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k3, k4, k0, k1, t0, t1, round+2);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k4, k0, k1, k2, t1, t2, round+3);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k0, k1, k2, k3, t2, t0, round+4);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k1, k2, k3, k4, t0, t1, round+5);
|
||||
}
|
||||
/*
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k1, k2, k3, k4, t1, t2, 1);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k2, k3, k4, k0, t2, t0, 2);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k3, k4, k0, k1, t0, t1, 3);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k4, k0, k1, k2, t1, t2, 4);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k0, k1, k2, k3, t2, t0, 5);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k1, k2, k3, k4, t0, t1, 6);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k2, k3, k4, k0, t1, t2, 7);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k3, k4, k0, k1, t2, t0, 8);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k4, k0, k1, k2, t0, t1, 9);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k0, k1, k2, k3, t1, t2, 10);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k1, k2, k3, k4, t2, t0, 11);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k2, k3, k4, k0, t0, t1, 12);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k3, k4, k0, k1, t1, t2, 13);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k4, k0, k1, k2, t2, t0, 14);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k0, k1, k2, k3, t0, t1, 15);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k1, k2, k3, k4, t1, t2, 16);
|
||||
THREEFISH(R_256_0_0, R_256_0_1, R_256_1_0, R_256_1_1);
|
||||
THREEFISH(R_256_2_0, R_256_2_1, R_256_3_0, R_256_3_1);
|
||||
INJECTKEY(k2, k3, k4, k0, t2, t0, 17);
|
||||
THREEFISH(R_256_4_0, R_256_4_1, R_256_5_0, R_256_5_1);
|
||||
THREEFISH(R_256_6_0, R_256_6_1, R_256_7_0, R_256_7_1);
|
||||
INJECTKEY(k3, k4, k0, k1, t0, t1, 18);
|
||||
*/
|
||||
// Feedforward XOR
|
||||
k[0] = x0 ^ getLE(message[0]);
|
||||
k[1] = x1 ^ getLE(message[1]);
|
||||
k[2] = x2 ^ getLE(message[2]);
|
||||
k[3] = x3 ^ getLE(message[3]);
|
||||
|
||||
// Update tweak
|
||||
t1 &= ~T1_MASK_FIRST;
|
||||
|
||||
// Eat data bytes
|
||||
message += WORDS;
|
||||
} while (--blocks > 0);
|
||||
|
||||
// Update tweak
|
||||
Tweak[0] = t0;
|
||||
Tweak[1] = t1;
|
||||
|
||||
// Update state
|
||||
memcpy(NextState, k, BYTES);
|
||||
}
|
||||
|
||||
#undef THREEFISH
|
||||
#undef INJECTKEY
|
||||
246
DependentExtensions/cat/src/crypt/hash/Skein512.cpp
Normal file
246
DependentExtensions/cat/src/crypt/hash/Skein512.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
using namespace cat;
|
||||
|
||||
#define THREEFISH(R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, RA, RB, RC, RD, RE, RF) \
|
||||
x[0] += x[1]; x[1] = CAT_ROL64(x[1], R0); x[1] ^= x[0]; \
|
||||
x[2] += x[3]; x[3] = CAT_ROL64(x[3], R1); x[3] ^= x[2]; \
|
||||
x[4] += x[5]; x[5] = CAT_ROL64(x[5], R2); x[5] ^= x[4]; \
|
||||
x[6] += x[7]; x[7] = CAT_ROL64(x[7], R3); x[7] ^= x[6]; \
|
||||
x[2] += x[1]; x[1] = CAT_ROL64(x[1], R4); x[1] ^= x[2]; \
|
||||
x[4] += x[7]; x[7] = CAT_ROL64(x[7], R5); x[7] ^= x[4]; \
|
||||
x[6] += x[5]; x[5] = CAT_ROL64(x[5], R6); x[5] ^= x[6]; \
|
||||
x[0] += x[3]; x[3] = CAT_ROL64(x[3], R7); x[3] ^= x[0]; \
|
||||
x[4] += x[1]; x[1] = CAT_ROL64(x[1], R8); x[1] ^= x[4]; \
|
||||
x[6] += x[3]; x[3] = CAT_ROL64(x[3], R9); x[3] ^= x[6]; \
|
||||
x[0] += x[5]; x[5] = CAT_ROL64(x[5], RA); x[5] ^= x[0]; \
|
||||
x[2] += x[7]; x[7] = CAT_ROL64(x[7], RB); x[7] ^= x[2]; \
|
||||
x[6] += x[1]; x[1] = CAT_ROL64(x[1], RC); x[1] ^= x[6]; \
|
||||
x[0] += x[7]; x[7] = CAT_ROL64(x[7], RD); x[7] ^= x[0]; \
|
||||
x[2] += x[5]; x[5] = CAT_ROL64(x[5], RE); x[5] ^= x[2]; \
|
||||
x[4] += x[3]; x[3] = CAT_ROL64(x[3], RF); x[3] ^= x[4];
|
||||
|
||||
#define INJECTKEY(K0, K1, K2, K3, K4, K5, K6, K7, T0, T1, R) \
|
||||
x[0] += (K0); \
|
||||
x[1] += (K1); \
|
||||
x[2] += (K2); \
|
||||
x[3] += (K3); \
|
||||
x[4] += (K4); \
|
||||
x[5] += (K5) + (T0); \
|
||||
x[6] += (K6) + (T1); \
|
||||
x[7] += (K7) + (R);
|
||||
|
||||
void Skein::HashComputation512(const void *_message, int blocks, u32 byte_count, u64 *NextState)
|
||||
{
|
||||
const int BITS = 512;
|
||||
const int WORDS = BITS / 64;
|
||||
const int BYTES = BITS / 8;
|
||||
const u64 *message = (const u64 *)_message;
|
||||
|
||||
// Key schedule: Chaining
|
||||
u64 k[WORDS+1];
|
||||
memcpy(k, State, BYTES);
|
||||
|
||||
// Key schedule: Tweak
|
||||
u64 t[3];
|
||||
memcpy(t, Tweak, sizeof(Tweak));
|
||||
|
||||
do
|
||||
{
|
||||
t[0] += byte_count;
|
||||
|
||||
// Parity extension
|
||||
t[2] = t[0] ^ t[1];
|
||||
k[WORDS] = 0x1BD11BDAA9FC1A22LL;
|
||||
|
||||
// First full key injection
|
||||
u64 x[WORDS];
|
||||
for (int ii = 0; ii < WORDS; ++ii)
|
||||
{
|
||||
x[ii] = k[ii] + getLE(message[ii]);
|
||||
k[WORDS] ^= k[ii];
|
||||
}
|
||||
|
||||
x[WORDS-3] += t[0];
|
||||
x[WORDS-2] += t[1];
|
||||
|
||||
// 72 rounds
|
||||
|
||||
// 10/26/09: Updated for SHA-3 competition Round 2
|
||||
enum {
|
||||
R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37,
|
||||
R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42,
|
||||
R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39,
|
||||
R_512_3_0=44, R_512_3_1= 9, R_512_3_2=54, R_512_3_3=56,
|
||||
R_512_4_0=39, R_512_4_1=30, R_512_4_2=34, R_512_4_3=24,
|
||||
R_512_5_0=13, R_512_5_1=50, R_512_5_2=10, R_512_5_3=17,
|
||||
R_512_6_0=25, R_512_6_1=29, R_512_6_2=39, R_512_6_3=43,
|
||||
R_512_7_0= 8, R_512_7_1=35, R_512_7_2=56, R_512_7_3=22
|
||||
};
|
||||
|
||||
#if defined(CAT_WORD_64)
|
||||
// Should unroll farther on 64-bit OS
|
||||
for (int round = 1; round <= 18; round += 6)
|
||||
{
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
|
||||
u64 k0 = k[(round)%9];
|
||||
u64 k1 = k[(round+1)%9];
|
||||
u64 k2 = k[(round+2)%9];
|
||||
u64 k3 = k[(round+3)%9];
|
||||
u64 k4 = k[(round+4)%9];
|
||||
u64 k5 = k[(round+5)%9];
|
||||
u64 k6 = k[(round+6)%9];
|
||||
u64 k7 = k[(round+7)%9];
|
||||
u64 k8 = k[(round+8)%9];
|
||||
|
||||
INJECTKEY(k0, k1, k2, k3, k4, k5, k6, k7, t[1], t[2], round);
|
||||
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k1, k2, k3, k4, k5, k6, k7, k8, t[2], t[0], round+1);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k2, k3, k4, k5, k6, k7, k8, k0, t[0], t[1], round+2);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k3, k4, k5, k6, k7, k8, k0, k1, t[1], t[2], round+3);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k4, k5, k6, k7, k8, k0, k1, k2, t[2], t[0], round+4);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k5, k6, k7, k8, k0, k1, k2, k3, t[0], t[1], round+5);
|
||||
}
|
||||
#else
|
||||
for (int round = 1; round <= 18; round += 2)
|
||||
{
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
|
||||
u64 k0 = k[(round)%9];
|
||||
u64 k1 = k[(round+1)%9];
|
||||
u64 k2 = k[(round+2)%9];
|
||||
u64 k3 = k[(round+3)%9];
|
||||
u64 k4 = k[(round+4)%9];
|
||||
u64 k5 = k[(round+5)%9];
|
||||
u64 k6 = k[(round+6)%9];
|
||||
u64 k7 = k[(round+7)%9];
|
||||
u64 k8 = k[(round+8)%9];
|
||||
|
||||
u64 t1 = t[(round+1)%3];
|
||||
|
||||
INJECTKEY(k0, k1, k2, k3, k4, k5, k6, k7, t[(round)%3], t1, round);
|
||||
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
|
||||
INJECTKEY(k1, k2, k3, k4, k5, k6, k7, k8, t1, t[(round+2)%3], round+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[1], k[2], k[3], k[4], k[5], k[6], k[7], k[8], t1, t2, 1);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[2], k[3], k[4], k[5], k[6], k[7], k[8], k[0], t2, t0, 2);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[3], k[4], k[5], k[6], k[7], k[8], k[0], k[1], t0, t1, 3);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[4], k[5], k[6], k[7], k[8], k[0], k[1], k[2], t1, t2, 4);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[5], k[6], k[7], k[8], k[0], k[1], k[2], k[3], t2, t0, 5);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[6], k[7], k[8], k[0], k[1], k[2], k[3], k[4], t0, t1, 6);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[7], k[8], k[0], k[1], k[2], k[3], k[4], k[5], t1, t2, 7);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[8], k[0], k[1], k[2], k[3], k[4], k[5], k[6], t2, t0, 8);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7], t0, t1, 9);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[1], k[2], k[3], k[4], k[5], k[6], k[7], k[8], t1, t2, 10);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[2], k[3], k[4], k[5], k[6], k[7], k[8], k[0], t2, t0, 11);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[3], k[4], k[5], k[6], k[7], k[8], k[0], k[1], t0, t1, 12);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[4], k[5], k[6], k[7], k[8], k[0], k[1], k[2], t1, t2, 13);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[5], k[6], k[7], k[8], k[0], k[1], k[2], k[3], t2, t0, 14);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[6], k[7], k[8], k[0], k[1], k[2], k[3], k[4], t0, t1, 15);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[7], k[8], k[0], k[1], k[2], k[3], k[4], k[5], t1, t2, 16);
|
||||
THREEFISH(R_512_0_0, R_512_0_1, R_512_0_2, R_512_0_3, R_512_1_0, R_512_1_1, R_512_1_2, R_512_1_3,
|
||||
R_512_2_0, R_512_2_1, R_512_2_2, R_512_2_3, R_512_3_0, R_512_3_1, R_512_3_2, R_512_3_3);
|
||||
INJECTKEY(k[8], k[0], k[1], k[2], k[3], k[4], k[5], k[6], t2, t0, 17);
|
||||
THREEFISH(R_512_4_0, R_512_4_1, R_512_4_2, R_512_4_3, R_512_5_0, R_512_5_1, R_512_5_2, R_512_5_3,
|
||||
R_512_6_0, R_512_6_1, R_512_6_2, R_512_6_3, R_512_7_0, R_512_7_1, R_512_7_2, R_512_7_3);
|
||||
INJECTKEY(k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7], t0, t1, 18);
|
||||
*/
|
||||
// Feedforward XOR
|
||||
for (int ii = 0; ii < WORDS; ++ii)
|
||||
k[ii] = x[ii] ^ getLE(message[ii]);
|
||||
|
||||
// Update tweak
|
||||
t[1] &= ~T1_MASK_FIRST;
|
||||
|
||||
// Eat data bytes
|
||||
message += WORDS;
|
||||
} while (--blocks > 0);
|
||||
|
||||
// Update tweak
|
||||
memcpy(Tweak, t, sizeof(Tweak));
|
||||
|
||||
// Update state
|
||||
memcpy(NextState, k, BYTES);
|
||||
}
|
||||
|
||||
#undef THREEFISH
|
||||
#undef INJECTKEY
|
||||
117
DependentExtensions/cat/src/crypt/pass/Passwords.cpp
Normal file
117
DependentExtensions/cat/src/crypt/pass/Passwords.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/pass/Passwords.hpp>
|
||||
#include <cat/crypt/hash/Skein.hpp>
|
||||
#include <cat/lang/Strings.hpp>
|
||||
using namespace cat;
|
||||
|
||||
//// PasswordCreator
|
||||
|
||||
bool PasswordCreator::HashPassword(const void *in_name, int name_bytes,
|
||||
const void *in_password, int password_bytes,
|
||||
void *out_hash /* 32 bytes */)
|
||||
{
|
||||
#if defined(CAT_USER_ERROR_CHECKING)
|
||||
if (!in_name || !in_password || !out_hash || name_bytes < 0 || password_bytes < 0) return false;
|
||||
#endif
|
||||
|
||||
Skein hash;
|
||||
|
||||
if (!hash.BeginKey(HASH_BITS)) return false;
|
||||
hash.Crunch(in_name, name_bytes);
|
||||
hash.Crunch("\r:\n", 3);
|
||||
hash.Crunch(in_password, password_bytes);
|
||||
hash.End();
|
||||
hash.Generate(out_hash, HASH_BYTES, STRENGTHENING_FACTOR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PasswordCreator::HashPasswordString(const char *in_name,
|
||||
const char *in_password,
|
||||
void *out_hash /* 32 bytes */)
|
||||
{
|
||||
int name_bytes = (int)strlen(in_name);
|
||||
int password_bytes = (int)strlen(in_password);
|
||||
|
||||
// Convert name to lower case and count characters
|
||||
char *lcase_name = new char[name_bytes + 1];
|
||||
|
||||
CopyToLowercaseString(in_name, lcase_name);
|
||||
|
||||
bool success = HashPassword(lcase_name, name_bytes, in_password, password_bytes, out_hash);
|
||||
|
||||
delete []lcase_name;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
//// PasswordVerifier
|
||||
|
||||
bool PasswordVerifier::SaltHash(IRandom *prng,
|
||||
const void *in_hash /* 32 bytes */,
|
||||
void *out_salted_hash /* 32 bytes */,
|
||||
u32 *out_salt /* 4 bytes */)
|
||||
{
|
||||
#if defined(CAT_USER_ERROR_CHECKING)
|
||||
if (!prng || !in_hash || !out_salted_hash || !out_salt) return false;
|
||||
#endif
|
||||
|
||||
Skein hash;
|
||||
|
||||
*out_salt = prng->Generate();
|
||||
|
||||
if (!hash.BeginKey(HASH_BITS)) return false;
|
||||
hash.Crunch(in_hash, HASH_BYTES);
|
||||
hash.Crunch(out_salt, sizeof(*out_salt));
|
||||
hash.End();
|
||||
hash.Generate(out_salted_hash, HASH_BYTES);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PasswordVerifier::VerifyHash(const void *in_hash /* 32 bytes */,
|
||||
const void *in_salted_hash /* 32 bytes */,
|
||||
u32 in_salt /* 4 bytes */)
|
||||
{
|
||||
#if defined(CAT_USER_ERROR_CHECKING)
|
||||
if (!in_hash || !in_salted_hash) return false;
|
||||
#endif
|
||||
|
||||
Skein hash;
|
||||
u8 Jp[HASH_BYTES];
|
||||
|
||||
if (!hash.BeginKey(HASH_BITS)) return false;
|
||||
hash.Crunch(&in_salt, sizeof(in_salt));
|
||||
hash.Crunch(in_hash, HASH_BYTES);
|
||||
hash.End();
|
||||
hash.Generate(Jp, HASH_BYTES);
|
||||
|
||||
return cat::SecureEqual(in_salted_hash, Jp, HASH_BYTES);
|
||||
}
|
||||
183
DependentExtensions/cat/src/crypt/privatekey/ChaCha.cpp
Normal file
183
DependentExtensions/cat/src/crypt/privatekey/ChaCha.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/symmetric/ChaCha.hpp>
|
||||
#include <cat/port/EndianNeutral.hpp>
|
||||
#include <string.h>
|
||||
using namespace cat;
|
||||
|
||||
|
||||
//// ChaChaKey
|
||||
|
||||
ChaChaKey::~ChaChaKey()
|
||||
{
|
||||
CAT_OBJCLR(state);
|
||||
}
|
||||
|
||||
static u32 InitialState[12] = {
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
// These are from BLAKE-32:
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
||||
// Took the rest of these from the SHA-256 SBOX constants:
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13
|
||||
};
|
||||
|
||||
// Key up to 384 bits
|
||||
void ChaChaKey::Set(const void *key, int bytes)
|
||||
{
|
||||
// Precondition: Bytes must be a multiple of 4
|
||||
if (bytes > 48) bytes = 48;
|
||||
|
||||
memcpy(state, InitialState, sizeof(InitialState));
|
||||
|
||||
const u32 *in32 = (const u32 *)key;
|
||||
int words = bytes / 4;
|
||||
|
||||
for (int ii = 0; ii < words; ++ii)
|
||||
{
|
||||
state[ii] ^= getLE(in32[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// ChaChaOutput
|
||||
|
||||
#define QUARTERROUND(a,b,c,d) \
|
||||
x[a] += x[b]; x[d] = CAT_ROL32(x[d] ^ x[a], 16); \
|
||||
x[c] += x[d]; x[b] = CAT_ROL32(x[b] ^ x[c], 12); \
|
||||
x[a] += x[b]; x[d] = CAT_ROL32(x[d] ^ x[a], 8); \
|
||||
x[c] += x[d]; x[b] = CAT_ROL32(x[b] ^ x[c], 7);
|
||||
|
||||
void ChaChaOutput::GenerateKeyStream(u32 *out_words)
|
||||
{
|
||||
// Update block counter
|
||||
if (!++state[12]) state[13]++;
|
||||
|
||||
register u32 x[16];
|
||||
|
||||
// Copy state into work registers
|
||||
for (int ii = 0; ii < 16; ++ii)
|
||||
x[ii] = state[ii];
|
||||
|
||||
// Mix state for 12 rounds
|
||||
for (int round = 12; round > 0; round -= 2)
|
||||
{
|
||||
QUARTERROUND(0, 4, 8, 12)
|
||||
QUARTERROUND(1, 5, 9, 13)
|
||||
QUARTERROUND(2, 6, 10, 14)
|
||||
QUARTERROUND(3, 7, 11, 15)
|
||||
QUARTERROUND(0, 5, 10, 15)
|
||||
QUARTERROUND(1, 6, 11, 12)
|
||||
QUARTERROUND(2, 7, 8, 13)
|
||||
QUARTERROUND(3, 4, 9, 14)
|
||||
}
|
||||
|
||||
// Add state to mixed state, little-endian
|
||||
for (int jj = 0; jj < 16; ++jj)
|
||||
out_words[jj] = getLE(x[jj] + state[jj]);
|
||||
}
|
||||
|
||||
ChaChaOutput::ChaChaOutput(const ChaChaKey &key, u64 iv)
|
||||
{
|
||||
for (int ii = 0; ii < 12; ++ii)
|
||||
state[ii] = key.state[ii];
|
||||
|
||||
// Initialize block counter to zero
|
||||
state[12] = 0;
|
||||
state[13] = 0;
|
||||
|
||||
// Initialize IV
|
||||
state[14] = (u32)iv;
|
||||
state[15] = (u32)(iv >> 32);
|
||||
}
|
||||
ChaChaOutput::~ChaChaOutput()
|
||||
{
|
||||
CAT_OBJCLR(state);
|
||||
}
|
||||
|
||||
// Message with any number of bytes
|
||||
void ChaChaOutput::Crypt(const void *in_bytes, void *out_bytes, int bytes)
|
||||
{
|
||||
const u32 *in32 = (const u32 *)in_bytes;
|
||||
u32 *out32 = (u32 *)out_bytes;
|
||||
|
||||
#ifdef CAT_AUDIT
|
||||
int initial_bytes = bytes;
|
||||
printf("AUDIT: ChaCha input ");
|
||||
for (int ii = 0; ii < bytes; ++ii)
|
||||
{
|
||||
printf("%02x", ((cat::u8*)in_bytes)[ii]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
while (bytes >= 64)
|
||||
{
|
||||
u32 key32[16];
|
||||
GenerateKeyStream(key32);
|
||||
|
||||
for (int ii = 0; ii < 16; ++ii)
|
||||
out32[ii] = in32[ii] ^ key32[ii];
|
||||
|
||||
out32 += 16;
|
||||
in32 += 16;
|
||||
bytes -= 64;
|
||||
}
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
u32 key32[16];
|
||||
GenerateKeyStream(key32);
|
||||
|
||||
int words = bytes / 4;
|
||||
for (int ii = 0; ii < words; ++ii)
|
||||
out32[ii] = in32[ii] ^ key32[ii];
|
||||
|
||||
const u8 *in8 = (const u8 *)(in32 + words);
|
||||
u8 *out8 = (u8 *)(out32 + words);
|
||||
const u8 *key8 = (const u8 *)(key32 + words);
|
||||
|
||||
switch (bytes % 4)
|
||||
{
|
||||
case 3: out8[2] = in8[2] ^ key8[2];
|
||||
case 2: out8[1] = in8[1] ^ key8[1];
|
||||
case 1: out8[0] = in8[0] ^ key8[0];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CAT_AUDIT
|
||||
printf("AUDIT: ChaCha output ");
|
||||
for (int ii = 0; ii < initial_bytes; ++ii)
|
||||
{
|
||||
printf("%02x", ((cat::u8*)out_bytes)[ii]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef QUARTERROUND
|
||||
101
DependentExtensions/cat/src/crypt/rand/EntropyGeneric.cpp
Normal file
101
DependentExtensions/cat/src/crypt/rand/EntropyGeneric.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of LibCat nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cat/crypt/rand/Fortuna.hpp>
|
||||
using namespace cat;
|
||||
|
||||
// Used for MacOSX, iPhone, PS3, XBox, and others (for now)
|
||||
// I want to have more of these operating systems defined
|
||||
|
||||
#if !defined(CAT_OS_WINDOWS) && !defined(CAT_OS_LINUX)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#if !defined(CAT_NO_ENTROPY_THREAD)
|
||||
|
||||
bool FortunaFactory::ThreadFunction(void *)
|
||||
{
|
||||
// Generic version does not spawn a thread
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // !defined(CAT_NO_ENTROPY_THREAD)
|
||||
|
||||
|
||||
bool FortunaFactory::InitializeEntropySources()
|
||||
{
|
||||
// Fire poll for entropy all goes into pool 0
|
||||
PollInvariantSources(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FortunaFactory::ShutdownEntropySources()
|
||||
{
|
||||
}
|
||||
|
||||
void FortunaFactory::PollInvariantSources(int pool_index)
|
||||
{
|
||||
Skein &pool = Pool[pool_index];
|
||||
|
||||
struct {
|
||||
u32 cycles_start;
|
||||
u8 system_prng[32];
|
||||
u32 cycles_end;
|
||||
} Sources;
|
||||
|
||||
// Cycles at the start
|
||||
Sources.cycles_start = Clock::cycles();
|
||||
|
||||
int random_fd = open("/dev/random", O_RDONLY);
|
||||
|
||||
// /dev/random large request
|
||||
if (random_fd >= 0)
|
||||
{
|
||||
read(random_fd, Sources.system_prng, sizeof(Sources.system_prng));
|
||||
|
||||
close(random_fd);
|
||||
}
|
||||
|
||||
// Cycles at the end
|
||||
Sources.cycles_end = Clock::cycles();
|
||||
|
||||
pool.Crunch(&Sources, sizeof(Sources));
|
||||
}
|
||||
|
||||
void FortunaFactory::PollSlowEntropySources(int pool_index)
|
||||
{
|
||||
}
|
||||
|
||||
void FortunaFactory::PollFastEntropySources(int pool_index)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user