2018-02-04 03:22:01 +01:00
|
|
|
// Matrix Construct
|
|
|
|
//
|
2018-01-14 02:55:21 +01:00
|
|
|
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
2018-02-04 03:22:01 +01:00
|
|
|
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
2018-01-14 02:55:21 +01:00
|
|
|
//
|
|
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
// purpose with or without fee is hereby granted, provided that the above
|
2018-02-04 03:22:01 +01:00
|
|
|
// copyright notice and this permission notice is present in all copies. The
|
|
|
|
// full license for this software is available in the LICENSE file.
|
2007-01-25 07:40:21 +01:00
|
|
|
|
2016-08-13 05:05:54 +02:00
|
|
|
#pragma once
|
|
|
|
#define HAVE_IRCD_CLIENT_H
|
2016-08-24 00:25:09 +02:00
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
namespace ircd
|
|
|
|
{
|
|
|
|
struct client;
|
|
|
|
|
2019-02-16 01:47:00 +01:00
|
|
|
const ipport &remote(const client &);
|
|
|
|
const ipport &local(const client &);
|
2023-02-09 19:12:11 +01:00
|
|
|
|
|
|
|
string_view loghead(const mutable_buffer &buf, const client &);
|
|
|
|
string_view loghead(const client &);
|
2017-08-28 23:51:22 +02:00
|
|
|
}
|
2016-09-12 23:07:46 +02:00
|
|
|
|
2018-05-21 12:01:40 +02:00
|
|
|
/// Remote party connecting to our daemon to make requests.
|
2017-08-28 23:51:22 +02:00
|
|
|
struct ircd::client
|
2017-08-23 22:33:31 +02:00
|
|
|
:std::enable_shared_from_this<client>
|
2018-09-30 01:51:11 +02:00
|
|
|
,ircd::instance_multimap<net::ipport, client, net::ipport::cmp_ip>
|
2016-09-12 23:07:46 +02:00
|
|
|
{
|
2016-11-29 16:23:38 +01:00
|
|
|
struct init;
|
2018-01-14 02:55:21 +01:00
|
|
|
struct conf;
|
|
|
|
struct settings;
|
|
|
|
struct request;
|
2017-09-30 08:04:41 +02:00
|
|
|
|
2018-10-24 21:39:48 +02:00
|
|
|
static log::log log;
|
2018-01-14 02:55:21 +01:00
|
|
|
static struct settings settings;
|
|
|
|
static struct conf default_conf;
|
2018-12-28 21:57:32 +01:00
|
|
|
static ctx::pool::opts pool_opts;
|
2018-09-02 00:08:48 +02:00
|
|
|
static ctx::pool pool;
|
2018-12-28 21:57:32 +01:00
|
|
|
static ctx::dock dock;
|
2018-04-15 01:21:52 +02:00
|
|
|
static uint64_t ctr; // monotonic
|
2016-09-23 08:59:24 +02:00
|
|
|
|
2018-01-14 02:55:21 +01:00
|
|
|
struct conf *conf {&default_conf};
|
2018-02-17 23:28:06 +01:00
|
|
|
unique_buffer<mutable_buffer> head_buffer;
|
2018-02-18 00:44:53 +01:00
|
|
|
unique_buffer<mutable_buffer> content_buffer;
|
2018-02-12 20:58:40 +01:00
|
|
|
std::shared_ptr<socket> sock;
|
2018-09-30 01:51:11 +02:00
|
|
|
net::ipport local;
|
2018-04-15 01:21:52 +02:00
|
|
|
uint64_t id {++ctr};
|
2018-11-07 06:34:28 +01:00
|
|
|
uint64_t ready_count {0};
|
|
|
|
uint64_t request_count {0};
|
2018-04-14 02:03:17 +02:00
|
|
|
ctx::ctx *reqctx {nullptr};
|
2018-02-12 20:58:40 +01:00
|
|
|
ircd::timer timer;
|
|
|
|
size_t head_length {0};
|
|
|
|
size_t content_consumed {0};
|
2018-02-18 00:44:53 +01:00
|
|
|
resource::request request;
|
2018-01-14 02:55:21 +01:00
|
|
|
|
2020-12-25 16:11:25 +01:00
|
|
|
size_t write_all(const net::const_buffers &);
|
2018-03-11 18:48:58 +01:00
|
|
|
size_t write_all(const const_buffer &);
|
2018-01-14 02:55:21 +01:00
|
|
|
void close(const net::close_opts &, net::close_callback);
|
|
|
|
ctx::future<void> close(const net::close_opts & = {});
|
2016-09-23 08:59:24 +02:00
|
|
|
|
2022-06-14 20:21:51 +02:00
|
|
|
private:
|
2018-02-18 00:44:53 +01:00
|
|
|
void discard_unconsumed(const http::request::head &);
|
|
|
|
bool resource_request(const http::request::head &);
|
2018-01-14 02:55:21 +01:00
|
|
|
bool handle_request(parse::capstan &pc);
|
2018-08-20 03:09:43 +02:00
|
|
|
bool main();
|
2022-06-14 20:21:51 +02:00
|
|
|
|
|
|
|
static char *read(client &, char *&start, char *const &stop); //TODO: XXX
|
|
|
|
static parse::read_closure read_closure(client &); //TODO: XXX
|
|
|
|
static void handle_requests(std::shared_ptr<client>);
|
|
|
|
static void handle_ready(std::shared_ptr<client>, const error_code &ec);
|
2018-03-15 21:44:29 +01:00
|
|
|
bool async();
|
2016-09-23 08:59:24 +02:00
|
|
|
|
2022-06-14 20:21:51 +02:00
|
|
|
public:
|
2017-03-14 00:11:30 +01:00
|
|
|
client(std::shared_ptr<socket>);
|
2016-11-29 16:23:38 +01:00
|
|
|
client(client &&) = delete;
|
|
|
|
client(const client &) = delete;
|
|
|
|
client &operator=(client &&) = delete;
|
|
|
|
client &operator=(const client &) = delete;
|
2018-01-27 06:58:52 +01:00
|
|
|
~client() noexcept;
|
2017-08-28 23:51:22 +02:00
|
|
|
|
2022-06-14 20:21:51 +02:00
|
|
|
static void create(net::listener &, const std::shared_ptr<socket> &);
|
|
|
|
static size_t count(const net::ipport &remote); // cmp is by IP only, not port
|
|
|
|
static void terminate_all();
|
|
|
|
static void interrupt_all();
|
|
|
|
static void close_all();
|
|
|
|
static void wait_all();
|
|
|
|
static void spawn();
|
|
|
|
|
2018-09-30 01:51:11 +02:00
|
|
|
friend const ipport &remote(const client &);
|
|
|
|
friend const ipport &local(const client &);
|
2016-09-23 08:59:24 +02:00
|
|
|
};
|
|
|
|
|
2023-02-03 08:33:32 +01:00
|
|
|
template<>
|
|
|
|
decltype(ircd::client::map)
|
|
|
|
ircd::instance_multimap<ircd::net::ipport, ircd::client, ircd::net::ipport::cmp_ip>::map;
|
|
|
|
|
2018-01-14 02:55:21 +01:00
|
|
|
/// Confs can be attached to individual clients to change their behavior
|
|
|
|
struct ircd::client::conf
|
|
|
|
{
|
2022-06-14 20:21:51 +02:00
|
|
|
template<class T> using item = ircd::conf::item<T>;
|
|
|
|
|
|
|
|
static item<seconds> async_timeout_default;
|
|
|
|
static item<seconds> request_timeout_default;
|
|
|
|
static item<size_t> header_max_size_default;
|
2018-04-20 01:35:59 +02:00
|
|
|
|
2018-01-14 02:55:21 +01:00
|
|
|
/// Default time limit for how long a client connection can be in "async mode"
|
|
|
|
/// (or idle mode) after which it is disconnected.
|
2018-04-20 01:35:59 +02:00
|
|
|
seconds async_timeout {async_timeout_default};
|
2018-01-14 02:55:21 +01:00
|
|
|
|
2018-04-16 01:42:13 +02:00
|
|
|
/// Time limit for how long a connected client can be sending its request.
|
|
|
|
/// This is meaningful before the resource being sought is known (while
|
|
|
|
/// receiving headers), after which its own specific timeout specified by
|
|
|
|
/// its options takes over.
|
2018-04-20 01:35:59 +02:00
|
|
|
seconds request_timeout {request_timeout_default};
|
|
|
|
|
|
|
|
/// Number of bytes allocated to receive HTTP request headers for client.
|
|
|
|
size_t header_max_size {header_max_size_default};
|
2018-01-14 02:55:21 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Settings apply to all clients and cannot be configured per-client
|
|
|
|
struct ircd::client::settings
|
|
|
|
{
|
2022-06-14 20:21:51 +02:00
|
|
|
template<class T> using item = ircd::conf::item<T>;
|
|
|
|
|
|
|
|
static item<size_t> stack_size;
|
|
|
|
static item<size_t> pool_size;
|
|
|
|
static item<size_t> max_client;
|
|
|
|
static item<size_t> max_client_per_peer;
|
2018-01-14 02:55:21 +01:00
|
|
|
};
|
|
|
|
|
2022-05-26 21:28:28 +02:00
|
|
|
struct [[gnu::visibility("hidden")]]
|
|
|
|
ircd::client::init
|
2016-08-28 10:16:24 +02:00
|
|
|
{
|
2016-11-29 16:23:38 +01:00
|
|
|
init();
|
|
|
|
~init() noexcept;
|
|
|
|
};
|
2020-12-25 16:11:25 +01:00
|
|
|
|
|
|
|
inline size_t
|
|
|
|
ircd::client::write_all(const const_buffer &buf)
|
|
|
|
{
|
|
|
|
const const_buffer bufs[]
|
|
|
|
{
|
|
|
|
buf
|
|
|
|
};
|
|
|
|
|
|
|
|
return write_all(bufs);
|
|
|
|
}
|