0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-20 12:12:15 +02:00

Support Cityhash.

When running build script, add CITY=1 to build with Cityhash library.

Signed-off-by: James Yonan <james@openvpn.net>
This commit is contained in:
James Yonan 2017-08-18 23:56:13 -06:00 committed by Antonio Quartulli
parent fdbb0b96b1
commit ce0977b2ea
6 changed files with 179 additions and 79 deletions

View File

@ -853,23 +853,31 @@ namespace openvpn {
return 0;
}
std::size_t hashval() const
template <typename HASH>
void hash(HASH& h) const
{
std::size_t seed = 0;
switch (ver)
{
case Addr::V4:
Hash::combine(seed, 4, u.v4);
u.v4.hash(h);
break;
case Addr::V6:
Hash::combine(seed, 6, u.v6);
u.v6.hash(h);
break;
default:
break;
}
return seed;
}
#ifdef HAVE_CITYHASH
std::size_t hashval() const
{
HashSizeT h;
hash(h);
return h.value();
}
#endif
#ifdef OPENVPN_IP_IMMUTABLE
private:
#endif
@ -967,6 +975,8 @@ namespace openvpn {
}
}
#ifdef HAVE_CITYHASH
OPENVPN_HASH_METHOD(openvpn::IP::Addr, hashval);
#endif
#endif

View File

@ -35,7 +35,6 @@
#include <openvpn/common/socktypes.hpp>
#include <openvpn/common/ffs.hpp>
#include <openvpn/common/hexstr.hpp>
#include <openvpn/common/hash.hpp>
#include <openvpn/addr/iperr.hpp>
namespace openvpn {
@ -493,9 +492,10 @@ namespace openvpn {
return SIZE;
}
std::size_t hashval() const
template <typename HASH>
void hash(HASH& h) const
{
return Hash::value(u.addr);
h(u.addr);
}
#ifdef OPENVPN_IP_IMMUTABLE
@ -566,6 +566,4 @@ namespace openvpn {
}
}
OPENVPN_HASH_METHOD(openvpn::IPv4::Addr, hashval);
#endif // OPENVPN_ADDR_IPV4_H

View File

@ -34,7 +34,6 @@
#include <openvpn/common/socktypes.hpp>
#include <openvpn/common/ffs.hpp>
#include <openvpn/common/hexstr.hpp>
#include <openvpn/common/hash.hpp>
#include <openvpn/addr/ipv4.hpp>
#include <openvpn/addr/iperr.hpp>
@ -535,9 +534,10 @@ namespace openvpn {
return SIZE;
}
std::size_t hashval() const
template <typename HASH>
void hash(HASH& h) const
{
return Hash::value(u.u32[0], u.u32[1], u.u32[2], u.u32[3]);
h(u.bytes, sizeof(u.bytes));
}
#ifdef OPENVPN_IP_IMMUTABLE
@ -825,6 +825,4 @@ namespace openvpn {
}
}
OPENVPN_HASH_METHOD(openvpn::IPv6::Addr, hashval);
#endif // OPENVPN_ADDR_IPV6_H

View File

@ -167,10 +167,21 @@ namespace openvpn {
return prefix_len == other.prefix_len && addr == other.addr;
}
template <typename HASH>
void hash(HASH& h) const
{
addr.hash(h);
h(prefix_len);
}
#ifdef HAVE_CITYHASH
std::size_t hash_value() const
{
return Hash::value(addr, prefix_len);
HashSizeT h;
hash(h);
return h.value();
}
#endif
};
template <typename ADDR>
@ -253,8 +264,10 @@ namespace openvpn {
}
}
#ifdef HAVE_CITYHASH
OPENVPN_HASH_METHOD(openvpn::IP::Route, hash_value);
OPENVPN_HASH_METHOD(openvpn::IP::Route4, hash_value);
OPENVPN_HASH_METHOD(openvpn::IP::Route6, hash_value);
#endif
#endif

View File

@ -22,11 +22,12 @@
#ifndef OPENVPN_COMMON_HASH_H
#define OPENVPN_COMMON_HASH_H
#include <cstring> // for std::strlen
#include <string>
#include <cstdint> // for std::uint32_t, uint64_t
#include <functional>
#include <openvpn/common/exception.hpp>
#include <openvpn/common/size.hpp>
#include <openvpn/common/hexstr.hpp>
#define OPENVPN_HASH_METHOD(T, meth) \
namespace std { \
@ -40,79 +41,152 @@
}; \
}
#ifdef HAVE_CITYHASH
#ifdef OPENVPN_HASH128_CRC
#include <citycrc.h>
#define OPENVPN_HASH128 ::CityHashCrc128WithSeed
#else
#include <city.h>
#define OPENVPN_HASH128 ::CityHash128WithSeed
#endif
#if SIZE_MAX == 0xFFFFFFFF
#define HashSizeT Hash32
#elif SIZE_MAX == 0xFFFFFFFFFFFFFFFF
#define HashSizeT Hash64
#else
#error "Unrecognized SIZE_MAX"
#endif
namespace openvpn {
namespace Hash {
void combine_data(std::size_t& seed, const void *data, std::size_t size);
class Hash128
{
public:
Hash128() : hashval(0,0) {}
template <class T>
inline void combine(std::size_t& seed, const T& v)
void operator()(const void *data, const std::size_t size)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
hashval = OPENVPN_HASH128((const char *)data, size, hashval);
}
inline void combine(std::size_t& seed, const char *str)
void operator()(const std::string& str)
{
combine_data(seed, str, std::strlen(str));
(*this)(str.c_str(), str.length());
}
template<typename T, typename... Args>
inline void combine(std::size_t& seed, const T& first, Args... args)
{
combine(seed, first);
combine(seed, args...);
}
template<typename... Args>
inline std::size_t value(Args... args)
{
std::size_t hash = 0;
combine(hash, args...);
return hash;
}
// A hasher that combines a data hash with a stateful seed.
template <typename T>
class InitialSeed
inline void operator()(const T& obj)
{
public:
InitialSeed(std::size_t seed) : seed_(seed) {}
std::size_t operator()(const T& obj) const
{
std::size_t seed = seed_;
combine(seed, obj);
return seed;
}
private:
std::size_t seed_;
};
inline void combine_data(std::size_t& seed, const void *data, std::size_t size)
{
while (size >= sizeof(std::uint32_t))
{
combine(seed, static_cast<const std::uint32_t*>(data)[0]);
data = static_cast<const std::uint8_t*>(data) + sizeof(std::uint32_t);
size -= sizeof(std::uint32_t);
}
switch (size)
{
case 1:
combine(seed, static_cast<const std::uint8_t*>(data)[0]);
break;
case 2:
combine(seed, static_cast<const std::uint16_t*>(data)[0]);
break;
case 3:
combine(seed, static_cast<const std::uint16_t*>(data)[0]);
combine(seed, static_cast<const std::uint8_t*>(data)[2]);
break;
}
static_assert(std::is_pod<T>::value, "Hash128: POD type required");
(*this)(&obj, sizeof(obj));
}
}
std::uint64_t high() const
{
return hashval.second;
}
std::uint64_t low() const
{
return hashval.first;
}
std::string to_string() const
{
return render_hex_number(high()) + render_hex_number(low());
}
private:
uint128 hashval;
};
class Hash64
{
public:
Hash64(const std::uint64_t init_hashval=0)
: hashval(init_hashval)
{
}
void operator()(const void *data, const std::size_t size)
{
hashval = ::CityHash64WithSeed((const char *)data, size, hashval);
}
void operator()(const std::string& str)
{
(*this)(str.c_str(), str.length());
}
template <typename T>
inline void operator()(const T& obj)
{
static_assert(std::is_pod<T>::value, "Hash64: POD type required");
(*this)(&obj, sizeof(obj));
}
std::uint64_t value() const
{
return hashval;
}
std::string to_string() const
{
return render_hex_number(hashval);
}
private:
std::uint64_t hashval;
};
class Hash32
{
public:
Hash32(const std::uint32_t init_hashval=0)
: hashval(init_hashval)
{
}
void operator()(const void *data, const std::size_t size)
{
hashval = hash_combine(::CityHash32((const char *)data, size), hashval);
}
void operator()(const std::string& str)
{
(*this)(str.c_str(), str.length());
}
template <typename T>
inline void operator()(const T& obj)
{
static_assert(std::is_pod<T>::value, "Hash64: POD type required");
(*this)(&obj, sizeof(obj));
}
std::uint32_t value() const
{
return hashval;
}
std::string to_string() const
{
return render_hex_number(hashval);
}
private:
static std::uint32_t hash_combine(const std::uint32_t h1,
const std::uint32_t h2)
{
return h1 ^ (h2 + 0x9e3779b9 + (h1<<6) + (h1>>2));
}
std::uint32_t hashval;
};
}
#endif
#endif

View File

@ -42,6 +42,7 @@ if [ -z "$1" ]; then
echo " LZ4=1 -- build with LZ4 compression library"
echo " LZ4_SYS=1 -- build with system LZ4 compression library"
echo " SNAP=1 -- build with Snappy compression library"
echo " CITY=1 -- build with Cityhash hash library"
echo " JAVA=1 -- build with JVM"
echo ' EXTRA_CPP="foo1.cpp foo2.cpp" -- add extra .cpp files'
for s in $(enum_build_extras) ; do
@ -213,6 +214,12 @@ if [ "$SNAP" = "1" ]; then
CPPFLAGS="$CPPFLAGS -DHAVE_SNAPPY"
fi
# Cityhash
if [ "$CITY" = "1" ]; then
LIBS="$LIBS -lcityhash"
CPPFLAGS="$CPPFLAGS -DHAVE_CITYHASH"
fi
# JVM
if [ "$JAVA" = "1" ]; then
if [ -z "$JAVA_HOME" ]; then