return 1;
}
-/**
- * Ubiquitous helper template for writing string appenders
- */
-template <class T> struct IsSomeString {
- enum { value = std::is_same<T, std::string>::value
- || std::is_same<T, fbstring>::value };
-};
-
/**
* Everything implicitly convertible to const char* gets appended.
*/
#include <string>
#include <vector>
+#include <folly/Conv.h>
#include <folly/String.h>
+#include <folly/detail/IPAddressSource.h>
using std::ostream;
using std::string;
if (elemCount == 0 || // weird invalid string
elemCount > 2) { // invalid string (IP/CIDR/extras)
- throw IPAddressFormatException("Invalid ipSlashCidr specified. ",
- "Expected IP/CIDR format, got ",
- "'", ipSlashCidr, "'");
+ throw IPAddressFormatException(to<std::string>(
+ "Invalid ipSlashCidr specified. ",
+ "Expected IP/CIDR format, got ",
+ "'",
+ ipSlashCidr,
+ "'"));
}
IPAddress subnet(vec.at(0));
uint8_t cidr = (defaultCidr > -1) ? defaultCidr : (subnet.isV4() ? 32 : 128);
try {
cidr = to<uint8_t>(vec.at(1));
} catch (...) {
- throw IPAddressFormatException("Mask value ",
- "'", vec.at(1), "' not a valid mask");
+ throw IPAddressFormatException(
+ to<std::string>("Mask value ", "'", vec.at(1), "' not a valid mask"));
}
}
if (cidr > subnet.bitCount()) {
- throw IPAddressFormatException("CIDR value '", cidr, "' ",
- "is > network bit count ",
- "'", subnet.bitCount(), "'");
+ throw IPAddressFormatException(to<std::string>(
+ "CIDR value '",
+ cidr,
+ "' ",
+ "is > network bit count ",
+ "'",
+ subnet.bitCount(),
+ "'"));
}
return std::make_pair(applyMask ? subnet.mask(cidr) : subnet, cidr);
}
+// public static
+std::string IPAddress::networkToString(const CIDRNetwork& network) {
+ return network.first.str() + "/" + folly::to<std::string>(network.second);
+}
+
// public static
IPAddress IPAddress::fromBinary(ByteRange bytes) {
if (bytes.size() == 4) {
return IPAddress(IPAddressV6::fromBinary(bytes));
} else {
string hexval = detail::Bytes::toHex(bytes.data(), bytes.size());
- throw IPAddressFormatException("Invalid address with hex value ",
- "'", hexval, "'");
+ throw IPAddressFormatException(
+ to<std::string>("Invalid address with hex value ", "'", hexval, "'"));
}
}
{
string ip = addr.str(); // inet_pton() needs NUL-terminated string
auto throwFormatException = [&](const string& msg) {
- throw IPAddressFormatException("Invalid IP '", ip, "': ", msg);
+ throw IPAddressFormatException(
+ to<std::string>("Invalid IP '", ip, "': ", msg));
};
if (ip.size() < 2) {
return {IPAddress(0), 0};
}
+[[noreturn]] void IPAddress::asV4Throw() const {
+ auto fam = detail::familyNameStr(family());
+ throw InvalidAddressFamilyException(to<std::string>(
+ "Can't convert address with family ", fam, " to AF_INET address"));
+}
+
+[[noreturn]] void IPAddress::asV6Throw() const {
+ auto fam = detail::familyNameStr(family());
+ throw InvalidAddressFamilyException(to<std::string>(
+ "Can't convert address with family ", fam, " to AF_INET6 address"));
+}
+
+
} // folly
#pragma once
#include <functional>
-#include <iostream>
+#include <iosfwd>
#include <memory>
#include <string>
#include <utility> // std::pair
-#include <boost/operators.hpp>
-
-#include <folly/Conv.h>
-#include <folly/Format.h>
#include <folly/Range.h>
#include <folly/IPAddressException.h>
#include <folly/IPAddressV4.h>
* CHECK(IPAddress::createIPv6(v4addr) == v6map.asV6());
* @encode
*/
-class IPAddress : boost::totally_ordered<IPAddress> {
+class IPAddress {
public:
// returns true iff the input string can be parsed as an ip-address
static bool validate(StringPiece ip);
*
* @return string representing the netblock
*/
- static std::string networkToString(const CIDRNetwork& network) {
- return network.first.str() + "/" + folly::to<std::string>(network.second);
- }
+ static std::string networkToString(const CIDRNetwork& network);
/**
* Create a new IPAddress instance from the provided binary data
* @throws IPAddressFormatException is not a V4 instance
*/
const IPAddressV4& asV4() const {
- if (!isV4()) {
- auto familyName = detail::familyNameStr(family());
- throw InvalidAddressFamilyException("Can't convert address with family ",
- familyName, " to AF_INET address");
+ if (UNLIKELY(!isV4())) {
+ asV4Throw();
}
return addr_.ipV4Addr;
}
* @throws InvalidAddressFamilyException is not a V6 instance
*/
const IPAddressV6& asV6() const {
- if (!isV6()) {
- auto familyName = detail::familyNameStr(family());
- throw InvalidAddressFamilyException("Can't convert address with family ",
- familyName, " to AF_INET6 address");
+ if (UNLIKELY(!isV6())) {
+ asV6Throw();
}
return addr_.ipV6Addr;
}
}
private:
+ [[noreturn]] void asV4Throw() const;
+ [[noreturn]] void asV6Throw() const;
+
typedef union IPAddressV46 {
IPAddressV4 ipV4Addr;
IPAddressV6 ipV6Addr;
bool operator==(const IPAddress& addr1, const IPAddress& addr2);
// Return true if addr1 < addr2
bool operator<(const IPAddress& addr1, const IPAddress& addr2);
+// Derived operators
+inline bool operator!=(const IPAddress& a, const IPAddress& b) {
+ return !(a == b);
+}
+inline bool operator>(const IPAddress& a, const IPAddress& b) {
+ return b < a;
+}
+inline bool operator<=(const IPAddress& a, const IPAddress& b) {
+ return !(a > b);
+}
+inline bool operator>=(const IPAddress& a, const IPAddress& b) {
+ return !(a < b);
+}
} // folly
#include <exception>
#include <string>
+#include <utility>
-#include <folly/Conv.h>
#include <folly/detail/IPAddress.h>
namespace folly {
*/
class IPAddressFormatException : public std::exception {
public:
- explicit IPAddressFormatException(const std::string& msg)
- : msg_(msg) {}
- IPAddressFormatException(
- const IPAddressFormatException&) = default;
- template<typename... Args>
- explicit IPAddressFormatException(Args&&... args)
- : msg_(to<std::string>(std::forward<Args>(args)...)) {}
+ explicit IPAddressFormatException(std::string msg) noexcept
+ : msg_(std::move(msg)) {}
+ IPAddressFormatException(const IPAddressFormatException&) = default;
+ IPAddressFormatException(IPAddressFormatException&&) = default;
+ IPAddressFormatException& operator=(const IPAddressFormatException&) =
+ default;
+ IPAddressFormatException& operator=(IPAddressFormatException&&) = default;
virtual ~IPAddressFormatException() noexcept {}
virtual const char *what(void) const noexcept {
}
private:
- const std::string msg_;
+ std::string msg_;
};
class InvalidAddressFamilyException : public IPAddressFormatException {
public:
- explicit InvalidAddressFamilyException(const std::string& msg)
- : IPAddressFormatException(msg) {}
- InvalidAddressFamilyException(
- const InvalidAddressFamilyException&) = default;
- explicit InvalidAddressFamilyException(sa_family_t family)
- : IPAddressFormatException("Address family " +
- detail::familyNameStr(family) +
- " is not AF_INET or AF_INET6") {}
- template<typename... Args>
- explicit InvalidAddressFamilyException(Args&&... args)
- : IPAddressFormatException(std::forward<Args>(args)...) {}
+ explicit InvalidAddressFamilyException(std::string msg) noexcept
+ : IPAddressFormatException(std::move(msg)) {}
+ explicit InvalidAddressFamilyException(sa_family_t family) noexcept
+ : InvalidAddressFamilyException(
+ "Address family " + detail::familyNameStr(family) +
+ " is not AF_INET or AF_INET6") {}
+ InvalidAddressFamilyException(const InvalidAddressFamilyException&) = default;
+ InvalidAddressFamilyException(InvalidAddressFamilyException&&) = default;
+ InvalidAddressFamilyException& operator=(
+ const InvalidAddressFamilyException&) = default;
+ InvalidAddressFamilyException& operator=(InvalidAddressFamilyException&&) =
+ default;
};
} // folly
#include <folly/Format.h>
#include <folly/IPAddress.h>
#include <folly/IPAddressV6.h>
+#include <folly/detail/IPAddressSource.h>
using std::ostream;
using std::string;
auto str = ip.str();
in_addr addr;
if (inet_pton(AF_INET, str.c_str(), &addr) != 1) {
- throw IPAddressFormatException("Can't convert invalid IP '", ip, "' ",
- "to long");
+ throw IPAddressFormatException(
+ to<std::string>("Can't convert invalid IP '", ip, "' ", "to long"));
}
return addr.s_addr;
}
{
auto ip = addr.str();
if (inet_pton(AF_INET, ip.c_str(), &addr_.inAddr_) != 1) {
- throw IPAddressFormatException("Invalid IPv4 address '", addr, "'");
+ throw IPAddressFormatException(
+ to<std::string>("Invalid IPv4 address '", addr, "'"));
}
}
// public
void IPAddressV4::setFromBinary(ByteRange bytes) {
if (bytes.size() != 4) {
- throw IPAddressFormatException("Invalid IPv4 binary data: length must "
- "be 4 bytes, got ", bytes.size());
+ throw IPAddressFormatException(to<std::string>(
+ "Invalid IPv4 binary data: length must ",
+ "be 4 bytes, got ",
+ bytes.size()));
}
memcpy(&addr_.inAddr_.s_addr, bytes.data(), sizeof(in_addr));
}
auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
auto addr = subnetInfo.first;
if (!addr.isV4()) {
- throw IPAddressFormatException("Address '", addr.toJson(), "' ",
- "is not a V4 address");
+ throw IPAddressFormatException(to<std::string>(
+ "Address '", addr.toJson(), "' ", "is not a V4 address"));
}
return inSubnetWithMask(addr.asV4(), fetchMask(subnetInfo.second));
}
IPAddressV4 IPAddressV4::mask(size_t numBits) const {
static const auto bits = bitCount();
if (numBits > bits) {
- throw IPAddressFormatException("numBits(", numBits,
- ") > bitsCount(", bits, ")");
+ throw IPAddressFormatException(
+ to<std::string>("numBits(", numBits, ") > bitsCount(", bits, ")"));
}
ByteArray4 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_);
const ByteArray4 IPAddressV4::fetchMask(size_t numBits) {
static const uint8_t bits = bitCount();
if (numBits > bits) {
- throw IPAddressFormatException("IPv4 addresses are 32 bits");
+ throw IPAddressFormatException(
+ to<std::string>("IPv4 addresses are 32 bits"));
}
// masks_ is backed by an array so is zero indexed
return masks_[numBits];
}
+// public static
+CIDRNetworkV4 IPAddressV4::longestCommonPrefix(
+ const CIDRNetworkV4& one,
+ const CIDRNetworkV4& two) {
+ auto prefix = detail::Bytes::longestCommonPrefix(
+ one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second);
+ return {IPAddressV4(prefix.first), prefix.second};
+}
// static private
const std::array<ByteArray4, 33> IPAddressV4::masks_ = {{
#pragma once
-#include <functional>
-#include <iostream>
+#include <cstring>
-#include <boost/operators.hpp>
+#include <array>
+#include <functional>
+#include <iosfwd>
#include <folly/Hash.h>
#include <folly/Range.h>
*
* @see IPAddress
*/
-class IPAddressV4 : boost::totally_ordered<IPAddressV4> {
+class IPAddressV4 {
public:
// returns true iff the input string can be parsed as an ipv4-address
static bool validate(StringPiece ip);
// @see IPAddress#isZero
bool isZero() const {
- return detail::Bytes::isZero(bytes(), 4);
+ constexpr auto zero = ByteArray4{{}};
+ return 0 == std::memcmp(bytes(), zero.data(), zero.size());
}
bool isLinkLocalBroadcast() const {
*/
static const ByteArray4 fetchMask(size_t numBits);
- // Given 2 IPAddressV4,mask pairs extract the longest common IPAddress,
+ // Given 2 IPAddressV4, mask pairs extract the longest common IPAddress,
// mask pair
static CIDRNetworkV4 longestCommonPrefix(
- const CIDRNetworkV4& one, const CIDRNetworkV4& two) {
- auto prefix =
- detail::Bytes::longestCommonPrefix(one.first.addr_.bytes_, one.second,
- two.first.addr_.bytes_, two.second);
- return {IPAddressV4(prefix.first), prefix.second};
- }
+ const CIDRNetworkV4& one,
+ const CIDRNetworkV4& two);
// Number of bytes in the address representation.
static size_t byteCount() { return 4; }
//get nth most significant bit - 0 indexed
inline bool operator<(const IPAddressV4& addr1, const IPAddressV4& addr2) {
return (addr1.toLongHBO() < addr2.toLongHBO());
}
+// Derived operators
+inline bool operator!=(const IPAddressV4& a, const IPAddressV4& b) {
+ return !(a == b);
+}
+inline bool operator>(const IPAddressV4& a, const IPAddressV4& b) {
+ return b < a;
+}
+inline bool operator<=(const IPAddressV4& a, const IPAddressV4& b) {
+ return !(a > b);
+}
+inline bool operator>=(const IPAddressV4& a, const IPAddressV4& b) {
+ return !(a < b);
+}
} // folly
#include <folly/IPAddress.h>
#include <folly/IPAddressV4.h>
#include <folly/MacAddress.h>
+#include <folly/detail/IPAddressSource.h>
using std::ostream;
using std::string;
// Allow addresses surrounded in brackets
if (ip.size() < 2) {
- throw IPAddressFormatException("Invalid IPv6 address '", ip,
- "': address too short");
+ throw IPAddressFormatException(
+ to<std::string>("Invalid IPv6 address '", ip, "': address too short"));
}
if (ip.front() == '[' && ip.back() == ']') {
ip = ip.substr(1, ip.size() - 2);
scope_ = ipAddr->sin6_scope_id;
freeaddrinfo(result);
} else {
- throw IPAddressFormatException("Invalid IPv6 address '", ip, "'");
+ throw IPAddressFormatException(
+ to<std::string>("Invalid IPv6 address '", ip, "'"));
}
}
void IPAddressV6::setFromBinary(ByteRange bytes) {
if (bytes.size() != 16) {
- throw IPAddressFormatException("Invalid IPv6 binary data: length must "
- "be 16 bytes, got ", bytes.size());
+ throw IPAddressFormatException(to<std::string>(
+ "Invalid IPv6 binary data: length must ",
+ "be 16 bytes, got ",
+ bytes.size()));
}
memcpy(&addr_.in6Addr_.s6_addr, bytes.data(), sizeof(in6_addr));
scope_ = 0;
auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
auto addr = subnetInfo.first;
if (!addr.isV6()) {
- throw IPAddressFormatException("Address '", addr.toJson(), "' ",
- "is not a V6 address");
+ throw IPAddressFormatException(to<std::string>(
+ "Address '", addr.toJson(), "' ", "is not a V6 address"));
}
return inSubnetWithMask(addr.asV6(), fetchMask(subnetInfo.second));
}
IPAddressV6 IPAddressV6::mask(size_t numBits) const {
static const auto bits = bitCount();
if (numBits > bits) {
- throw IPAddressFormatException("numBits(", numBits, ") > bitCount(",
- bits, ")");
+ throw IPAddressFormatException(
+ to<std::string>("numBits(", numBits, ") > bitCount(", bits, ")"));
}
ByteArray16 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_);
return IPAddressV6(ba);
string ip(buffer);
return ip;
} else {
- throw IPAddressFormatException("Invalid address with hex ",
- "'", detail::Bytes::toHex(bytes(), 16), "'");
+ throw IPAddressFormatException(to<std::string>(
+ "Invalid address with hex ",
+ "'",
+ detail::Bytes::toHex(bytes(), 16),
+ "'"));
}
}
return masks_[numBits];
}
+// public static
+CIDRNetworkV6 IPAddressV6::longestCommonPrefix(
+ const CIDRNetworkV6& one,
+ const CIDRNetworkV6& two) {
+ auto prefix = detail::Bytes::longestCommonPrefix(
+ one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second);
+ return {IPAddressV6(prefix.first), prefix.second};
+}
+
// protected
bool IPAddressV6::inBinarySubnet(const std::array<uint8_t, 2> addr,
size_t numBits) const {
#pragma once
+#include <cstring>
+
+#include <array>
#include <functional>
-#include <iostream>
+#include <iosfwd>
#include <map>
#include <stdexcept>
-#include <boost/operators.hpp>
-
#include <folly/Hash.h>
#include <folly/Range.h>
#include <folly/detail/IPAddress.h>
* Serializing / Deserializing IPAddressB6's on different hosts
* that use link-local scoping probably won't work.
*/
-class IPAddressV6 : boost::totally_ordered<IPAddressV6> {
+class IPAddressV6 {
public:
// V6 Address Type
enum Type {
// @see IPAddress#isZero
bool isZero() const {
- return detail::Bytes::isZero(bytes(), 16);
+ constexpr auto zero = ByteArray16{{}};
+ return 0 == std::memcmp(bytes(), zero.data(), zero.size());
}
bool isLinkLocalBroadcast() const;
static const ByteArray16 fetchMask(size_t numBits);
// Given 2 IPAddressV6,mask pairs extract the longest common IPAddress,
// mask pair
- static CIDRNetworkV6 longestCommonPrefix(const CIDRNetworkV6& one,
- const CIDRNetworkV6& two) {
- auto prefix = detail::Bytes::longestCommonPrefix(
- one.first.addr_.bytes_, one.second,
- two.first.addr_.bytes_, two.second);
- return {IPAddressV6(prefix.first), prefix.second};
- }
+ static CIDRNetworkV6 longestCommonPrefix(
+ const CIDRNetworkV6& one,
+ const CIDRNetworkV6& two);
// Number of bytes in the address representation.
static constexpr size_t byteCount() { return 16; }
return cmp;
}
}
+// Derived operators
+inline bool operator!=(const IPAddressV6& a, const IPAddressV6& b) {
+ return !(a == b);
+}
+inline bool operator>(const IPAddressV6& a, const IPAddressV6& b) {
+ return b < a;
+}
+inline bool operator<=(const IPAddressV6& a, const IPAddressV6& b) {
+ return !(a > b);
+}
+inline bool operator>=(const IPAddressV6& a, const IPAddressV6& b) {
+ return !(a < b);
+}
} // folly
#include <folly/MacAddress.h>
+#include <iostream>
+
#include <folly/Exception.h>
#include <folly/IPAddressV6.h>
#pragma once
-#include <iostream>
-
-#include <boost/operators.hpp>
+#include <iosfwd>
#include <folly/Bits.h>
-#include <folly/Conv.h>
+#include <folly/Range.h>
namespace folly {
/*
* MacAddress represents an IEEE 802 MAC address.
*/
-class MacAddress : private boost::totally_ordered<MacAddress> {
+class MacAddress {
public:
static constexpr size_t SIZE = 6;
static const MacAddress BROADCAST;
return getByte(0) & 0x2;
}
- // Equality and less-than operators.
- // boost::totally_ordered provides the other comparison operators.
+ // Comparison operators.
bool operator==(const MacAddress& other) const {
// All constructors and modifying methods make sure padding is 0,
return u64HBO() < other.u64HBO();
}
+ bool operator!=(const MacAddress& other) const {
+ return !(*this == other);
+ }
+
+ bool operator>(const MacAddress& other) const {
+ return other < *this;
+ }
+
+ bool operator>=(const MacAddress& other) const {
+ return !(*this < other);
+ }
+
+ bool operator<=(const MacAddress& other) const {
+ return !(*this > other);
+ }
+
private:
explicit MacAddress(uint64_t valueNBO) {
memcpy(&bytes_, &valueNBO, 8);
detail/Futex.h \
detail/GroupVarintDetail.h \
detail/IPAddress.h \
+ detail/IPAddressSource.h \
detail/Malloc.h \
detail/MemoryIdler.h \
detail/MPMCPipelineDetail.h \
Bits.cpp \
Checksum.cpp \
detail/CacheLocality.cpp \
+ detail/IPAddress.cpp \
dynamic.cpp \
File.cpp \
FileUtil.cpp \
}
};
+/**
+ * Ubiquitous helper template for knowing what's a string
+ */
+template <class T> struct IsSomeString {
+ enum { value = std::is_same<T, std::string>::value
+ || std::is_same<T, fbstring>::value };
+};
+
} // !namespace folly
#pragma GCC diagnostic pop
#include <folly/SocketAddress.h>
+#include <folly/Exception.h>
#include <folly/Hash.h>
#include <boost/functional/hash.hpp>
#include <errno.h>
#include <sstream>
#include <string>
+#include <system_error>
namespace {
#include <sys/types.h>
#include <cstddef>
-#include <iostream>
+#include <iosfwd>
#include <string>
#include <folly/IPAddress.h>
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/detail/IPAddress.h>
+
+#include <folly/Format.h>
+
+namespace folly { namespace detail {
+
+std::string familyNameStrDefault(sa_family_t family) {
+ return folly::sformat("sa_family_t({})", folly::to<std::string>(family));
+}
+
+[[noreturn]] void getNthMSBitImplThrow(size_t bitCount, sa_family_t family) {
+ throw std::invalid_argument(folly::to<std::string>(
+ "Bit index must be < ",
+ bitCount,
+ " for addresses of type :",
+ familyNameStr(family)));
+}
+
+}}
#pragma once
-#include <boost/noncopyable.hpp>
-#include <glog/logging.h>
-
-#include <algorithm>
-#include <array>
-#include <cstring>
#include <string>
-#include <sstream>
-#include <type_traits>
-#include <vector>
#include <sys/types.h>
-
-#include <folly/Conv.h>
-#include <folly/Format.h>
#include <folly/portability/Sockets.h>
-// BSDish platforms don't provide standard access to s6_addr16
-#ifndef s6_addr16
-# if defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(__NetBSD__) || defined(__OpenBSD__)
-# define s6_addr16 __u6_addr.__u6_addr16
-# endif
-#endif
-
namespace folly { namespace detail {
+std::string familyNameStrDefault(sa_family_t family);
+
inline std::string familyNameStr(sa_family_t family) {
switch (family) {
case AF_INET:
case AF_UNIX:
return "AF_UNIX";
default:
- return folly::format("sa_family_t({})",
- folly::to<std::string>(family)).str();
+ return familyNameStrDefault(family);
}
}
-template<typename IPAddrType>
-inline bool getNthMSBitImpl(const IPAddrType& ip, uint8_t bitIndex,
- sa_family_t family) {
+[[noreturn]] void getNthMSBitImplThrow(size_t bitCount, sa_family_t family);
+
+template <typename IPAddrType>
+inline bool
+getNthMSBitImpl(const IPAddrType& ip, uint8_t bitIndex, sa_family_t family) {
if (bitIndex >= ip.bitCount()) {
- throw std::invalid_argument(folly::to<std::string>("Bit index must be < ",
- ip.bitCount(), " for addresses of type :", familyNameStr(family)));
+ getNthMSBitImplThrow(ip.bitCount(), family);
}
//Underlying bytes are in n/w byte order
return (ip.getNthMSByte(bitIndex / 8) & (0x80 >> (bitIndex % 8))) != 0;
}
-/**
- * Helper for working with unsigned char* or uint8_t* ByteArray values
- */
-struct Bytes : private boost::noncopyable {
- // return true if all values of src are zero
- static bool isZero(const uint8_t* src, std::size_t len) {
- for (std::size_t i = 0; i < len; i++) {
- if (src[i] != 0x00) {
- return false;
- }
- }
- return true;
- }
-
- // mask the values from two byte arrays, returning a new byte array
- template<std::size_t N>
- static std::array<uint8_t, N> mask(const std::array<uint8_t, N>& a,
- const std::array<uint8_t, N>& b) {
- static_assert(N > 0, "Can't mask an empty ByteArray");
- std::size_t asize = a.size();
- std::array<uint8_t, N> ba{{0}};
- for (std::size_t i = 0; i < asize; i++) {
- ba[i] = a[i] & b[i];
- }
- return ba;
- }
-
- template<std::size_t N>
- static std::pair<std::array<uint8_t, N>, uint8_t>
- longestCommonPrefix(
- const std::array<uint8_t, N>& one, uint8_t oneMask,
- const std::array<uint8_t, N>& two, uint8_t twoMask) {
- static constexpr auto kBitCount = N * 8;
- static constexpr std::array<uint8_t, 8> kMasks {{
- 0x80, // /1
- 0xc0, // /2
- 0xe0, // /3
- 0xf0, // /4
- 0xf8, // /5
- 0xfc, // /6
- 0xfe, // /7
- 0xff // /8
- }};
- if (oneMask > kBitCount || twoMask > kBitCount) {
- throw std::invalid_argument(folly::to<std::string>("Invalid mask "
- "length: ", oneMask > twoMask ? oneMask : twoMask,
- ". Mask length must be <= ", kBitCount));
- }
-
- auto mask = std::min(oneMask, twoMask);
- uint8_t byteIndex = 0;
- std::array<uint8_t, N> ba{{0}};
- // Compare a byte at a time. Note - I measured compared this with
- // going multiple bytes at a time (8, 4, 2 and 1). It turns out
- // to be 20 - 25% slower for 4 and 16 byte arrays.
- while (byteIndex * 8 < mask && one[byteIndex] == two[byteIndex]) {
- ba[byteIndex] = one[byteIndex];
- ++byteIndex;
- }
- auto bitIndex = std::min(mask, (uint8_t)(byteIndex * 8));
- // Compute the bit up to which the two byte arrays match in the
- // unmatched byte.
- // Here the check is bitIndex < mask since the 0th mask entry in
- // kMasks array holds the mask for masking the MSb in this byte.
- // We could instead make it hold so that no 0th entry masks no
- // bits but thats a useless iteration.
- while (bitIndex < mask && ((one[bitIndex / 8] & kMasks[bitIndex % 8]) ==
- (two[bitIndex / 8] & kMasks[bitIndex % 8]))) {
- ba[bitIndex / 8] = one[bitIndex / 8] & kMasks[bitIndex % 8];
- ++bitIndex;
- }
- return {ba, bitIndex};
- }
-
- // create an in_addr from an uint8_t*
- static inline in_addr mkAddress4(const uint8_t* src) {
- union {
- in_addr addr;
- uint8_t bytes[4];
- } addr;
- std::memset(&addr, 0, 4);
- std::memcpy(addr.bytes, src, 4);
- return addr.addr;
- }
-
- // create an in6_addr from an uint8_t*
- static inline in6_addr mkAddress6(const uint8_t* src) {
- in6_addr addr;
- std::memset(&addr, 0, 16);
- std::memcpy(addr.s6_addr, src, 16);
- return addr;
- }
-
- // convert an uint8_t* to its hex value
- static std::string toHex(const uint8_t* src, std::size_t len) {
- static const char* const lut = "0123456789abcdef";
- std::stringstream ss;
- for (std::size_t i = 0; i < len; i++) {
- const unsigned char c = src[i];
- ss << lut[c >> 4] << lut[c & 15];
- }
- return ss.str();
- }
-
- private:
- Bytes() = delete;
- ~Bytes() = delete;
-};
-
-//
-// Write a maximum amount of base-converted character digits, of a
-// given base, from an unsigned integral type into a byte buffer of
-// sufficient size.
-//
-// This function does not append null terminators.
-//
-// Output buffer size must be guaranteed by caller (indirectly
-// controlled by DigitCount template parameter).
-//
-// Having these parameters at compile time allows compiler to
-// precompute several of the values, use smaller instructions, and
-// better optimize surrounding code.
-//
-// IntegralType:
-// - Something like uint8_t, uint16_t, etc
-//
-// DigitCount is the maximum number of digits to be printed
-// - This is tied to IntegralType and Base. For example:
-// - uint8_t in base 10 will print at most 3 digits ("255")
-// - uint16_t in base 16 will print at most 4 hex digits ("FFFF")
-//
-// Base is the desired output base of the string
-// - Base 10 will print [0-9], base 16 will print [0-9a-f]
-//
-// PrintAllDigits:
-// - Whether or not leading zeros should be printed
-//
-template<class IntegralType,
- IntegralType DigitCount,
- IntegralType Base = 10,
- bool PrintAllDigits = false,
- class = typename std::enable_if<
- std::is_integral<IntegralType>::value &&
- std::is_unsigned<IntegralType>::value,
- bool>::type>
- inline void writeIntegerString(
- IntegralType val,
- char** buffer) {
- char* buf = *buffer;
-
- if (!PrintAllDigits && val == 0) {
- *(buf++) = '0';
- *buffer = buf;
- return;
- }
-
- IntegralType powerToPrint = 1;
- for (int i = 1; i < DigitCount; ++i) {
- powerToPrint *= Base;
- }
-
- bool found = PrintAllDigits;
- while (powerToPrint) {
-
- if (found || powerToPrint <= val) {
- IntegralType value = val/powerToPrint;
- if (Base == 10 || value < 10) {
- value += '0';
- } else {
- value += ('a'-10);
- }
- *(buf++) = value;
- val %= powerToPrint;
- found = true;
- }
-
- powerToPrint /= Base;
- }
-
- *buffer = buf;
-}
-
-inline std::string fastIpv4ToString(
- const in_addr& inAddr) {
- const uint8_t* octets = reinterpret_cast<const uint8_t*>(&inAddr.s_addr);
- char str[sizeof("255.255.255.255")];
- char* buf = str;
-
- writeIntegerString<uint8_t, 3>(octets[0], &buf);
- *(buf++) = '.';
- writeIntegerString<uint8_t, 3>(octets[1], &buf);
- *(buf++) = '.';
- writeIntegerString<uint8_t, 3>(octets[2], &buf);
- *(buf++) = '.';
- writeIntegerString<uint8_t, 3>(octets[3], &buf);
-
- return std::string(str, buf-str);
-}
-
-inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
-#ifdef _MSC_VER
- const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.u.Word);
-#else
- const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.s6_addr16);
-#endif
- char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
- char* buf = str;
-
- for (int i = 0; i < 8; ++i) {
- writeIntegerString<uint16_t,
- 4, // at most 4 hex digits per ushort
- 16, // base 16 (hex)
- true>(htons(bytes[i]), &buf);
-
- if(i != 7) {
- *(buf++) = ':';
- }
- }
-
- return std::string(str, buf-str);
-}
-
}} // folly::detail
--- /dev/null
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <glog/logging.h>
+#include <sys/types.h>
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <string>
+#include <type_traits>
+
+#include <folly/Conv.h>
+#include <folly/detail/IPAddress.h>
+
+// BSDish platforms don't provide standard access to s6_addr16
+#ifndef s6_addr16
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
+ defined(__OpenBSD__)
+#define s6_addr16 __u6_addr.__u6_addr16
+#endif
+#endif
+
+namespace folly {
+namespace detail {
+
+/**
+ * Helper for working with unsigned char* or uint8_t* ByteArray values
+ */
+struct Bytes {
+ // mask the values from two byte arrays, returning a new byte array
+ template <std::size_t N>
+ static std::array<uint8_t, N> mask(
+ const std::array<uint8_t, N>& a,
+ const std::array<uint8_t, N>& b) {
+ static_assert(N > 0, "Can't mask an empty ByteArray");
+ std::size_t asize = a.size();
+ std::array<uint8_t, N> ba{{0}};
+ for (std::size_t i = 0; i < asize; i++) {
+ ba[i] = a[i] & b[i];
+ }
+ return ba;
+ }
+
+ template <std::size_t N>
+ static std::pair<std::array<uint8_t, N>, uint8_t> longestCommonPrefix(
+ const std::array<uint8_t, N>& one,
+ uint8_t oneMask,
+ const std::array<uint8_t, N>& two,
+ uint8_t twoMask) {
+ static constexpr auto kBitCount = N * 8;
+ static constexpr std::array<uint8_t, 8> kMasks{{
+ 0x80, // /1
+ 0xc0, // /2
+ 0xe0, // /3
+ 0xf0, // /4
+ 0xf8, // /5
+ 0xfc, // /6
+ 0xfe, // /7
+ 0xff // /8
+ }};
+ if (oneMask > kBitCount || twoMask > kBitCount) {
+ throw std::invalid_argument(folly::to<std::string>(
+ "Invalid mask "
+ "length: ",
+ oneMask > twoMask ? oneMask : twoMask,
+ ". Mask length must be <= ",
+ kBitCount));
+ }
+
+ auto mask = std::min(oneMask, twoMask);
+ uint8_t byteIndex = 0;
+ std::array<uint8_t, N> ba{{0}};
+ // Compare a byte at a time. Note - I measured compared this with
+ // going multiple bytes at a time (8, 4, 2 and 1). It turns out
+ // to be 20 - 25% slower for 4 and 16 byte arrays.
+ while (byteIndex * 8 < mask && one[byteIndex] == two[byteIndex]) {
+ ba[byteIndex] = one[byteIndex];
+ ++byteIndex;
+ }
+ auto bitIndex = std::min(mask, (uint8_t)(byteIndex * 8));
+ // Compute the bit up to which the two byte arrays match in the
+ // unmatched byte.
+ // Here the check is bitIndex < mask since the 0th mask entry in
+ // kMasks array holds the mask for masking the MSb in this byte.
+ // We could instead make it hold so that no 0th entry masks no
+ // bits but thats a useless iteration.
+ while (bitIndex < mask && ((one[bitIndex / 8] & kMasks[bitIndex % 8]) ==
+ (two[bitIndex / 8] & kMasks[bitIndex % 8]))) {
+ ba[bitIndex / 8] = one[bitIndex / 8] & kMasks[bitIndex % 8];
+ ++bitIndex;
+ }
+ return {ba, bitIndex};
+ }
+
+ // create an in_addr from an uint8_t*
+ static inline in_addr mkAddress4(const uint8_t* src) {
+ union {
+ in_addr addr;
+ uint8_t bytes[4];
+ } addr;
+ std::memset(&addr, 0, 4);
+ std::memcpy(addr.bytes, src, 4);
+ return addr.addr;
+ }
+
+ // create an in6_addr from an uint8_t*
+ static inline in6_addr mkAddress6(const uint8_t* src) {
+ in6_addr addr;
+ std::memset(&addr, 0, 16);
+ std::memcpy(addr.s6_addr, src, 16);
+ return addr;
+ }
+
+ // convert an uint8_t* to its hex value
+ static std::string toHex(const uint8_t* src, std::size_t len) {
+ static const char* const lut = "0123456789abcdef";
+ std::string out(len * 2, 0);
+ for (std::size_t i = 0; i < len; i++) {
+ const unsigned char c = src[i];
+ out[i * 2 + 0] = lut[c >> 4];
+ out[i + 2 + 1] = lut[c & 15];
+ }
+ return out;
+ }
+
+ private:
+ Bytes() = delete;
+ ~Bytes() = delete;
+};
+
+//
+// Write a maximum amount of base-converted character digits, of a
+// given base, from an unsigned integral type into a byte buffer of
+// sufficient size.
+//
+// This function does not append null terminators.
+//
+// Output buffer size must be guaranteed by caller (indirectly
+// controlled by DigitCount template parameter).
+//
+// Having these parameters at compile time allows compiler to
+// precompute several of the values, use smaller instructions, and
+// better optimize surrounding code.
+//
+// IntegralType:
+// - Something like uint8_t, uint16_t, etc
+//
+// DigitCount is the maximum number of digits to be printed
+// - This is tied to IntegralType and Base. For example:
+// - uint8_t in base 10 will print at most 3 digits ("255")
+// - uint16_t in base 16 will print at most 4 hex digits ("FFFF")
+//
+// Base is the desired output base of the string
+// - Base 10 will print [0-9], base 16 will print [0-9a-f]
+//
+// PrintAllDigits:
+// - Whether or not leading zeros should be printed
+//
+template <
+ class IntegralType,
+ IntegralType DigitCount,
+ IntegralType Base = 10,
+ bool PrintAllDigits = false,
+ class = typename std::enable_if<
+ std::is_integral<IntegralType>::value &&
+ std::is_unsigned<IntegralType>::value,
+ bool>::type>
+inline void writeIntegerString(IntegralType val, char** buffer) {
+ char* buf = *buffer;
+
+ if (!PrintAllDigits && val == 0) {
+ *(buf++) = '0';
+ *buffer = buf;
+ return;
+ }
+
+ IntegralType powerToPrint = 1;
+ for (int i = 1; i < DigitCount; ++i) {
+ powerToPrint *= Base;
+ }
+
+ bool found = PrintAllDigits;
+ while (powerToPrint) {
+ if (found || powerToPrint <= val) {
+ IntegralType value = val / powerToPrint;
+ if (Base == 10 || value < 10) {
+ value += '0';
+ } else {
+ value += ('a' - 10);
+ }
+ *(buf++) = value;
+ val %= powerToPrint;
+ found = true;
+ }
+
+ powerToPrint /= Base;
+ }
+
+ *buffer = buf;
+}
+
+inline std::string fastIpv4ToString(const in_addr& inAddr) {
+ const uint8_t* octets = reinterpret_cast<const uint8_t*>(&inAddr.s_addr);
+ char str[sizeof("255.255.255.255")];
+ char* buf = str;
+
+ writeIntegerString<uint8_t, 3>(octets[0], &buf);
+ *(buf++) = '.';
+ writeIntegerString<uint8_t, 3>(octets[1], &buf);
+ *(buf++) = '.';
+ writeIntegerString<uint8_t, 3>(octets[2], &buf);
+ *(buf++) = '.';
+ writeIntegerString<uint8_t, 3>(octets[3], &buf);
+
+ return std::string(str, buf - str);
+}
+
+inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
+#ifdef _MSC_VER
+ const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.u.Word);
+#else
+ const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.s6_addr16);
+#endif
+ char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
+ char* buf = str;
+
+ for (int i = 0; i < 8; ++i) {
+ writeIntegerString<
+ uint16_t,
+ 4, // at most 4 hex digits per ushort
+ 16, // base 16 (hex)
+ true>(htons(bytes[i]), &buf);
+
+ if (i != 7) {
+ *(buf++) = ':';
+ }
+ }
+
+ return std::string(str, buf - str);
+}
+}
+}
#include <folly/FileUtil.h>
#include <folly/SocketAddress.h>
+#include <folly/String.h>
#include <folly/detail/SocketFastOpen.h>
#include <folly/io/async/EventBase.h>
#include <folly/io/async/NotificationQueue.h>
*/
#include <folly/io/async/test/BlockingSocket.h>
+#include <iostream>
+
#include <folly/ExceptionWrapper.h>
#include <gflags/gflags.h>
#include <folly/Bits.h>
#include <folly/Format.h>
-#include <folly/String.h>
#include <folly/MacAddress.h>
+#include <folly/String.h>
+#include <folly/detail/IPAddressSource.h>
using namespace folly;
using namespace std;
#include <gtest/gtest.h>
+#include <folly/Conv.h>
#include <folly/IPAddressV6.h>
#include <folly/MacAddress.h>
#include <gtest/gtest.h>
#include <iostream>
#include <sstream>
+#include <system_error>
+
#include <folly/test/SocketAddressTestHelper.h>
using namespace boost;