2018-02-04 03:22:01 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
2016-11-29 16:23:38 +01:00
|
|
|
|
|
|
|
#pragma once
|
2017-09-30 08:04:41 +02:00
|
|
|
#define HAVE_IRCD_NET_SOCKET_H
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-10-19 12:55:24 +02:00
|
|
|
// This file is not included with the IRCd standard include stack because
|
|
|
|
// it requires symbols we can't forward declare without boost headers. It
|
|
|
|
// is part of the <ircd/asio.h> stack which can be included in your
|
2018-01-06 02:01:37 +01:00
|
|
|
// definition file if you need low level access to this socket API.
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-09-30 08:04:41 +02:00
|
|
|
namespace ircd::net
|
2017-08-28 23:51:22 +02:00
|
|
|
{
|
2019-04-16 04:54:31 +02:00
|
|
|
extern conf::item<std::string> ssl_curve_list;
|
|
|
|
extern conf::item<std::string> ssl_cipher_list;
|
|
|
|
extern conf::item<std::string> ssl_cipher_blacklist;
|
2018-01-05 08:14:21 +01:00
|
|
|
extern asio::ssl::context sslv23_client;
|
2017-09-30 08:04:41 +02:00
|
|
|
}
|
2017-03-13 22:07:58 +01:00
|
|
|
|
2018-01-22 09:31:53 +01:00
|
|
|
/// Internal socket interface
|
|
|
|
///
|
2017-09-30 08:04:41 +02:00
|
|
|
struct ircd::net::socket
|
|
|
|
:std::enable_shared_from_this<ircd::net::socket>
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
2017-10-19 12:55:24 +02:00
|
|
|
struct io;
|
2016-11-29 16:23:38 +01:00
|
|
|
struct stat;
|
2018-01-01 10:42:00 +01:00
|
|
|
struct xfer;
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2018-01-01 10:42:00 +01:00
|
|
|
using endpoint = ip::tcp::endpoint;
|
|
|
|
using wait_type = ip::tcp::socket::wait_type;
|
|
|
|
using message_flags = asio::socket_base::message_flags;
|
|
|
|
using handshake_type = asio::ssl::stream<ip::tcp::socket>::handshake_type;
|
2018-01-08 12:03:50 +01:00
|
|
|
using ec_handler = std::function<void (const error_code &)>;
|
|
|
|
using eptr_handler = std::function<void (std::exception_ptr)>;
|
2018-01-01 10:42:00 +01:00
|
|
|
|
2016-11-29 16:23:38 +01:00
|
|
|
struct stat
|
|
|
|
{
|
|
|
|
size_t bytes {0};
|
|
|
|
size_t calls {0};
|
|
|
|
};
|
|
|
|
|
2018-03-13 02:45:21 +01:00
|
|
|
static uint64_t count; // monotonic
|
|
|
|
static uint64_t instances; // current socket count
|
2020-06-17 07:33:13 +02:00
|
|
|
static stats::item<uint64_t> total_bytes_in;
|
|
|
|
static stats::item<uint64_t> total_bytes_out;
|
|
|
|
static stats::item<uint64_t> total_calls_in;
|
|
|
|
static stats::item<uint64_t> total_calls_out;
|
2020-10-03 09:39:27 +02:00
|
|
|
static ios::descriptor desc_connect;
|
|
|
|
static ios::descriptor desc_handshake;
|
|
|
|
static ios::descriptor desc_disconnect;
|
|
|
|
static ios::descriptor desc_timeout;
|
|
|
|
static ios::descriptor desc_wait[4];
|
2018-03-13 02:45:21 +01:00
|
|
|
|
2018-09-30 02:15:45 +02:00
|
|
|
uint64_t id {++count};
|
2017-10-25 18:37:37 +02:00
|
|
|
ip::tcp::socket sd;
|
|
|
|
asio::ssl::stream<ip::tcp::socket &> ssl;
|
2016-11-29 16:23:38 +01:00
|
|
|
stat in, out;
|
2019-10-09 03:14:10 +02:00
|
|
|
deadline_timer timer;
|
2018-04-16 00:55:25 +02:00
|
|
|
uint64_t timer_sem[2] {0}; // handler, sender
|
2020-05-31 08:08:09 +02:00
|
|
|
char alpn[12] {0};
|
2018-04-16 00:55:25 +02:00
|
|
|
bool timer_set {false}; // boolean lockout
|
2017-11-01 23:51:24 +01:00
|
|
|
bool timedout {false};
|
2018-03-10 00:55:15 +01:00
|
|
|
bool fini {false};
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2018-01-07 06:34:02 +01:00
|
|
|
void call_user(const eptr_handler &, const error_code &) noexcept;
|
|
|
|
void call_user(const ec_handler &, const error_code &) noexcept;
|
|
|
|
bool handle_verify(bool, asio::ssl::verify_context &, const open_opts &) noexcept;
|
2018-01-16 04:46:23 +01:00
|
|
|
void handle_disconnect(std::shared_ptr<socket>, eptr_handler, error_code) noexcept;
|
2018-01-20 12:14:14 +01:00
|
|
|
void handle_handshake(std::weak_ptr<socket>, eptr_handler, error_code) noexcept;
|
2019-04-17 06:27:01 +02:00
|
|
|
void handle_connect(std::weak_ptr<socket>, const open_opts &, eptr_handler, error_code) noexcept;
|
2018-01-20 12:14:14 +01:00
|
|
|
void handle_timeout(std::weak_ptr<socket>, ec_handler, error_code) noexcept;
|
2019-09-13 21:30:05 +02:00
|
|
|
void handle_ready(std::weak_ptr<socket>, ready, ec_handler, error_code) noexcept;
|
2016-11-29 16:23:38 +01:00
|
|
|
|
|
|
|
public:
|
|
|
|
operator const ip::tcp::socket &() const { return sd; }
|
|
|
|
operator ip::tcp::socket &() { return sd; }
|
2017-11-16 02:27:36 +01:00
|
|
|
operator const SSL &() const;
|
|
|
|
operator SSL &();
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2018-01-01 10:42:00 +01:00
|
|
|
endpoint remote() const; // getpeername(); throws if not conn
|
|
|
|
endpoint local() const; // getsockname(); throws if not conn/bound
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-10-19 12:55:24 +02:00
|
|
|
// Timer for this socket
|
2018-01-07 06:34:02 +01:00
|
|
|
void set_timeout(const milliseconds &, ec_handler);
|
2017-09-12 18:28:41 +02:00
|
|
|
void set_timeout(const milliseconds &);
|
2018-01-04 23:20:30 +01:00
|
|
|
milliseconds cancel_timeout() noexcept;
|
2017-09-12 18:28:41 +02:00
|
|
|
|
2018-01-07 06:34:02 +01:00
|
|
|
// low level write suite
|
2018-01-08 12:04:15 +01:00
|
|
|
template<class iov> size_t write_one(iov&&); // non-blocking
|
|
|
|
template<class iov> size_t write_any(iov&&); // non-blocking
|
2018-01-14 10:46:50 +01:00
|
|
|
template<class iov> size_t write_few(iov&&); // yielding
|
2018-01-08 12:04:15 +01:00
|
|
|
template<class iov> size_t write_all(iov&&); // yielding
|
2018-01-07 06:34:02 +01:00
|
|
|
|
|
|
|
// low level read suite
|
2018-01-08 12:04:15 +01:00
|
|
|
template<class iov> size_t read_one(iov&&); // non-blocking
|
2018-01-14 10:46:50 +01:00
|
|
|
template<class iov> size_t read_any(iov&&); // non-blocking
|
|
|
|
template<class iov> size_t read_few(iov&&); // yielding
|
2018-01-08 12:04:15 +01:00
|
|
|
template<class iov> size_t read_all(iov&&); // yielding
|
2018-01-07 06:34:02 +01:00
|
|
|
|
2019-03-12 22:27:42 +01:00
|
|
|
// low level check suite
|
|
|
|
error_code check(std::nothrow_t, const ready &) noexcept;
|
|
|
|
|
2018-01-08 22:25:13 +01:00
|
|
|
// low level wait suite
|
|
|
|
void wait(const wait_opts &);
|
|
|
|
void wait(const wait_opts &, wait_callback_ec);
|
|
|
|
void wait(const wait_opts &, wait_callback_eptr);
|
2019-09-14 20:41:44 +02:00
|
|
|
template<class... args> auto operator()(args&&...); // Alias to wait()
|
2018-01-08 22:25:13 +01:00
|
|
|
|
2018-01-07 06:34:02 +01:00
|
|
|
void disconnect(const close_opts &, eptr_handler);
|
|
|
|
void handshake(const open_opts &, eptr_handler);
|
|
|
|
void connect(const endpoint &, const open_opts &, eptr_handler);
|
2019-09-14 20:41:44 +02:00
|
|
|
bool cancel() noexcept;
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2020-02-27 19:11:59 +01:00
|
|
|
socket(asio::ssl::context & = sslv23_client);
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-10-19 12:55:24 +02:00
|
|
|
// Socket cannot be copied or moved; must be constructed as shared ptr
|
2017-08-23 22:47:15 +02:00
|
|
|
socket(socket &&) = delete;
|
|
|
|
socket(const socket &) = delete;
|
2018-04-12 21:52:14 +02:00
|
|
|
socket &operator=(socket &&) = delete;
|
|
|
|
socket &operator=(const socket &) = delete;
|
2016-11-29 16:23:38 +01:00
|
|
|
~socket() noexcept;
|
|
|
|
};
|
|
|
|
|
2018-01-08 22:25:13 +01:00
|
|
|
template<class... args>
|
|
|
|
auto
|
|
|
|
ircd::net::socket::operator()(args&&... a)
|
|
|
|
{
|
|
|
|
return this->wait(std::forward<args>(a)...);
|
|
|
|
}
|