0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-01-13 08:23:56 +01:00

ircd: new client; start over.

This commit is contained in:
Jason Volk 2016-09-10 12:57:33 -07:00
parent 5b55e60015
commit 556ceba8a0
12 changed files with 140 additions and 2380 deletions

View file

@ -75,6 +75,11 @@ boost::asio::signal_set sigs
*ios
};
// TODO: XXX: This has to be declared first before any modules
// are loaded otherwise the module will not be unloadable.
boost::asio::ip::tcp::acceptor _dummy_acceptor_ { *ios };
boost::asio::ip::tcp::socket _dummy_sock_ { *ios };
int main(int argc, char *const *argv)
try
{
@ -395,5 +400,8 @@ handle_line(const std::string &line)
if(line == "EXIT")
exit(0);
ircd::execute(ircd::me, line);
if(unlikely(!ircd::me))
throw ircd::error("IRCd `me' not available to execute on");
ircd::execute(*ircd::me, line);
}

View file

@ -27,305 +27,35 @@
#pragma once
#define HAVE_IRCD_CLIENT_H
#include "client_user.h"
#include "client_serv.h"
#include "client_mode.h"
#ifdef __cplusplus
namespace ircd {
namespace client {
enum class status : uint8_t
enum class state
{
CONNECTING = 0x01,
HANDSHAKE = 0x02,
ME = 0x04,
UNKNOWN = 0x08,
REJECT = 0x10,
SERVER = 0x20,
CLIENT = 0x40,
CONNECTING,
};
enum flags
{
PINGSENT = 0x00000001, // Unreplied ping sent
DEAD = 0x00000002, // Local socket is dead--Exiting soon
KILLED = 0x00000004, // Prevents "QUIT" from being sent for this
SENTUSER = 0x00000008, // Client sent a USER command.
CLICAP = 0x00000010, // In CAP negotiation, wait for CAP END
CLOSING = 0x00000020, // set when closing to suppress errors
PING_COOKIE = 0x00000040, // has sent ping cookie
GOTID = 0x00000080, // successful ident lookup achieved
FLOODDONE = 0x00000100, // flood grace period over / reported
NORMALEX = 0x00000200, // Client exited normally
MARK = 0x00000400, // marked client
HIDDEN = 0x00000800, // hidden server
EOB = 0x00001000, // EOB
MYCONNECT = 0x00002000, // MyConnect
IOERROR = 0x00004000, // IO error
SERVICE = 0x00008000, // network service
TGCHANGE = 0x00010000, // we're allowed to clear something
DYNSPOOF = 0x00020000, // dynamic spoof, only opers see ip
TGEXCESSIVE = 0x00040000, // whether the client has attemped to change targets excessively fast
CLICAP_DATA = 0x00080000, // requested CAP LS 302
EXTENDCHANS = 0x00100000,
EXEMPTRESV = 0x00200000,
EXEMPTKLINE = 0x00400000,
EXEMPTFLOOD = 0x00800000,
IP_SPOOFING = 0x01000000,
EXEMPTSPAMBOT = 0x02000000,
EXEMPTSHIDE = 0x04000000,
EXEMPTJUPE = 0x08000000,
};
// we store ipv6 ips for remote clients, so this needs to be v6 always
constexpr auto PASSWDLEN = 128;
constexpr auto CIPHERKEYLEN = 64; // 512bit
constexpr auto CLIENT_BUFSIZE = 512; // must be at least 512 bytes
constexpr auto IDLEN = 10;
};
struct client
{
rb_dlink_node node;
serv::list::iterator lnode;
std::shared_ptr<user::user> user; // ...defined, if this is a user
std::shared_ptr<serv::serv> serv; // ...defined, if this is a server
struct client *servptr; /* Points to server this Client is on */
struct client *from; /* == self, if Local Client, *NEVER* NULL! */
std::unique_ptr<struct sock> sock;
// unique whowas id associating any history to *this (TODO: replace with connid)
whowas::id_t wwid;
time_t tsinfo; /* TS on the nick, SVINFO on server */
mode::mask mode;
uint64_t flags; /* client flags */
unsigned int snomask; /* server notice mask */
int hopcount; /* number of servers to this 0 = local */
enum status status; // Client type
unsigned char handler; /* Handler index */
unsigned long serial; /* used to enforce 1 send per nick */
/* client->name is the unique name for a client nick or host */
char name[HOSTLEN + 1];
/*
* client->username is the username from ident or the USER message,
* If the client is idented the USER message is ignored, otherwise
* the username part of the USER message is put here prefixed with a
* tilde depending on the I:line, Once a client has registered, this
* field should be considered read-only.
*/
char username[USERLEN + 1]; /* client's username */
/*
* client->host contains the resolved name or ip address
* as a string for the user, it may be fiddled with for oper spoofing etc.
*/
char host[HOSTLEN + 1]; /* client's hostname */
char orighost[HOSTLEN + 1]; /* original hostname (before dynamic spoofing) */
char sockhost[HOSTIPLEN + 1]; /* clients ip */
char info[REALLEN + 1]; /* Free form additional client info */
char id[IDLEN]; /* UID/SID, unique on the network */
/* list of who has this client on their allow list, its counterpart
* is in LocalUser
*/
rb_dlink_list on_allow_list;
time_t first_received_message_time;
int received_number_of_privmsgs;
int flood_noticed;
struct LocalUser *localClient;
struct PreClient *preClient;
time_t large_ctcp_sent; /* ctcp to large group sent, relax flood checks */
char *certfp; /* client certificate fingerprint */
client() {}
client(boost::asio::io_service *const &ios = ircd::ios);
client(const client &) = delete;
client &operator=(const client &) = delete;
~client() noexcept {}
};
struct ZipStats
{
unsigned long long in;
unsigned long long in_wire;
unsigned long long out;
unsigned long long out_wire;
double in_ratio;
double out_ratio;
};
typedef int SSL_OPEN_CB(client *, int status);
struct LocalUser
{
rb_dlink_node tnode; /* This is the node for the local list type the client is on */
rb_dlink_list connids; /* This is the list of connids to free */
/*
* The following fields are allocated only for local clients
* (directly connected to *this* server with a socket.
*/
/* Anti flooding part, all because of lamers... */
time_t last_join_time; /* when this client last
joined a channel */
time_t last_leave_time; /* when this client last
* left a channel */
int join_leave_count; /* count of JOIN/LEAVE in less than
MIN_JOIN_LEAVE_TIME seconds */
int oper_warn_count_down; /* warn opers of this possible
spambot every time this gets to 0 */
time_t last_caller_id_time;
time_t lasttime; /* last time we parsed something */
time_t firsttime; /* time client was created */
/* Send and receive linebuf queues .. */
buf_head_t buf_sendq;
buf_head_t buf_recvq;
/*
* we want to use unsigned int here so the sizes have a better chance of
* staying the same on 64 bit machines. The current trend is to use
* I32LP64, (32 bit ints, 64 bit longs and pointers) and since ircd
* will NEVER run on an operating system where ints are less than 32 bits,
* it's a relatively safe bet to use ints. Since right shift operations are
* performed on these, it's not safe to allow them to become negative,
* which is possible for long running server connections. Unsigned values
* generally overflow gracefully. --Bleep
*
* We have modern conveniences. Let's use uint32_t. --Elizafox
*/
uint32_t sendM; /* Statistics: protocol messages send */
uint32_t sendK; /* Statistics: total k-bytes send */
uint32_t receiveM; /* Statistics: protocol messages received */
uint32_t receiveK; /* Statistics: total k-bytes received */
uint16_t sendB; /* counters to count upto 1-k lots of bytes */
uint16_t receiveB; /* sent and received. */
struct Listener *listener; /* listener accepted from */
struct ConfItem *att_conf; /* attached conf */
struct server_conf *att_sconf;
struct rb_sockaddr_storage ip;
time_t last_nick_change;
int number_of_nick_changes;
/*
* XXX - there is no reason to save this, it should be checked when it's
* received and not stored, this is not used after registration
*
* agreed. lets get rid of it someday! --nenolod
*/
char *passwd;
char *auth_user;
char *opername; /* name of operator{} block being used or tried (challenge) */
char *challenge;
char *fullcaps;
char *cipher_string;
int caps; /* capabilities bit-field */
rb_fde_t *F; /* >= 0, for local clients */
/* time challenge response is valid for */
time_t chal_time;
time_t next_away; /* Don't allow next away before... */
time_t last;
/* clients allowed to talk through +g */
rb_dlink_list allow_list;
/* nicknames theyre monitoring */
rb_dlink_list monitor_list;
/*
* Anti-flood stuff. We track how many messages were parsed and how
* many we were allowed in the current second, and apply a simple decay
* to avoid flooding.
* -- adrian
*/
int sent_parsed; /* how many messages we've parsed in this second */
time_t last_knock; /* time of last knock */
uint32_t random_ping;
/* target change stuff */
/* targets we're aware of (fnv32(use_id(target_p))):
* 0..TGCHANGE_NUM-1 regular slots
* TGCHANGE_NUM..TGCHANGE_NUM+TGCHANGE_REPLY-1 reply slots
*/
uint32_t targets[tgchange::NUM + tgchange::REPLY];
unsigned int targets_free; /* free targets */
time_t target_last; /* last time we cleared a slot */
/* ratelimit items */
time_t ratelimit;
unsigned int join_who_credits;
struct ListClient *safelist_data;
char *mangledhost; /* non-NULL if host mangling module loaded and
applicable to this client */
struct _ssl_ctl *ssl_ctl; /* which ssl daemon we're associate with */
struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */
struct ws_ctl *ws_ctl; /* ctl for wsockd */
SSL_OPEN_CB *ssl_callback; /* ssl connection is now open */
uint32_t localflags;
struct ZipStats *zipstats; /* zipstats */
struct ev_entry *event; /* used for associated events */
struct PrivilegeSet *privset; /* privset... */
char sasl_agent[IDLEN];
unsigned char sasl_out;
unsigned char sasl_complete;
unsigned int sasl_messages;
unsigned int sasl_failures;
time_t sasl_next_retry;
};
#define AUTHC_F_DEFERRED 0x01
#define AUTHC_F_COMPLETE 0x02
struct AuthClient
{
uint32_t cid; /* authd id */
time_t timeout; /* When to terminate authd query */
bool accepted; /* did authd accept us? */
char cause; /* rejection cause */
char *data; /* reason data */
char *reason; /* reason we were rejected */
int flags;
};
struct PreClient
{
char spoofnick[NICKLEN + 1];
char spoofuser[USERLEN + 1];
char spoofhost[HOSTLEN + 1];
struct AuthClient auth;
struct rb_sockaddr_storage lip; /* address of our side of the connection */
};
struct ListClient
{
char *chname;
unsigned int users_min, users_max;
time_t created_min, created_max, topic_min, topic_max;
int operspy;
~client();
};
} // namespace client
} // namespace ircd
#endif // __cplusplus
/*
inline bool
is(const client &client, const mode::mask &mask)
{
@ -583,16 +313,13 @@ parse_as_server(const client &client)
return bool(client.status & (status::CONNECTING | status::HANDSHAKE | status::SERVER));
}
/*
* ts stuff
*/
#define TS_CURRENT 6
#define TS_MIN 6
#define TS_DOESTS 0x10000000
#define DoesTS(x) ((x)->tsinfo & TS_DOESTS)
/* if target is TS6, use id if it has one, else name */
inline bool
has_id(const client &client)
@ -639,7 +366,6 @@ id(const client &source, const client &target)
/* flags for local clients, this needs stuff moved from above to here at some point */
#define LFLAGS_SSL 0x00000001
#define LFLAGS_FLUSH 0x00000002
@ -877,86 +603,4 @@ operator!=(const client &a, const client &b)
return !(a == b);
}
/* local flags */
#define IsSSL(x) ((x)->localClient->localflags & LFLAGS_SSL)
#define SetSSL(x) ((x)->localClient->localflags |= LFLAGS_SSL)
#define ClearSSL(x) ((x)->localClient->localflags &= ~LFLAGS_SSL)
#define IsFlush(x) ((x)->localClient->localflags & LFLAGS_FLUSH)
#define SetFlush(x) ((x)->localClient->localflags |= LFLAGS_FLUSH)
#define ClearFlush(x) ((x)->localClient->localflags &= ~LFLAGS_FLUSH)
/*
* definitions for get_client_name
*/
#define HIDE_IP 0
#define SHOW_IP 1
#define MASK_IP 2
extern void check_banned_lines(void);
extern void check_klines_event(void *unused);
extern void check_klines(void);
extern void check_dlines(void);
extern void check_xlines(void);
extern void resv_nick_fnc(const char *mask, const char *reason, int temp_time);
extern const char *get_client_name(client *client, int show_ip);
extern const char *log_client_name(client *, int);
extern int is_remote_connect(client *);
void init(void);
extern client *make_client(client *from);
extern void free_pre_client(client *client);
extern void free_client(client *client);
extern int exit_client(client *, client *, client *, const char *);
extern void error_exit_client(client *, int);
extern void count_local_client_memory(size_t * count, size_t * memory);
extern void count_remote_client_memory(size_t * count, size_t * memory);
extern int clean_nick(const char *, int loc_client);
extern client *find_chasing(client *, const char *, int *);
extern client *find_person(const char *);
extern client *find_named_person(const char *);
client *find_named_person(const std::string &);
extern client *next_client(client *, const char *);
#define accept_message(s, t) ((s) == (t) || (rb_dlinkFind((s), &((t)->localClient->allow_list))))
extern void del_all_accepts(client *client_p);
extern void dead_link(client *client_p, int sendqex);
extern int show_ip(client *source_p, client *target_p);
extern int show_ip_conf(struct ConfItem *aconf, client *source_p);
extern int show_ip_whowas(const whowas::whowas &, client &source);
extern void close_connection(client *);
extern void init_uid(void);
extern char *generate_uid(void);
uint32_t connid_get(client *client_p);
void connid_put(uint32_t id);
void client_release_connids(client *client_p);
user::user &make_user(client &, const std::string &login = {});
serv::serv &make_serv(client &);
} // namespace client
using client::ZipStats;
using client::LocalUser;
using client::ListClient;
const client::user::user &user(const client::client &client);
client::user::user &user(client::client &client);
const client::serv::serv &serv(const client::client &client);
client::serv::serv &serv(client::client &client);
} // namespace ircd
#endif // __cplusplus
*/

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 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_CLIENT_SOCK_H
#ifdef __cplusplus
#include <boost/asio.hpp>
#include <boost/asio/steady_timer.hpp>
namespace ircd {
namespace client {
namespace ip = boost::asio::ip;
using boost::asio::steady_timer;
struct sock
{
ip::tcp::socket sd;
steady_timer timer;
operator const ip::tcp::socket &() const;
operator ip::tcp::socket &();
sock(boost::asio::io_service *const &ios = ircd::ios);
};
inline
sock::operator ip::tcp::socket &()
{
return sd;
}
inline
sock::operator const ip::tcp::socket &()
const
{
return sd;
}
} // namespace client
} // namespace ircd
#endif // __cplusplus

View file

@ -31,26 +31,11 @@
#include "stdinc.h"
#endif
// TODO: move
// Allow a reference to an ios to be passed to ircd
#ifdef __cplusplus
namespace boost {
namespace asio {
struct io_service;
} // namespace asio
} // namespace boost
#endif // __cplusplus
#ifdef __cplusplus
namespace ircd {
extern bool debugmode;
extern boost::asio::io_service *ios;
extern client::client me;
extern client::client *me;
// Set callback for when IRCd's main context has completed.
using main_exit_cb = std::function<void ()>;

View file

@ -36,8 +36,8 @@ extern bool valid_username(const char *username);
extern int user_mode(client::client *, client::client *, int, const char **);
void send_umode_out(client::client &client, const client::client &after, const umode::mask &before = 0);
void send_umode(client::client &to, const client::client &after, const umode::mask &before = 0);
//void send_umode_out(client::client &client, const client::client &after, const umode::mask &before = 0);
//void send_umode(client::client &to, const client::client &after, const umode::mask &before = 0);
void send_umode(client::client &to, const client::client &source, const char *const &buf);
extern void show_lusers(client::client *source_p);

View file

@ -27,6 +27,18 @@
#include <rb/rb.h>
#endif
// TODO: move
// Allow a reference to an ios to be passed to ircd
#ifdef __cplusplus
namespace boost {
namespace asio {
struct io_service;
} // namespace asio
} // namespace boost
#endif // __cplusplus
namespace ircd
{
using std::begin;
@ -41,6 +53,8 @@ namespace ircd
// Temp fwd decl scaffold
namespace ircd
{
extern boost::asio::io_service *ios;
namespace client
{
struct client;

View file

@ -42,7 +42,8 @@ libircd_la_SOURCES = \
snomask.cc \
info.cc \
cmd.cc \
ctx.cc
ctx.cc \
client.cc
#authproc.cc \
#bandbi.cc \

File diff suppressed because it is too large Load diff

View file

@ -107,7 +107,7 @@ conf::execute(const std::string &line)
try
{
log.debug("%s", line.c_str());
ircd::execute(me, line);
ircd::execute(*me, line);
return true;
}
catch(const std::exception &e)

View file

@ -31,6 +31,7 @@ namespace ircd
bool debugmode; // set by command line
boost::asio::io_service *ios; // user's io service
main_exit_cb main_exit_func; // Called when main context exits
client::client *me; // That's me
void seed_random();
void init_system();
@ -76,10 +77,13 @@ void
ircd::main()
noexcept try
{
// Ownership is taken of the main context to delete it at function end
// The user is notified when this function ends; + other cleanup
const scope main_exit(&main_exiting);
log::debug("IRCd entered main context.");
// Establish me here after we have an ios
me = new client::client;
log::info("executing configuration");
conf::execute();
@ -145,6 +149,7 @@ ircd::main_exiting()
noexcept try
{
mods::unload();
delete me;
if(main_exit_func)
{
@ -258,8 +263,7 @@ struct ServerStatistics ServerStats;
struct ev_entry *check_splitmode_ev;
int maxconnections;
client::client me; // That's me
struct LocalUser meLocalUser; // That's also part of me
//struct LocalUser meLocalUser; // That's also part of me
rb_dlink_list global_client_list;

View file

@ -46,7 +46,7 @@ moduledir=@moduledir@
#m_kill_la_SOURCES = m_kill.cc
#m_message_la_SOURCES = m_message.cc
#m_mode_la_SOURCES = m_mode.cc
m_modules_la_SOURCES = m_modules.cc
#m_modules_la_SOURCES = m_modules.cc
#m_nick_la_SOURCES = m_nick.cc
#m_part_la_SOURCES = m_part.cc
#m_quit_la_SOURCES = m_quit.cc
@ -122,8 +122,8 @@ m_modules_la_SOURCES = m_modules.cc
#m_xline_la_SOURCES = m_xline.cc
#sno_routing_la_SOURCES = sno_routing.cc
module_LTLIBRARIES = \
m_modules.la
module_LTLIBRARIES =
# m_modules.la
# m_ban.la \
# m_die.la \
# m_error.la \

View file

@ -20,19 +20,13 @@
*/
#include <boost/asio.hpp>
#include <ircd/lex_cast.h>
#include <ircd/ctx_ctx.h>
#include <ircd/lex_cast.h>
#include <ircd/client_sock.h>
namespace ip = boost::asio::ip;
using namespace ircd;
struct clicli
{
ip::tcp::socket socket;
clicli(): socket{*ircd::ios} {}
};
const size_t STACK_SIZE
{
256_KiB // can be optimized
@ -127,9 +121,9 @@ bool
listener::accept()
try
{
auto clit(std::make_unique<clicli>());
acceptor.async_accept(clit->socket, yield(continuation()));
printf("Got client!\n");
auto client(std::make_unique<client::client>());
acceptor.async_accept(client->sock->sd, yield(continuation()));
return true;
}
catch(const boost::system::system_error &e)