aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/net/socket_address.h
blob: a070202ef2ccf501e42110fe86aefdaf5cacbff8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include <vespa/vespalib/stllike/string.h>
#include "socket_handle.h"
#include <vector>
#include <sys/socket.h>
#include <functional>

struct sockaddr_in;
struct sockaddr_in6;
struct sockaddr_un;

namespace vespalib {

/**
 * Wrapper class for low-level TCP/IP and IPC socket addresses.
 **/
class SocketAddress
{
private:
    socklen_t        _size;
    sockaddr_storage _addr;

    const sockaddr *addr() const { return reinterpret_cast<const sockaddr *>(&_addr); }
    const sockaddr_in *addr_in() const { return reinterpret_cast<const sockaddr_in *>(&_addr); }
    const sockaddr_in6 *addr_in6() const { return reinterpret_cast<const sockaddr_in6 *>(&_addr); }
    const sockaddr_un *addr_un() const { return reinterpret_cast<const sockaddr_un *>(&_addr); }
    SocketAddress(const sockaddr *addr_in, socklen_t addrlen_in);
public:
    SocketAddress() noexcept { memset(this, 0, sizeof(SocketAddress)); }
    SocketAddress(const SocketAddress &rhs) noexcept { memcpy(this, &rhs, sizeof(SocketAddress)); }
    SocketAddress &operator=(const SocketAddress &rhs) noexcept {
        memcpy(this, &rhs, sizeof(SocketAddress));
        return *this;
    }
    const sockaddr *raw_addr() const { return addr(); }
    socklen_t raw_addr_len() const { return _size; }
    bool valid() const { return (_size >= sizeof(sa_family_t)); }
    bool is_ipv4() const { return (valid() && (_addr.ss_family == AF_INET)); }
    bool is_ipv6() const { return (valid() && (_addr.ss_family == AF_INET6)); }
    bool is_ipc() const { return (valid() && (_addr.ss_family == AF_UNIX)); }
    bool is_wildcard() const;
    bool is_abstract() const;
    int port() const;
    vespalib::string ip_address() const;
    vespalib::string reverse_lookup() const;
    vespalib::string path() const;
    vespalib::string name() const;
    vespalib::string spec() const;
    SocketHandle raw_socket() const;
    SocketHandle connect(const std::function<bool(SocketHandle&)> &tweak) const;
    SocketHandle connect() const { return connect([](SocketHandle&) noexcept { return true; }); }
    SocketHandle connect_async() const {
        return connect([](SocketHandle &handle){ return handle.set_blocking(false); });
    }
    SocketHandle listen(int backlog = 500) const;
    static SocketAddress address_of(int sockfd);
    static SocketAddress peer_address(int sockfd);
    static std::vector<SocketAddress> resolve(int port, const char *node = nullptr);
    static SocketAddress select_local(int port, const char *node = nullptr);
    static SocketAddress select_remote(int port, const char *node = nullptr);
    template <typename SELECTOR>
    static SocketAddress select(const SELECTOR &replace, int port, const char *node = nullptr) {
        auto list = resolve(port, node);
        if (!list.empty()) {
            size_t best = 0;
            for (size_t i = 1; i < list.size(); ++i) {
                if (replace(list[best], list[i])) {
                    best = i;
                }
            }
            return list[best];
        }
        return SocketAddress();
    }
    static SocketAddress from_path(const vespalib::string &path);
    static SocketAddress from_name(const vespalib::string &name);
    static std::vector<SocketAddress> get_interfaces();
    static vespalib::string normalize(const vespalib::string &host_name);
};

} // namespace vespalib