X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FIPAddress.h;h=20eddb910f2c88b9193c62d6e8d6b537903dfa32;hb=dc2c2837d095c9d3a5407e939a88b982ba37858a;hp=c5f57aadd9584f754d89288bbca46c7a351e5574;hpb=dced19f55cf70ce7c0b881af5125d95b76321373;p=folly.git diff --git a/folly/IPAddress.h b/folly/IPAddress.h index c5f57aad..20eddb91 100644 --- a/folly/IPAddress.h +++ b/folly/IPAddress.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,19 +17,16 @@ #pragma once #include -#include +#include #include #include #include // std::pair -#include - -#include "folly/Format.h" -#include "folly/Range.h" -#include "folly/IPAddressException.h" -#include "folly/IPAddressV4.h" -#include "folly/IPAddressV6.h" -#include "folly/detail/IPAddress.h" +#include +#include +#include +#include +#include namespace folly { @@ -67,8 +64,11 @@ typedef std::pair CIDRNetwork; * CHECK(IPAddress::createIPv6(v4addr) == v6map.asV6()); * @encode */ -class IPAddress : boost::totally_ordered { +class IPAddress { public: + // returns true iff the input string can be parsed as an ip-address + static bool validate(StringPiece ip); + // return the V4 representation of the address, converting it from V6 to V4 if // needed. Note that this will throw an IPAddressFormatException if the V6 // address is not IPv4Mapped. @@ -97,9 +97,7 @@ class IPAddress : boost::totally_ordered { * * @return string representing the netblock */ - static std::string networkToString(const CIDRNetwork& network) { - return network.first.str() + "/" + std::to_string(network.second); - } + static std::string networkToString(const CIDRNetwork& network); /** * Create a new IPAddress instance from the provided binary data @@ -166,10 +164,8 @@ class IPAddress : boost::totally_ordered { * @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; } @@ -179,10 +175,8 @@ class IPAddress : boost::totally_ordered { * @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; } @@ -197,15 +191,23 @@ class IPAddress : boost::totally_ordered { } memset(dest, 0, sizeof(sockaddr_storage)); dest->ss_family = family(); + if (isV4()) { sockaddr_in *sin = reinterpret_cast(dest); sin->sin_addr = asV4().toAddr(); sin->sin_port = port; +#if defined(__APPLE__) + sin->sin_len = sizeof(*sin); +#endif return sizeof(*sin); } else if (isV6()) { sockaddr_in6 *sin = reinterpret_cast(dest); sin->sin6_addr = asV6().toAddr(); sin->sin6_port = port; + sin->sin6_scope_id = asV6().getScopeId(); +#if defined(__APPLE__) + sin->sin6_len = sizeof(*sin); +#endif return sizeof(*sin); } else { throw InvalidAddressFamilyException(family()); @@ -251,6 +253,12 @@ class IPAddress : boost::totally_ordered { return isV6() && asV6().isIPv4Mapped(); } + // @return true if address is uninitialized + bool empty() const { return (family_ == AF_UNSPEC); } + + // @return true if address is initialized + explicit operator bool() const { return !empty(); } + // @return true if this is an IPAddressV4 instance bool isV4() const { return (family_ == AF_INET); } @@ -310,6 +318,12 @@ class IPAddress : boost::totally_ordered { : asV6().isLoopback(); } + // Return true if the address qualifies as link local + bool isLinkLocal() const { + return isV4() ? asV4().isLinkLocal() + : asV6().isLinkLocal(); + } + // Return true if the address qualifies as broadcast. bool isLinkLocalBroadcast() const { return isV4() ? asV4().isLinkLocalBroadcast() @@ -349,8 +363,8 @@ class IPAddress : boost::totally_ordered { * @return IPAddress instance with bits set to 0 */ IPAddress mask(uint8_t numBits) const { - return isV4() ? IPAddress(std::move(asV4().mask(numBits))) - : IPAddress(std::move(asV6().mask(numBits))); + return isV4() ? IPAddress(asV4().mask(numBits)) + : IPAddress(asV6().mask(numBits)); } /** @@ -387,6 +401,9 @@ class IPAddress : boost::totally_ordered { } private: + [[noreturn]] void asV4Throw() const; + [[noreturn]] void asV6Throw() const; + typedef union IPAddressV46 { IPAddressV4 ipV4Addr; IPAddressV6 ipV6Addr; @@ -420,6 +437,19 @@ void toAppend(IPAddress addr, fbstring* result); 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