2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <boost/noncopyable.hpp>
20 #include <glog/logging.h>
27 #include <type_traits>
32 #include <arpa/inet.h>
33 #include <netinet/in.h>
34 #include <sys/socket.h>
38 // missing in socket headers
39 #define sa_family_t ADDRESS_FAMILY
42 #include <sys/types.h>
46 #include <folly/Conv.h>
47 #include <folly/Format.h>
49 // BSDish platforms don't provide standard access to s6_addr16
51 # if defined(__APPLE__) || defined(__FreeBSD__) || \
52 defined(__NetBSD__) || defined(__OpenBSD__)
53 # define s6_addr16 __u6_addr.__u6_addr16
57 namespace folly { namespace detail {
59 inline std::string familyNameStr(sa_family_t family) {
70 return folly::format("sa_family_t({})",
71 folly::to<std::string>(family)).str();
75 template<typename IPAddrType>
76 inline bool getNthMSBitImpl(const IPAddrType& ip, uint8_t bitIndex,
78 if (bitIndex >= ip.bitCount()) {
79 throw std::invalid_argument(folly::to<std::string>("Bit index must be < ",
80 ip.bitCount(), " for addresses of type :", familyNameStr(family)));
82 //Underlying bytes are in n/w byte order
83 return (ip.getNthMSByte(bitIndex / 8) & (0x80 >> (bitIndex % 8))) != 0;
87 * Helper for working with unsigned char* or uint8_t* ByteArray values
89 struct Bytes : private boost::noncopyable {
90 // return true if all values of src are zero
91 static bool isZero(const uint8_t* src, std::size_t len) {
92 for (std::size_t i = 0; i < len; i++) {
100 // mask the values from two byte arrays, returning a new byte array
101 template<std::size_t N>
102 static std::array<uint8_t, N> mask(const std::array<uint8_t, N>& a,
103 const std::array<uint8_t, N>& b) {
104 static_assert(N > 0, "Can't mask an empty ByteArray");
105 std::size_t asize = a.size();
106 std::array<uint8_t, N> ba{{0}};
107 for (std::size_t i = 0; i < asize; i++) {
113 template<std::size_t N>
114 static std::pair<std::array<uint8_t, N>, uint8_t>
116 const std::array<uint8_t, N>& one, uint8_t oneMask,
117 const std::array<uint8_t, N>& two, uint8_t twoMask) {
118 static constexpr auto kBitCount = N * 8;
119 static constexpr std::array<uint8_t, 8> kMasks {{
129 if (oneMask > kBitCount || twoMask > kBitCount) {
130 throw std::invalid_argument(folly::to<std::string>("Invalid mask "
131 "length: ", oneMask > twoMask ? oneMask : twoMask,
132 ". Mask length must be <= ", kBitCount));
135 auto mask = std::min(oneMask, twoMask);
136 uint8_t byteIndex = 0;
137 std::array<uint8_t, N> ba{{0}};
138 // Compare a byte at a time. Note - I measured compared this with
139 // going multiple bytes at a time (8, 4, 2 and 1). It turns out
140 // to be 20 - 25% slower for 4 and 16 byte arrays.
141 while (byteIndex * 8 < mask && one[byteIndex] == two[byteIndex]) {
142 ba[byteIndex] = one[byteIndex];
145 auto bitIndex = std::min(mask, (uint8_t)(byteIndex * 8));
146 // Compute the bit up to which the two byte arrays match in the
148 // Here the check is bitIndex < mask since the 0th mask entry in
149 // kMasks array holds the mask for masking the MSb in this byte.
150 // We could instead make it hold so that no 0th entry masks no
151 // bits but thats a useless iteration.
152 while (bitIndex < mask && ((one[bitIndex / 8] & kMasks[bitIndex % 8]) ==
153 (two[bitIndex / 8] & kMasks[bitIndex % 8]))) {
154 ba[bitIndex / 8] = one[bitIndex / 8] & kMasks[bitIndex % 8];
157 return {ba, bitIndex};
160 // create an in_addr from an uint8_t*
161 static inline in_addr mkAddress4(const uint8_t* src) {
166 std::memset(&addr, 0, 4);
167 std::memcpy(addr.bytes, src, 4);
171 // create an in6_addr from an uint8_t*
172 static inline in6_addr mkAddress6(const uint8_t* src) {
174 std::memset(&addr, 0, 16);
175 std::memcpy(addr.s6_addr, src, 16);
179 // convert an uint8_t* to its hex value
180 static std::string toHex(const uint8_t* src, std::size_t len) {
181 static const char* const lut = "0123456789abcdef";
182 std::stringstream ss;
183 for (std::size_t i = 0; i < len; i++) {
184 const unsigned char c = src[i];
185 ss << lut[c >> 4] << lut[c & 15];
196 // Write a maximum amount of base-converted character digits, of a
197 // given base, from an unsigned integral type into a byte buffer of
200 // This function does not append null terminators.
202 // Output buffer size must be guaranteed by caller (indirectly
203 // controlled by DigitCount template parameter).
205 // Having these parameters at compile time allows compiler to
206 // precompute several of the values, use smaller instructions, and
207 // better optimize surrounding code.
210 // - Something like uint8_t, uint16_t, etc
212 // DigitCount is the maximum number of digits to be printed
213 // - This is tied to IntegralType and Base. For example:
214 // - uint8_t in base 10 will print at most 3 digits ("255")
215 // - uint16_t in base 16 will print at most 4 hex digits ("FFFF")
217 // Base is the desired output base of the string
218 // - Base 10 will print [0-9], base 16 will print [0-9a-f]
221 // - Whether or not leading zeros should be printed
223 template<class IntegralType,
224 IntegralType DigitCount,
225 IntegralType Base = 10,
226 bool PrintAllDigits = false,
227 class = typename std::enable_if<
228 std::is_integral<IntegralType>::value &&
229 std::is_unsigned<IntegralType>::value,
231 inline void writeIntegerString(
236 if (!PrintAllDigits && val == 0) {
242 IntegralType powerToPrint = 1;
243 for (int i = 1; i < DigitCount; ++i) {
244 powerToPrint *= Base;
247 bool found = PrintAllDigits;
248 while (powerToPrint) {
250 if (found || powerToPrint <= val) {
251 IntegralType value = val/powerToPrint;
252 if (Base == 10 || value < 10) {
262 powerToPrint /= Base;
268 inline std::string fastIpv4ToString(
269 const in_addr& inAddr) {
270 const uint8_t* octets = reinterpret_cast<const uint8_t*>(&inAddr.s_addr);
271 char str[sizeof("255.255.255.255")];
274 writeIntegerString<uint8_t, 3>(octets[0], &buf);
276 writeIntegerString<uint8_t, 3>(octets[1], &buf);
278 writeIntegerString<uint8_t, 3>(octets[2], &buf);
280 writeIntegerString<uint8_t, 3>(octets[3], &buf);
282 return std::string(str, buf-str);
285 inline std::string fastIpv6ToString(const in6_addr& in6Addr) {
287 const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.u.Word);
289 const uint16_t* bytes = reinterpret_cast<const uint16_t*>(&in6Addr.s6_addr16);
291 char str[sizeof("2001:0db8:0000:0000:0000:ff00:0042:8329")];
294 for (int i = 0; i < 8; ++i) {
295 writeIntegerString<uint16_t,
296 4, // at most 4 hex digits per ushort
298 true>(htons(bytes[i]), &buf);
305 return std::string(str, buf-str);