Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions include/seastar/core/reactor.hh
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,6 @@ class reactor;

}

namespace std {

template <>
struct hash<::sockaddr_in> {
size_t operator()(::sockaddr_in a) const {
return a.sin_port ^ a.sin_addr.s_addr;
}
};

}

bool operator==(const ::sockaddr_in a, const ::sockaddr_in b);

namespace seastar {

class thread_pool;
Expand Down
8 changes: 4 additions & 4 deletions include/seastar/http/httpd.hh
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ public:
, _fd(std::move(fd))
, _read_buf(_fd.input())
, _write_buf(_fd.output())
, _client_addr(_fd.remote_address())
, _server_addr(_fd.local_address())
, _client_addr(_fd.remote_address().unmapped())
, _server_addr(_fd.local_address().unmapped())
, _tls(tls) {
on_new_connection();
}
Expand All @@ -93,8 +93,8 @@ public:
, _fd(std::move(fd))
, _read_buf(_fd.input())
, _write_buf(_fd.output())
, _client_addr(std::move(client_addr))
, _server_addr(std::move(server_addr))
, _client_addr(client_addr.unmapped())
, _server_addr(server_addr.unmapped())
, _tls(tls) {
on_new_connection();
}
Expand Down
27 changes: 27 additions & 0 deletions include/seastar/http/request.hh
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,28 @@ public:
*/
static request make(httpd::operation_type type, sstring host, sstring path);

/**
* \brief Make simple request to an address
*
* \param method - method to use, e.g. "GET"
* \param addr - the address to contact. The "Host" header is its RFC 3986
* authority form, i.e. an IPv6 address is bracketed.
* \path - the URL to send the request to
*
*/
static request make(sstring method, const socket_address& addr, sstring path);

/**
* \brief Make simple request to an address
*
* \param method - method to use, e.g. operation_type::GET
* \param addr - the address to contact. The "Host" header is its RFC 3986
* authority form, i.e. an IPv6 address is bracketed.
* \path - the URL to send the request to
*
*/
static request make(httpd::operation_type type, const socket_address& addr, sstring path);

sstring request_line() const;
future<> write_request_headers(output_stream<char>& out) const;
private:
Expand All @@ -430,6 +452,11 @@ private:
};

namespace internal {

/// The RFC 3986 §3.2.2 authority for \param addr: "host:port", with an IPv6
/// address bracketed. A zone index is not part of an authority and is dropped.
sstring format_authority(const socket_address& addr);

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
inline sstring& deprecated_content(request& req) noexcept { return req.content; }
Expand Down
13 changes: 12 additions & 1 deletion include/seastar/net/api.hh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ socket_address make_ipv4_address(uint32_t ip, uint16_t port) noexcept {
return make_ipv4_address(ipv4_addr(ip, port));
}

inline
socket_address make_ipv6_address(const ipv6_addr& addr) noexcept {
return socket_address(addr);
}

namespace net {

// see linux tcp(7) for parameter explanation
Expand Down Expand Up @@ -432,6 +437,11 @@ struct listen_options {
/// setting it directly on the already-accepted socket is ineffective (see TCP(7)).
std::optional<int> so_rcvbuf;

/// If set, applied as IPV6_V6ONLY before bind on an AF_INET6 socket, so a
/// `[::]` listener's dual-stackness does not follow net.ipv6.bindv6only.
/// Ignored for other families.
std::optional<bool> ipv6_only;

void set_fixed_cpu(unsigned cpu) {
lba = server_socket::load_balancing_algorithm::fixed;
fixed_cpu = cpu;
Expand Down Expand Up @@ -490,7 +500,8 @@ class network_stack {
public:
virtual ~network_stack() {}
virtual server_socket listen(socket_address sa, listen_options opts) = 0;
// FIXME: local parameter assumes ipv4 for now, fix when adding other AF
// `local` may be of either family; unspecified means the wildcard address
// of the destination's family, with a port the system picks.
future<connected_socket> connect(socket_address sa, socket_address = {}, transport proto = transport::TCP);
virtual ::seastar::socket socket() = 0;

Expand Down
5 changes: 5 additions & 0 deletions include/seastar/net/inet_address.hh
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ public:
bool is_ipv4() const noexcept {
return _in_family == family::INET;
}
/// An IPv4 address carried inside an IPv6 one (::ffff:a.b.c.d), which is how
/// the kernel reports IPv4 peers of a dual-stack `[::]` listener.
bool is_ipv4_mapped() const noexcept;
/// The IPv4 address an IPv4-mapped address stands for; any other address unchanged.
inet_address unmapped() const noexcept;

size_t size() const noexcept;
const void * data() const noexcept;
Expand Down
21 changes: 19 additions & 2 deletions include/seastar/net/socket_defs.hh
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ public:

socket_address(uint32_t, uint16_t p = 0) noexcept;

/// The "any address" of a family: 0.0.0.0:port or [::]:port. Unlike the
/// port-only constructor, which is IPv4, the family is explicit.
static socket_address wildcard(sa_family_t family, uint16_t port = 0) noexcept;

socklen_t length() const noexcept { return addr_length; };

bool is_af_unix() const noexcept {
Expand All @@ -91,6 +95,9 @@ public:
net::inet_address addr() const noexcept;
::in_port_t port() const noexcept;
bool is_wildcard() const noexcept;
/// The AF_INET form of an IPv4-mapped IPv6 address, same port; any other
/// address unchanged. See net::inet_address::unmapped().
socket_address unmapped() const noexcept;

bool operator==(const socket_address&) const noexcept;
bool operator!=(const socket_address& a) const noexcept {
Expand All @@ -117,7 +124,8 @@ struct ipv4_addr {
ipv4_addr(const std::string &addr, uint16_t port);
// throws if not an ipv4 addr
ipv4_addr(const net::inet_address&, uint16_t);
ipv4_addr(const socket_address &) noexcept;
// throws if the address is IPv6 and not IPv4-mapped
ipv4_addr(const socket_address &);
ipv4_addr(const ::in_addr&, uint16_t = 0) noexcept;

bool is_ip_unspecified() const noexcept {
Expand All @@ -136,7 +144,8 @@ struct ipv6_addr {

ipv6_addr(const ipv6_bytes&, uint16_t port = 0) noexcept;
ipv6_addr(uint16_t port = 0) noexcept;
// throws if not a valid ipv6 addr
// "addr" or "[addr]:port". A zoned literal (fe80::1%eth0) has no
// representation here: use net::inet_address.
ipv6_addr(const std::string&);
ipv6_addr(const std::string&, uint16_t port);
ipv6_addr(const net::inet_address&, uint16_t = 0) noexcept;
Expand All @@ -156,6 +165,10 @@ std::ostream& operator<<(std::ostream&, const ipv6_addr&);
inline bool operator==(const ipv4_addr &lhs, const ipv4_addr& rhs) noexcept {
return lhs.ip == rhs.ip && lhs.port == rhs.port;
}

inline bool operator==(const ipv6_addr &lhs, const ipv6_addr& rhs) noexcept {
return lhs.ip == rhs.ip && lhs.port == rhs.port;
}
}

namespace std {
Expand All @@ -168,6 +181,10 @@ struct hash<seastar::ipv4_addr> {
size_t operator()(const seastar::ipv4_addr&) const;
};
template<>
struct hash<seastar::ipv6_addr> {
size_t operator()(const seastar::ipv6_addr&) const;
};
template<>
struct hash<seastar::unix_domain_addr> {
size_t operator()(const seastar::unix_domain_addr&) const;
};
Expand Down
12 changes: 11 additions & 1 deletion include/seastar/net/tls.hh
Original file line number Diff line number Diff line change
Expand Up @@ -445,13 +445,23 @@ namespace tls {
public:
/// \brief whether to wait for EOF from server on session termination
deprecated_wait_for_eof_on_shutdown wait_for_eof_on_shutdown;
/// \brief server name to be used for the SNI TLS extension
/// \brief the server being connected to: a DNS name, or an IP literal
/// (brackets allowed) which is not sent as SNI (RFC 6066 §3). Also the
/// name verification checks, see verify_server_name.
sstring server_name = {};

/// \brief whether server certificate should be verified. May be set to false
/// in test environments.
bool verify_certificate = true;

/// \brief whether the peer certificate must be issued for server_name
/// (a DNS SAN for names, an IP SAN for literals) as well as chaining to
/// a trusted CA. GnuTLS always checks this when server_name is set;
/// OpenSSL only when this is true. Off by default, so clients
/// connecting by address to certificates without an IP SAN keep
/// working until they opt in.
bool verify_server_name = false;

/// \brief Optional session resume data. Must be retrieved via
/// get_session_resume_data below.
session_data session_resume_data;
Expand Down
8 changes: 4 additions & 4 deletions src/core/reactor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,10 @@ pollable_fd posix_listen(socket_address sa, listen_options opts) {
fd.setsockopt(SOL_SOCKET, SO_RCVBUF, *opts.so_rcvbuf);
}

if (opts.ipv6_only && sa.u.sa.sa_family == AF_INET6) {
fd.setsockopt(IPPROTO_IPV6, IPV6_V6ONLY, int(*opts.ipv6_only));
}

try {
fd.bind(sa.u.sa, sa.length());

Expand Down Expand Up @@ -3935,10 +3939,6 @@ void schedule_urgent(task* t) noexcept {

}

bool operator==(const ::sockaddr_in a, const ::sockaddr_in b) {
return (a.sin_addr.s_addr == b.sin_addr.s_addr) && (a.sin_port == b.sin_port);
}

namespace seastar {

static bool kernel_supports_aio_fsync() {
Expand Down
19 changes: 19 additions & 0 deletions src/http/request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <utility>

#include <seastar/http/request.hh>
#include <seastar/net/inet_address.hh>
#include <seastar/http/url.hh>
#include <seastar/http/common.hh>
#include <seastar/util/assert.hh>
Expand Down Expand Up @@ -168,5 +169,23 @@ request request::make(httpd::operation_type type, sstring host, sstring path) {
return make(httpd::type2str(type), std::move(host), std::move(path));
}

request request::make(sstring method, const socket_address& addr, sstring path) {
return make(std::move(method), internal::format_authority(addr), std::move(path));
}

request request::make(httpd::operation_type type, const socket_address& addr, sstring path) {
return make(httpd::type2str(type), internal::format_authority(addr), std::move(path));
}

sstring internal::format_authority(const socket_address& addr) {
auto ip = addr.addr();
if (ip.is_ipv6()) {
// inet_address prints a scope as "%<index>", which an authority cannot
// carry; build the address without one.
return format("[{}]:{:d}", net::inet_address(static_cast<::in6_addr>(ip)), addr.port());
}
return format("{}:{:d}", ip, addr.port());
}

} // http namespace
} // seastar namespace
Loading
Loading