blob: 6fb9e596e314a812877c32882894cf02db944adf [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#ifndef KUDU_UTIL_NET_SOCKADDR_H
#define KUDU_UTIL_NET_SOCKADDR_H
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include <glog/logging.h>
#include "kudu/util/status.h"
namespace kudu {
class HostPort;
/// Represents a sockaddr.
///
/// Typically this wraps a sockaddr_in, but in the future will be extended to support
/// IPv6 and Unix sockets.
class Sockaddr {
public:
// Create an uninitialized socket. This instance must be assigned to before usage.
Sockaddr();
~Sockaddr();
// Copy constructor.
Sockaddr(const Sockaddr& other) noexcept;
// Construct from an IPv4 socket address.
explicit Sockaddr(const struct sockaddr_in& addr);
explicit Sockaddr(const struct sockaddr& addr, socklen_t len);
// Return the IPv4 wildcard address.
static Sockaddr Wildcard();
// Assignment operators.
Sockaddr& operator=(const Sockaddr& other) noexcept;
Sockaddr& operator=(const struct sockaddr_in& addr);
// Compare two addresses for equality. To be equal, the addresses must have the same
// family and have the same bytewise representation. Two uninitialized addresses
// are equal to each other but not to any other address.
bool operator==(const Sockaddr& other) const;
uint32_t HashCode() const;
// Compare two addresses bytewise.
//
// Returns a negative, zero, or positive integer to indicate if 'a' is less than,
// equal to, or greater than 'b'.
//
// Addresses of different families (or uninitialized addresses) can be safely compared.
// The comparison result has no semantic meaning but is deterministic.
static int BytewiseCompare(const Sockaddr& a, const Sockaddr& b);
static bool BytewiseLess(const Sockaddr& a, const Sockaddr& b) {
return BytewiseCompare(a, b) < 0;
}
bool is_initialized() const {
return len_ != 0;
}
// Parse a string IPv4 address of the form "A.B.C.D:port", storing the result
// in this Sockaddr object. If no ':port' is specified, uses 'default_port'.
// Note that this function will not handle resolving hostnames.
//
// Returns a bad Status if the input is malformed.
Status ParseString(const std::string& s, uint16_t default_port);
// Parse a HostPort instance which must contain a hostname in numeric notation
// as described above.
//
// Note that this function will not handle resolving hostnames.
Status ParseFromNumericHostPort(const HostPort& hp);
// Parse a UNIX domain path, storing the result in this Sockaddr object.
// A leading '@' indicates the address should be in the UNIX domain "abstract
// namespace" (see man unix(7)).
//
// May return InvalidArgument if the path is too long.
Status ParseUnixDomainPath(const std::string& s);
// Returns the dotted-decimal string '1.2.3.4' of the host component of this address.
std::string host() const;
// Set the IP port for this address.
// REQUIRES: is an IPv4 address.
void set_port(int port);
// Get the IP port for this address.
// REQUIRES: is an IPv4 address.
int port() const;
// Get the path for this address, assuming it's a UNIX domain socket address.
//
// REQUIRES: family() is AF_UNIX.
std::string UnixDomainPath() const;
// Return the type of UNIX domain socket address. See the unix(7) manpage for more
// details.
//
// REQUIRES: family() is AF_UNIX.
enum class UnixAddressType {
// A path-based socket visible on the filesystem.
kPath,
// A stream socket that has not been bound to a pathname using bind(2) has no
// name. For example, the address of a peer connected to a server has no name.
kUnnamed,
// A socket visible in the abstract namespace.
kAbstractNamespace,
};
UnixAddressType unix_address_type() const;
const struct sockaddr* addr() const {
return reinterpret_cast<const sockaddr*>(&storage_);
}
socklen_t addrlen() const {
DCHECK(is_initialized());
return len_;
}
const struct sockaddr_in& ipv4_addr() const;
sa_family_t family() const {
DCHECK(is_initialized());
return storage_.generic.ss_family;
}
bool is_ip() const {
return family() == AF_INET;
}
bool is_unix() const {
return family() == AF_UNIX;
}
// Returns the stringified address in '1.2.3.4:<port>' format.
std::string ToString() const;
// Returns true if the address is 0.0.0.0
bool IsWildcard() const;
// Returns true if the address is 127.*.*.* or a unix socket.
bool IsAnyLocalAddress() const;
// Does reverse DNS lookup of the address and stores it in hostname.
Status LookupHostname(std::string* hostname) const;
// Takes a vector of Sockaddr objects and returns a comma separated
// string containing ip addresses.
static std::string ToCommaSeparatedString(const std::vector<Sockaddr>& addrs);
// the default auto-generated copy constructor is fine here
private:
// Set the length of the internal storage to 'len' and adjust ASAN poisoning
// appropriately.
void set_length(socklen_t len);
// The length of valid bytes in storage_.
//
// For an uninitialized socket, this will be 0. Otherwise, this is guaranteed
// to be at least sizeof(sa_family_t).
//
// For some address types (ipv4, ipv6) this is fixed to the size of the appropriate
// struct. For other types (unix) this is variable-length depending on the length of
// the path.
socklen_t len_ = 0;
// Internal storage. This is a tagged union based on 'generic.ss_family'.
union {
struct sockaddr_storage generic;
struct sockaddr_in in;
struct sockaddr_un un;
} storage_;
};
} // namespace kudu
// Specialize std::hash for Sockaddr
namespace std {
template<>
struct hash<kudu::Sockaddr> {
int operator()(const kudu::Sockaddr& addr) const {
return addr.HashCode();
}
};
} // namespace std
#endif