mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 08:12:37 +01:00
ircd: Add preliminary 'server' as a client to *other* servers.
This commit is contained in:
parent
52641ba47f
commit
6a024e9e16
4 changed files with 343 additions and 0 deletions
118
include/ircd/server.h
Normal file
118
include/ircd/server.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Charybdis Development Team
|
||||
* Copyright (C) 2017 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_SERVER_H
|
||||
|
||||
namespace ircd
|
||||
{
|
||||
struct server;
|
||||
|
||||
size_t write(server &, const ilist<const_buffer> &iov);
|
||||
char *read(server &, char *&start, char *const &stop);
|
||||
|
||||
http::request::write_closure write_closure(server &);
|
||||
parse::read_closure read_closure(server &);
|
||||
}
|
||||
|
||||
/// The interface for when IRCd plays the role of client to other servers
|
||||
///
|
||||
/// This is a handle for being a client to another server. This class is
|
||||
/// named ircd::server and not ircd::client because this project is IRCd
|
||||
/// and not IRCc. This handle will attempt to find an existing connection
|
||||
/// pool for the remote server and then multiplex your requests and demultiplex
|
||||
/// your responses to achieve concurrency and sharing and limitations and
|
||||
/// shape the pipeline as best as the pool allows along with other instances
|
||||
/// of ircd::server for the same remote.
|
||||
///
|
||||
/// Note that this means ircd::server is only appropriate for stateless
|
||||
/// protocols like HTTP and chunked-encoding should be avoided if we are
|
||||
/// to get the best out of nagle'ing the pipe. Individual net::socket should
|
||||
/// be used otherwise.
|
||||
///
|
||||
/// This handle is a "tag" which services a single request and response per
|
||||
/// instance to an ircd::server::node over one ircd::server::link available
|
||||
/// to that node. Those interfaces are internal and don't have to be messed
|
||||
/// with.
|
||||
///
|
||||
/// Instances of this class can be used in arrays to make bulk requests.
|
||||
///
|
||||
struct ircd::server
|
||||
{
|
||||
struct init;
|
||||
struct node;
|
||||
struct link;
|
||||
|
||||
static std::map<net::ipport, std::shared_ptr<node>> nodes;
|
||||
|
||||
std::shared_ptr<node> n;
|
||||
unique_iterator<std::list<server *>> it;
|
||||
|
||||
public:
|
||||
operator const net::remote &() const;
|
||||
|
||||
server() = default;
|
||||
server(server &&) noexcept = default;
|
||||
server &operator=(server &&) noexcept = default;
|
||||
server(net::remote);
|
||||
~server() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::server::link
|
||||
{
|
||||
enum state :int;
|
||||
|
||||
std::shared_ptr<net::socket> s;
|
||||
std::deque<server *> q;
|
||||
enum state state;
|
||||
|
||||
link(const net::remote &remote);
|
||||
};
|
||||
|
||||
enum ircd::server::link::state
|
||||
:int
|
||||
{
|
||||
DEAD,
|
||||
IDLE,
|
||||
BUSY,
|
||||
};
|
||||
|
||||
struct ircd::server::node
|
||||
:std::enable_shared_from_this<ircd::server::node>
|
||||
{
|
||||
enum state :int;
|
||||
|
||||
net::remote remote;
|
||||
std::list<server *> tags;
|
||||
std::list<link> links;
|
||||
|
||||
void add(const size_t &num = 1);
|
||||
void del(const size_t &num = 1);
|
||||
|
||||
node(net::remote remote);
|
||||
~node() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::server::init
|
||||
{
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
|
@ -175,6 +175,7 @@ namespace ircd
|
|||
constexpr size_t BUFSIZE { 512 };
|
||||
|
||||
struct client;
|
||||
struct server;
|
||||
|
||||
std::string demangle(const std::string &symbol);
|
||||
template<class T> std::string demangle();
|
||||
|
@ -216,6 +217,7 @@ namespace ircd
|
|||
#include "net/net.h"
|
||||
#include "m/m.h"
|
||||
#include "resource.h"
|
||||
#include "server.h"
|
||||
#include "client.h"
|
||||
|
||||
template<class T>
|
||||
|
|
|
@ -80,6 +80,7 @@ libircd_la_SOURCES = \
|
|||
parse.cc \
|
||||
resource.cc \
|
||||
rfc1459.cc \
|
||||
server.cc \
|
||||
sodium.cc \
|
||||
###
|
||||
|
||||
|
|
222
ircd/server.cc
Normal file
222
ircd/server.cc
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Charybdis Development Team
|
||||
* Copyright (C) 2017 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ircd/server.h>
|
||||
#include <ircd/asio.h>
|
||||
|
||||
//
|
||||
// init
|
||||
//
|
||||
|
||||
ircd::server::init::init()
|
||||
{
|
||||
}
|
||||
|
||||
ircd::server::init::~init()
|
||||
noexcept
|
||||
{
|
||||
ircd::server::nodes.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// server
|
||||
//
|
||||
|
||||
ircd::http::request::write_closure
|
||||
ircd::write_closure(server &server)
|
||||
{
|
||||
// returns a function that can be called to send an iovector of data to a server
|
||||
return [&server](const ilist<const_buffer> &iov)
|
||||
{
|
||||
//std::cout << "<<<<" << std::endl;
|
||||
//std::cout << iov << std::endl;
|
||||
//std::cout << "----" << std::endl;
|
||||
write(server, iov);
|
||||
};
|
||||
}
|
||||
|
||||
ircd::parse::read_closure
|
||||
ircd::read_closure(server &server)
|
||||
{
|
||||
// Returns a function the parser can call when it wants more data
|
||||
return [&server](char *&start, char *const &stop)
|
||||
{
|
||||
char *const s(start);
|
||||
read(server, start, stop);
|
||||
//std::cout << ">>>>" << std::endl;
|
||||
//std::cout << string_view{s, start} << std::endl;
|
||||
//std::cout << "----" << std::endl;
|
||||
};
|
||||
}
|
||||
|
||||
char *
|
||||
ircd::read(server &server,
|
||||
char *&start,
|
||||
char *const &stop)
|
||||
try
|
||||
{
|
||||
auto &sock
|
||||
{
|
||||
*(*begin(server.n->links)).s
|
||||
};
|
||||
|
||||
const std::array<mutable_buffer, 1> bufs
|
||||
{{
|
||||
{ start, stop }
|
||||
}};
|
||||
|
||||
char *const base(start);
|
||||
start += sock.read_some(bufs);
|
||||
return base;
|
||||
}
|
||||
catch(const boost::system::system_error &e)
|
||||
{
|
||||
using namespace boost::system::errc;
|
||||
|
||||
log::error("read error: %s: %s",
|
||||
string(server.n->remote),
|
||||
e.what());
|
||||
|
||||
switch(e.code().value())
|
||||
{
|
||||
case operation_canceled:
|
||||
throw http::error(http::REQUEST_TIMEOUT);
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::write(server &server,
|
||||
const ilist<const_buffer> &iov)
|
||||
try
|
||||
{
|
||||
auto &sock
|
||||
{
|
||||
*(*begin(server.n->links)).s
|
||||
};
|
||||
|
||||
return sock.write(iov);
|
||||
}
|
||||
catch(const boost::system::system_error &e)
|
||||
{
|
||||
using namespace boost::system::errc;
|
||||
|
||||
log::error("write error: %s: %s",
|
||||
string(server.n->remote),
|
||||
e.what());
|
||||
|
||||
switch(e.code().value())
|
||||
{
|
||||
case operation_canceled:
|
||||
throw http::error(http::REQUEST_TIMEOUT);
|
||||
|
||||
default:
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// server
|
||||
//
|
||||
|
||||
ircd::server::server(net::remote remote)
|
||||
:n{[&remote]
|
||||
{
|
||||
const auto &ipp
|
||||
{
|
||||
static_cast<const net::ipport &>(remote)
|
||||
};
|
||||
|
||||
const auto it(nodes.lower_bound(ipp));
|
||||
if(it == nodes.end() || it->first != ipp)
|
||||
{
|
||||
const auto ipp{static_cast<net::ipport>(remote)};
|
||||
const auto n{std::make_shared<node>(std::move(remote))};
|
||||
nodes.emplace_hint(it, ipp, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}()}
|
||||
,it
|
||||
{
|
||||
n->tags, n->tags.emplace(n->tags.end(), this)
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::server::~server()
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
ircd::server::operator
|
||||
const ircd::net::remote &()
|
||||
const
|
||||
{
|
||||
static const ircd::net::remote null_remote {};
|
||||
if(unlikely(!n))
|
||||
return null_remote;
|
||||
|
||||
return n->remote;
|
||||
}
|
||||
|
||||
decltype(ircd::server::nodes)
|
||||
ircd::server::nodes
|
||||
{};
|
||||
|
||||
//
|
||||
// node
|
||||
//
|
||||
|
||||
ircd::server::node::node(net::remote remote)
|
||||
:remote{std::move(remote)}
|
||||
{
|
||||
add(1);
|
||||
}
|
||||
|
||||
ircd::server::node::~node()
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ircd::server::node::add(const size_t &num)
|
||||
{
|
||||
links.emplace_back(remote);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::server::node::del(const size_t &num)
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// link
|
||||
//
|
||||
|
||||
ircd::server::link::link(const net::remote &remote)
|
||||
:s{std::make_shared<net::socket>(remote)}
|
||||
,state{state::DEAD}
|
||||
{
|
||||
}
|
Loading…
Reference in a new issue