irccd  3.0.3
irc.hpp
1 /*
2  * irc.hpp -- low level IRC functions
3  *
4  * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #ifndef IRCCD_IRC_HPP
20 #define IRCCD_IRC_HPP
21 
27 #include <irccd/sysconfig.hpp>
28 
29 #include <functional>
30 #include <string>
31 #include <string_view>
32 #include <utility>
33 #include <vector>
34 
35 #include <boost/asio.hpp>
36 
37 #if defined(IRCCD_HAVE_SSL)
38 # include <boost/asio/ssl.hpp>
39 #endif
40 
41 namespace irccd {
42 
43 namespace daemon {
44 
48 namespace irc {
49 
55 enum class err {
64  nosuchnick = 401,
65 
74  nosuchserver = 402,
75 
83  nosuchchannel = 403,
84 
95  cannotsendtochan = 404,
96 
106  toomanychannels = 405,
107 
116  wasnosuchnick = 406,
117 
127  toomanytargets = 407,
128 
138  noorigin = 409,
139 
145  norecipient = 411,
146 
152  notexttosend = 412,
153 
159  notoplevel = 413,
160 
172  wildtoplevel = 414,
173 
182  unknowncommand = 421,
183 
191  nomotd = 422,
192 
202  noadmininfo = 423,
203 
212  fileerror = 424,
213 
222  nonicknamegiven = 431,
223 
233  erroneusnickname = 432,
234 
244  nicknameinuse = 433,
245 
255  nickcollision = 436,
256 
265  usernotinchannel = 441,
266 
276  notonchannel = 442,
277 
286  useronchannel = 443,
287 
297  nologin = 444,
298 
307  summondisabled = 445,
308 
317  usersdisabled = 446,
318 
328  notregistered = 451,
329 
339  needmoreparams = 461,
340 
350  alreadyregistred = 462,
351 
362  nopermforhost = 463,
363 
373  passwdmismatch = 464,
374 
384  yourebannedcreep = 465,
385 
391  keyset = 467,
392 
398  channelisfull = 471,
399 
405  unknownmode = 472,
406 
412  inviteonlychan = 473,
413 
419  bannedfromchan = 474,
420 
426  badchannelkey = 475,
427 
437  noprivileges = 481,
438 
449  chanoprivsneeded = 482,
450 
460  cantkillserver = 483,
461 
472  nooperhost = 491,
473 
483  umodeunknownflag = 501,
484 
493  usersdontmatch = 502
494 };
495 
501 enum class rpl {
507  none = 300,
508 
525  userhost = 302,
526 
535  ison = 303,
536 
542  away = 301,
543 
549  unaway = 305,
550 
563  nowaway = 306,
564 
570  whoisuser = 311,
571 
577  whoisserver = 312,
578 
584  whoisoperator = 313,
585 
591  whoisidle = 317,
592 
598  endofwhois = 318,
599 
620  whoischannels = 319,
621 
627  whowasuser = 314,
628 
641  endofwhowas = 369,
642 
648  liststart = 321,
649 
655  list = 322,
656 
668  listend = 323,
669 
675  channelmodeis = 324,
676 
682  notopic = 331,
683 
694  topic = 332,
695 
705  inviting = 341,
706 
715  summoning = 342,
716 
731  version = 351,
732 
739  whoreply = 352,
740 
754  endofwho = 315,
755 
761  namreply = 353,
762 
778  endofnames = 366,
779 
785  links = 364,
786 
796  endoflinks = 365,
797 
803  banlist = 367,
804 
817  endofbanlist = 368,
818 
824  info = 371,
825 
836  endofinfo = 374,
837 
843  motdstart = 375,
844 
850  motd = 372,
851 
864  endofmotd = 376,
865 
875  youreoper = 381,
876 
886  rehashing = 382,
887 
899  time = 391,
900 
906  userstart = 392,
907 
913  users = 393,
914 
920  endofusers = 394,
921 
934  nousers = 395,
935 
941  tracelink = 200,
942 
948  traceconnecting = 201,
949 
955  tracehandshake = 202,
956 
962  traceunknown = 203,
963 
969  traceoperator = 204,
970 
976  traceuser = 205,
977 
984  traceserver = 206,
985 
991  tracenewtype = 208,
992 
1018  tracelog = 261,
1019 
1027  statslinkinfo = 211,
1028 
1034  statscommands = 212,
1035 
1041  statscline = 213,
1042 
1048  statsnline = 214,
1049 
1055  statsiline = 215,
1056 
1062  statskline = 216,
1063 
1069  statsyline = 218,
1070 
1076  endofstats = 219,
1077 
1083  statslline = 241,
1084 
1090  statsuptime = 242,
1091 
1097  statsoline = 243,
1098 
1104  statshline = 244,
1105 
1114  umodeis = 221,
1115 
1122  luserclient = 251,
1123 
1129  luserop = 252,
1130 
1136  luserunknown = 253,
1137 
1143  luserchannels = 254,
1144 
1159  luserme = 255,
1160 
1166  adminme = 256,
1167 
1173  adminloc1 = 257,
1174 
1180  adminloc2 = 258,
1181 
1198  adminemail = 259
1199 };
1200 
1204 struct message {
1205  std::string prefix;
1206  std::string command;
1207  std::vector<std::string> args;
1208 
1215  template <typename Enum>
1216  auto is(Enum e) const noexcept -> bool
1217  {
1218  try {
1219  return std::stoi(command) == static_cast<int>(e);
1220  } catch (...) {
1221  return false;
1222  }
1223  }
1224 
1232  auto get(unsigned short index) const noexcept -> const std::string&;
1233 
1240  auto is_ctcp(unsigned short index) const noexcept -> bool;
1241 
1249  auto ctcp(unsigned short index) const -> std::string;
1250 
1257  static auto parse(const std::string& line) -> message;
1258 };
1259 
1263 struct user {
1264  std::string nick;
1265  std::string host;
1266 
1273  static auto parse(std::string_view line) -> user;
1274 };
1275 
1279 class connection {
1280 public:
1284  using connect_handler = std::function<void (std::error_code)>;
1285 
1289  using recv_handler = std::function<void (std::error_code, message)>;
1290 
1294  using send_handler = std::function<void (std::error_code)>;
1295 
1296 private:
1297  boost::asio::io_context& service_;
1298  boost::asio::ip::tcp::socket socket_{service_};
1299  boost::asio::ip::tcp::resolver resolver_{service_};
1300  boost::asio::streambuf input_{1024};
1301  boost::asio::streambuf output_;
1302 
1303  bool ipv4_{true};
1304  bool ipv6_{true};
1305  bool ssl_{false};
1306 
1307 #if defined(IRCCD_HAVE_SSL)
1308  boost::asio::ssl::context context_{boost::asio::ssl::context::tlsv12};
1309  boost::asio::ssl::stream<boost::asio::ip::tcp::socket&> ssl_socket_{socket_, context_};
1310 #endif
1311 
1312 #if !defined(NDEBUG)
1313  bool is_connecting_{false};
1314  bool is_receiving_{false};
1315  bool is_sending_{false};
1316 #endif
1317 
1318  void handshake(const connect_handler&);
1319  void connect(const boost::asio::ip::tcp::resolver::results_type&, const connect_handler&);
1320  void resolve(std::string_view, std::string_view, const connect_handler&);
1321 
1322 public:
1328  connection(boost::asio::io_service& service);
1329 
1333  virtual ~connection() = default;
1334 
1340  void use_ipv4(bool enable = true) noexcept;
1341 
1347  void use_ipv6(bool enable = true) noexcept;
1348 
1355  void use_ssl(bool enable = true) noexcept;
1356 
1367  void connect(std::string_view hostname, std::string_view service, connect_handler handler);
1368 
1372  void disconnect();
1373 
1384  void recv(recv_handler handler);
1385 
1397  void send(std::string_view message, send_handler handler);
1398 };
1399 
1400 } // !irc
1401 
1402 } // !daemon
1403 
1404 } // !irccd
1405 
1406 #endif // !IRCCD_IRC_HPP
irccd::daemon::irc::err::needmoreparams
@ needmoreparams
irccd::daemon::irc::rpl::umodeis
@ umodeis
irccd::daemon::irc::err::nomotd
@ nomotd
irccd::daemon::irc::rpl::luserclient
@ luserclient
irccd::daemon::irc::err::nosuchserver
@ nosuchserver
irccd::daemon::irc::rpl::traceconnecting
@ traceconnecting
irccd::daemon::irc::connection::use_ipv4
void use_ipv4(bool enable=true) noexcept
irccd::daemon::irc::rpl::luserme
@ luserme
irccd::daemon::irc::err::nopermforhost
@ nopermforhost
irccd::daemon::irc::err::usersdontmatch
@ usersdontmatch
irccd::daemon::irc::user::nick
std::string nick
The nickname.
Definition: irc.hpp:1264
irccd::daemon::irc::err::keyset
@ keyset
irccd::daemon::irc::rpl::away
@ away
irccd::daemon::irc::rpl::traceuser
@ traceuser
irccd::daemon::irc::message::command
std::string command
command (maybe string or code)
Definition: irc.hpp:1206
irccd::daemon::irc::err::toomanytargets
@ toomanytargets
irccd::daemon::irc::rpl::statslline
@ statslline
irccd::daemon::irc::err::notonchannel
@ notonchannel
irccd::daemon::irc::rpl::summoning
@ summoning
irccd::daemon::irc::err::noadmininfo
@ noadmininfo
irccd::daemon::irc::rpl::endofbanlist
@ endofbanlist
irccd::daemon::irc::err::fileerror
@ fileerror
irccd::daemon::irc::rpl::traceunknown
@ traceunknown
irccd::daemon::irc::rpl::traceoperator
@ traceoperator
irccd::daemon::irc::rpl::nowaway
@ nowaway
irccd::daemon::irc::rpl::endofwhowas
@ endofwhowas
irccd::daemon::irc::rpl::endofwho
@ endofwho
irccd::daemon::irc::rpl::endofinfo
@ endofinfo
irccd::daemon::irc::err::alreadyregistred
@ alreadyregistred
irccd::daemon::irc::rpl::whoischannels
@ whoischannels
irccd::daemon::irc::err::toomanychannels
@ toomanychannels
irccd::daemon::irc::rpl::statskline
@ statskline
irccd::daemon::irc::rpl::version
@ version
irccd::daemon::irc::err::noprivileges
@ noprivileges
irccd::daemon::irc::err::nonicknamegiven
@ nonicknamegiven
irccd::daemon::irc::rpl::endofnames
@ endofnames
irccd::daemon::irc::rpl::adminemail
@ adminemail
irccd::daemon::irc::err::erroneusnickname
@ erroneusnickname
irccd::daemon::irc::rpl::statsnline
@ statsnline
irccd::daemon::irc::message::is_ctcp
auto is_ctcp(unsigned short index) const noexcept -> bool
irccd::daemon::irc::connection::use_ssl
void use_ssl(bool enable=true) noexcept
irccd::daemon::irc::rpl::traceserver
@ traceserver
irccd::daemon::irc::rpl::motd
@ motd
irccd::daemon::irc::err::summondisabled
@ summondisabled
irccd::daemon::irc::message::args
std::vector< std::string > args
parameters
Definition: irc.hpp:1207
irccd::daemon::irc::message::is
auto is(Enum e) const noexcept -> bool
Definition: irc.hpp:1216
irccd::daemon::irc::rpl::whoisoperator
@ whoisoperator
irccd::daemon::irc::rpl::rehashing
@ rehashing
irccd::daemon::irc::rpl::endofmotd
@ endofmotd
irccd::daemon::irc::connection::~connection
virtual ~connection()=default
irccd::daemon::irc::rpl::topic
@ topic
irccd::daemon::irc::rpl::links
@ links
irccd::daemon::irc::rpl::whoisserver
@ whoisserver
irccd::daemon::irc::err::nologin
@ nologin
irccd::daemon::irc::connection::recv
void recv(recv_handler handler)
irccd::daemon::irc::message::get
auto get(unsigned short index) const noexcept -> const std::string &
irccd::daemon::irc::rpl::listend
@ listend
irccd::daemon::irc::connection::disconnect
void disconnect()
irccd::daemon::irc::err::notregistered
@ notregistered
irccd::daemon::irc::rpl::channelmodeis
@ channelmodeis
irccd::daemon::irc::rpl::ison
@ ison
irccd::daemon::irc::rpl
rpl
Describe numeric replies.
Definition: irc.hpp:501
irccd::daemon::irc::rpl::statslinkinfo
@ statslinkinfo
irccd::daemon::irc::connection::send
void send(std::string_view message, send_handler handler)
irccd::daemon::irc::err::useronchannel
@ useronchannel
irccd::daemon::irc::rpl::statsoline
@ statsoline
irccd::daemon::irc::rpl::time
@ time
irccd::daemon::irc::rpl::statscline
@ statscline
irccd::daemon::irc::user::parse
static auto parse(std::string_view line) -> user
irccd::daemon::irc::rpl::inviting
@ inviting
irccd::daemon::irc::rpl::whoisuser
@ whoisuser
irccd::daemon::irc::connection::recv_handler
std::function< void(std::error_code, message)> recv_handler
Definition: irc.hpp:1289
irccd::daemon::irc::err::unknowncommand
@ unknowncommand
irccd::daemon::irc::err::notoplevel
@ notoplevel
irccd::daemon::irc::err::notexttosend
@ notexttosend
irccd::daemon::irc::message::parse
static auto parse(const std::string &line) -> message
irccd::daemon::irc::rpl::userhost
@ userhost
irccd::daemon::irc::err::inviteonlychan
@ inviteonlychan
irccd::daemon::irc::user::host
std::string host
The hostname.
Definition: irc.hpp:1265
irccd::daemon::irc::rpl::luserop
@ luserop
irccd::daemon::irc::rpl::whowasuser
@ whowasuser
irccd::daemon::irc::rpl::endofusers
@ endofusers
irccd::daemon::irc::err::nosuchnick
@ nosuchnick
irccd::daemon::irc::rpl::luserunknown
@ luserunknown
irccd::daemon::irc::rpl::none
@ none
irccd::daemon::irc::err::passwdmismatch
@ passwdmismatch
irccd::daemon::irc::err
err
Describe errors.
Definition: irc.hpp:55
irccd::daemon::irc::rpl::statsyline
@ statsyline
irccd::daemon::irc::rpl::luserchannels
@ luserchannels
irccd::daemon::irc::err::norecipient
@ norecipient
irccd::daemon::irc::rpl::info
@ info
irccd::daemon::irc::message::prefix
std::string prefix
optional prefix
Definition: irc.hpp:1205
irccd::daemon::irc::rpl::statscommands
@ statscommands
irccd::daemon::irc::err::channelisfull
@ channelisfull
irccd::daemon::irc::err::usernotinchannel
@ usernotinchannel
irccd::daemon::irc::rpl::whoreply
@ whoreply
irccd::daemon::irc::connection::use_ipv6
void use_ipv6(bool enable=true) noexcept
irccd::daemon::irc::err::nicknameinuse
@ nicknameinuse
irccd::daemon::irc::message::ctcp
auto ctcp(unsigned short index) const -> std::string
irccd::daemon::irc::rpl::tracehandshake
@ tracehandshake
irccd::daemon::irc::err::cannotsendtochan
@ cannotsendtochan
irccd::daemon::irc::rpl::statsiline
@ statsiline
irccd::daemon::irc::rpl::adminloc1
@ adminloc1
irccd::daemon::irc::rpl::userstart
@ userstart
irccd::daemon::irc::rpl::unaway
@ unaway
irccd
Parent namespace.
Definition: acceptor.hpp:43
std
Definition: bot.hpp:253
irccd::daemon::irc::connection::connection
connection(boost::asio::io_service &service)
irccd::daemon::irc::rpl::notopic
@ notopic
irccd::daemon::irc::rpl::youreoper
@ youreoper
irccd::daemon::irc::rpl::namreply
@ namreply
irccd::daemon::irc::err::bannedfromchan
@ bannedfromchan
irccd::daemon::irc::rpl::motdstart
@ motdstart
irccd::daemon::irc::err::chanoprivsneeded
@ chanoprivsneeded
irccd::daemon::irc::rpl::whoisidle
@ whoisidle
irccd::daemon::irc::rpl::tracelink
@ tracelink
irccd::daemon::irc::err::nickcollision
@ nickcollision
irccd::daemon::irc::err::umodeunknownflag
@ umodeunknownflag
irccd::daemon::irc::rpl::endoflinks
@ endoflinks
irccd::daemon::irc::rpl::statsuptime
@ statsuptime
irccd::daemon::irc::rpl::endofwhois
@ endofwhois
irccd::daemon::irc::err::nooperhost
@ nooperhost
irccd::daemon::irc::err::usersdisabled
@ usersdisabled
irccd::daemon::irc::rpl::endofstats
@ endofstats
irccd::daemon::irc::err::unknownmode
@ unknownmode
irccd::daemon::irc::err::wildtoplevel
@ wildtoplevel
irccd::daemon::irc::rpl::tracelog
@ tracelog
irccd::daemon::irc::connection::connect_handler
std::function< void(std::error_code)> connect_handler
Definition: irc.hpp:1284
irccd::daemon::irc::connection
Abstract connection to a server.
Definition: irc.hpp:1279
irccd::daemon::irc::rpl::users
@ users
irccd::daemon::irc::err::wasnosuchnick
@ wasnosuchnick
irccd::daemon::irc::rpl::adminme
@ adminme
irccd::daemon::irc::rpl::banlist
@ banlist
irccd::daemon::irc::err::noorigin
@ noorigin
irccd::daemon::irc::rpl::list
@ list
irccd::daemon::irc::err::cantkillserver
@ cantkillserver
irccd::daemon::irc::rpl::tracenewtype
@ tracenewtype
irccd::daemon::irc::user
Describe a user.
Definition: irc.hpp:1263
irccd::daemon::irc::message
Describe a IRC message.
Definition: irc.hpp:1204
irccd::daemon::irc::err::nosuchchannel
@ nosuchchannel
irccd::daemon::irc::rpl::nousers
@ nousers
irccd::daemon::irc::rpl::statshline
@ statshline
irccd::daemon::irc::err::badchannelkey
@ badchannelkey
irccd::daemon::irc::connection::send_handler
std::function< void(std::error_code)> send_handler
Definition: irc.hpp:1294
irccd::daemon::irc::err::yourebannedcreep
@ yourebannedcreep
irccd::daemon::irc::rpl::liststart
@ liststart
irccd::daemon::irc::rpl::adminloc2
@ adminloc2