From 033456e94932a5fbeebfc212402648a55a69f7ae Mon Sep 17 00:00:00 2001 From: Xnoe Date: Sat, 19 Jun 2021 14:48:55 +0100 Subject: [PATCH] Initial commit of XnoIRCd codebase --- .gitignore | 2 + Makefile | 28 ++++++ channel.cpp | 28 ++++++ channel.h | 26 +++++ connection.cpp | 42 ++++++++ connection.h | 29 ++++++ irccommand.cpp | 94 ++++++++++++++++++ irccommand.h | 33 +++++++ ircserver.cpp | 30 ++++++ ircserver.h | 24 +++++ main.cpp | 42 ++++++++ nameable.cpp | 71 ++++++++++++++ nameable.h | 44 +++++++++ user.cpp | 233 +++++++++++++++++++++++++++++++++++++++++++++ user.h | 69 ++++++++++++++ userconnection.cpp | 50 ++++++++++ userconnection.h | 29 ++++++ 17 files changed, 874 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 channel.cpp create mode 100644 channel.h create mode 100644 connection.cpp create mode 100644 connection.h create mode 100644 irccommand.cpp create mode 100644 irccommand.h create mode 100644 ircserver.cpp create mode 100644 ircserver.h create mode 100644 main.cpp create mode 100644 nameable.cpp create mode 100644 nameable.h create mode 100644 user.cpp create mode 100644 user.h create mode 100644 userconnection.cpp create mode 100644 userconnection.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4974e64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +xnoircd diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9b7f09d --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +FLAGS = -pthread + +xnoircd: user.o nameable.o channel.o connection.o ircserver.o irccommand.o userconnection.o main.o + g++ $(FLAGS) user.o nameable.o channel.o connection.o ircserver.o irccommand.o userconnection.o main.o -o $@ + +user.o: user.cpp user.h + g++ -g -c $*.cpp + +connection.o: connection.cpp connection.h + g++ -g -c $*.cpp + +ircserver.o: ircserver.cpp ircserver.h + g++ -g -c $*.cpp + +irccommand.o: irccommand.cpp irccommand.h + g++ -g -c $*.cpp + +userconnection.o: userconnection.cpp userconnection.h + g++ -g -c $*.cpp + +nameable.o: nameable.cpp nameable.h + g++ -g -c $*.cpp + +channel.o: channel.cpp channel.h + g++ -g -c $*.cpp + +main.o: main.cpp + g++ -g -c $*.cpp \ No newline at end of file diff --git a/channel.cpp b/channel.cpp new file mode 100644 index 0000000..f373983 --- /dev/null +++ b/channel.cpp @@ -0,0 +1,28 @@ +#include "channel.h" + +Channel::Channel(IRCServer* server, std::string channel_name): Nameable(server) { + this->channel_name = channel_name; + server->register_addressable_name(channel_name, this); +} + +Channel::~Channel() { + remove_addressable_name(channel_name); +} + +void Channel::send_direct(std::string message) { + send_relay(message); +} + +std::string Channel::get_topic() { + return topic; +} + +void Channel::set_topic(std::string topic) { + this->topic = topic; +} +bool Channel::has_topic() { + return (this->topic!=""); +} +NameableType Channel::what_are_you() { + return NT_Channel; +} \ No newline at end of file diff --git a/channel.h b/channel.h new file mode 100644 index 0000000..7e8a092 --- /dev/null +++ b/channel.h @@ -0,0 +1,26 @@ +#ifndef CHANNEL_H +#define CHANNEL_H + +#include +#include "nameable.h" +#include "ircserver.h" + +class Channel: public Nameable { +private: + std::string channel_name; + std::string topic; + +public: + Channel(IRCServer* server, std::string channel_name); + ~Channel(); + + void send_direct(std::string message); + + std::string get_topic(); + bool has_topic(); + void set_topic(std::string topic); + + NameableType what_are_you(); +}; + +#endif \ No newline at end of file diff --git a/connection.cpp b/connection.cpp new file mode 100644 index 0000000..80f7a65 --- /dev/null +++ b/connection.cpp @@ -0,0 +1,42 @@ +#include "connection.h" +#include + +Connection::Connection(int fd) { + this->fd = fd; + std::thread(&Connection::conn_hdlr, this).detach(); +} + +Connection::~Connection() { + close(this->fd); +} + +void Connection::conn_hdlr() { + buffer = new char[512]; + while (alive) { + if (read(this->fd, buffer, 511) == 0) { + destroy(); + return; + } + std::string message(buffer); + int index; + if ((index = message.find_first_of("\r\n")) == std::string::npos) + continue; + else + message = message.substr(0, index); + process_cmd(message); + } +} + +void Connection::process_cmd(std::string command) {} +void Connection::destroy() {} + +void Connection::kill() { + this->alive = false; +} + +void Connection::send(std::string to_write) { + to_write = to_write + "\r\n"; + const char* buffer = to_write.c_str(); + int len = strlen(buffer); + write(this->fd, buffer, len); +} \ No newline at end of file diff --git a/connection.h b/connection.h new file mode 100644 index 0000000..6bb4173 --- /dev/null +++ b/connection.h @@ -0,0 +1,29 @@ +#ifndef CONNECTION_H +#define CONNECTION_H + +#include +#include +#include +#include + +class Connection { +private: + int fd; + int alive = true; + char* buffer; + +public: + Connection(int fd); + ~Connection(); + + void conn_hdlr(); + + virtual void process_cmd(std::string command); + virtual void destroy(); + + void kill(); + + void send(std::string to_write); +}; + +#endif \ No newline at end of file diff --git a/irccommand.cpp b/irccommand.cpp new file mode 100644 index 0000000..130765b --- /dev/null +++ b/irccommand.cpp @@ -0,0 +1,94 @@ +#include "irccommand.h" + +#include + +IRCCommand::IRCCommand(std::string raw_command) { + if (raw_command[0] == '@') { + int index = raw_command.find_first_of(" "); + + std::string tag_section = raw_command.substr(1, index); + raw_command = raw_command.substr(index+1); + + // Todo: Further process tags down + } + + if (raw_command[0] != 0) + raw_command.substr(1); + else + return; + + if (raw_command[0] == ':') { + int index = raw_command.find_first_of(" "); + source = raw_command.substr(1, index); + raw_command = raw_command.substr(index+1); + } + + if (raw_command[0] != 0) + raw_command.substr(1); + else + return; + + int index = raw_command.find_first_of(" "); + command = raw_command.substr(0, index); + raw_command = raw_command.substr(index+1); + + if (raw_command[0] != 0) + raw_command.substr(1); + else + return; + + std::vector payloads; + index = raw_command.find_first_of(" "); + + while (index != std::string::npos && raw_command[0] != ':') { + payloads.push_back(raw_command.substr(0, index)); + raw_command = raw_command.substr(index + 1); + index = raw_command.find_first_of(" "); + } + + if (raw_command[0] == ':') + payloads.push_back(raw_command.substr(1)); + else + payloads.push_back(raw_command); + + this->payload = payloads; +} + +bool IRCCommand::has_source() { + return (source!=""); +} + +std::string IRCCommand::get_source() { + return source; +} + +bool IRCCommand::has_command() { + return (command!=""); +} + +std::string IRCCommand::get_command() { + return command; +} + +bool IRCCommand::has_payload() { + return payload.size() > 0; +} + +std::string IRCCommand::get_payload(int i) { + return payload.at(i); +} + +int IRCCommand::get_payload_count() { + return payload.size(); +} + +std::string IRCCommand::to_string() { + std::string myself; + if (has_source()) + myself += "Source: " + get_source() + "\n"; + if (has_command()) + myself += "Command: " + get_command() + "\n"; + for (std::string p : payload) + myself += "Parameters: " + p + "\n"; + return myself; +} \ No newline at end of file diff --git a/irccommand.h b/irccommand.h new file mode 100644 index 0000000..7b98d8b --- /dev/null +++ b/irccommand.h @@ -0,0 +1,33 @@ +#ifndef IRCCOMMAND_H +#define IRCCOMMAND_H + +#include +#include +#include + +class IRCCommand { +private: + std::unordered_map tags; + std::string source, command = ""; + std::vector payload; +public: + IRCCommand(std::string raw_command); + + bool has_source(); + + std::string get_source(); + + bool has_command(); + + std::string get_command(); + + bool has_payload(); + + std::string get_payload(int i); + + int get_payload_count(); + + std::string to_string(); +}; + +#endif \ No newline at end of file diff --git a/ircserver.cpp b/ircserver.cpp new file mode 100644 index 0000000..0846764 --- /dev/null +++ b/ircserver.cpp @@ -0,0 +1,30 @@ +#include "ircserver.h" + +IRCServer::IRCServer(std::string hostname) { + this->hostname = hostname; + this->nameable_map = {}; +} + +bool IRCServer::is_addressable_name_free(std::string name) { + return nameable_map.find(name) == nameable_map.end(); +} + +bool IRCServer::has_addressable_name(std::string name) { + return !is_addressable_name_free(name); +} + +void IRCServer::remove_addressable_name(std::string name) { + nameable_map.erase(name); +} + +void IRCServer::register_addressable_name(std::string name, Nameable* bind) { + nameable_map[name] = bind; +} + +Nameable* IRCServer::resolve_addressable_name(std::string name) { + return nameable_map[name]; +} + +std::string IRCServer::get_hostname() { + return hostname; +} \ No newline at end of file diff --git a/ircserver.h b/ircserver.h new file mode 100644 index 0000000..2bf7eba --- /dev/null +++ b/ircserver.h @@ -0,0 +1,24 @@ +#ifndef IRCSERVER_H +#define IRCSERVER_H + +#include +#include + +class Nameable; +class IRCServer { +private: + std::unordered_map nameable_map; + std::string hostname; +public: + + IRCServer(std::string); + + void register_addressable_name(std::string name, Nameable* bind); + bool is_addressable_name_free(std::string name); + bool has_addressable_name(std::string name); + void remove_addressable_name(std::string name); + Nameable* resolve_addressable_name(std::string name); + std::string get_hostname(); +}; + +#endif \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..c814949 --- /dev/null +++ b/main.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "ircserver.h" +#include "userconnection.h" + +int main() { + int socketfd = socket(AF_INET, SOCK_STREAM, 0); + if (socketfd == 0) { + std::cout << "Socket Create Failed!\n" << std::flush; + return 1; + } + int opt = 1; + if (setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + std::cout << "Setting Socket Options Failed!\n" << std::flush; + return 1; + } + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(6667); + + unsigned int addrsize = sizeof(addr); + if (bind(socketfd, (struct sockaddr*)&addr, addrsize) < 0) { + std::cout << "Socket Bind Failed!\n" << std::flush; + return 1; + } + + if (listen(socketfd, 5) < 0) { + std::cout << "Socket Listen Failed!\n" << std::flush; + return 1; + } + + IRCServer* server = new IRCServer("xnoircd"); + + while (true) { + int sockfd = accept(socketfd, (struct sockaddr*)&addr, &addrsize); + new UserConnection(sockfd, server); + } +} \ No newline at end of file diff --git a/nameable.cpp b/nameable.cpp new file mode 100644 index 0000000..84692ae --- /dev/null +++ b/nameable.cpp @@ -0,0 +1,71 @@ +#include "nameable.h" + +Nameable::Nameable(IRCServer* server) { + this->server = server; +} +Nameable::~Nameable() { + this->associates.clear(); + this->associates.shrink_to_fit(); +} + +std::string Nameable::get_addressable_name() { + return this->addressable_name; +} +bool Nameable::set_addressable_name(std::string name) { + if (this->server->is_addressable_name_free(name)) { + this->addressable_name = name; + server->register_addressable_name(name, this); + return true; + } else { + return false; + } +} +bool Nameable::has_addressable_name() { + return (this->addressable_name!=""); +} +void Nameable::remove_addressable_name(std::string name) { + server->remove_addressable_name(name); +} +bool Nameable::rename(std::string name) { + if (server->is_addressable_name_free(name)) { + server->remove_addressable_name(name); + server->register_addressable_name(name, this); + this->addressable_name = name; + return true; + } else { + return false; + } +} + +std::vector Nameable::get_associates() { + return this->associates; +} +void Nameable::add_associate(Nameable* associate) { + std::cout << "Adding: " << associate->get_addressable_name() << "\n"; + this->associates.push_back(associate); +} +bool Nameable::has_associate(Nameable* associate) { + return !(std::find(associates.begin(), associates.end(), associate) == associates.end()); +} +void Nameable::remove_associate(Nameable* associate) { + auto index = std::find(this->associates.begin(), this->associates.end(), associate); + if (index != this->associates.end()) { + this->associates.erase(index); + } +} +std::string Nameable::associates_as_string() { + std::string associate_list; + for (Nameable* associate : associates) { + associate_list += associate->get_addressable_name() + " "; + } + return associate_list; +} + +void Nameable::send_direct(std::string message) {} +void Nameable::send_relay(std::string message) { + for (Nameable* associate : this->associates) { + associate->send_direct(message); + } +} + +NameableType Nameable::what_are_you() {} \ No newline at end of file diff --git a/nameable.h b/nameable.h new file mode 100644 index 0000000..d01240b --- /dev/null +++ b/nameable.h @@ -0,0 +1,44 @@ +#ifndef NAMEABLE_H +#define NAMEABLE_H + +#include +#include +#include +#include +#include "connection.h" +#include "ircserver.h" + +enum NameableType { + NT_User, + NT_Channel +}; + +class Nameable { +private: + std::string addressable_name = ""; + std::vector associates; + +public: + IRCServer* server; + Nameable(IRCServer* server); + ~Nameable(); + + std::string get_addressable_name(); + bool set_addressable_name(std::string name); + bool has_addressable_name(); + void remove_addressable_name(std::string name); + bool rename(std::string to); + + std::vector get_associates(); + void add_associate(Nameable* associate); + bool has_associate(Nameable* associate); + void remove_associate(Nameable* associate); + std::string associates_as_string(); + + virtual void send_direct(std::string message); + void send_relay(std::string message); + + virtual NameableType what_are_you(); +}; + +#endif \ No newline at end of file diff --git a/user.cpp b/user.cpp new file mode 100644 index 0000000..173ab5c --- /dev/null +++ b/user.cpp @@ -0,0 +1,233 @@ +#include "user.h" +#include + +std::vector split_string(std::string str, std::string delim) { + std::vector to_return; + int delim_len = delim.length(); + int index = str.find_first_of(delim); + while (index != std::string::npos) { + to_return.push_back(str.substr(0, index)); + str = str.substr(index+delim_len); + index = str.find_first_of(delim); + } + to_return.push_back(str); + return to_return; +} + +std::unordered_map>> User::commands = { + {"NICK", {0, &User::nick_cmd}}, + {"PING", {1, &User::ping_cmd}}, + {"WHO", {1, &User::who_cmd}}, + {"WHOIS", {1, &User::whois_cmd}}, + {"JOIN", {1, &User::join_cmd}}, + {"PART", {1, &User::part_cmd}}, + {"QUIT", {0, &User::quit_cmd}}, + {"PRIVMSG", {2, &User::privmsg_cmd}}, + {"TOPIC", {2, &User::topic_cmd}}, + {"NAMES", {1, &User::names_cmd}} +}; + +User::User(IRCServer* server, UserConnection* conn): Nameable(server) { + this->connection = conn; +} +User::~User() { + this->server->remove_addressable_name(this->get_nick()); + this->send_relay(":" + this->get_nick() + " QUIT :Quit: "); + for (Nameable* associate : this->get_associates()) + associate->remove_associate(this); + delete connection; +} + +void User::nick_cmd(IRCCommand* cmd) { + set_nick(cmd->get_payload(0)); +} + +void User::ping_cmd(IRCCommand* cmd) { + send_direct(":" + server->get_hostname() + " PONG " + server->get_hostname() + " " + cmd->get_payload(0)); +} + +void User::join_cmd(IRCCommand* cmd) { + std::string channels_parameter = cmd->get_payload(0); + + std::vector named_channels = split_string(channels_parameter, ","); + std::cout << named_channels.size() << "\n"; + + for (std::string named_channel : named_channels) { + Nameable* channel; + if (server->has_addressable_name(named_channel)) { + channel = server->resolve_addressable_name(named_channel); + } else { + channel = new Channel(server, named_channel); + } + + if (channel->what_are_you() != NT_Channel) + continue; + + Channel* chan = (Channel*)channel; + + this->add_associate(chan); + chan->add_associate(this); + chan->send_direct(":" + this->get_nick() + " JOIN " + named_channel); + std::vector channel_members = chan->get_associates(); + + this->send_direct(":" + server->get_hostname() + " 353 " + this->get_nick() + " " + named_channel + " :" + chan->associates_as_string()); + if (chan->has_topic()) + this->send_direct(":" + server->get_hostname() + " 332 " + this->get_nick() + " " + named_channel + " :" + chan->get_topic()); + } +} + +void User::part_cmd(IRCCommand* cmd) { + std::string channels_parameter = cmd->get_payload(0); + + std::vector named_channels = split_string(channels_parameter, ","); + + for (std::string named_channel : named_channels) { + if (server->has_addressable_name(named_channel)) { + Nameable* channel = server->resolve_addressable_name(named_channel); + this->remove_associate(channel); + channel->remove_associate(this); + channel->send_direct(":" + this->get_nick() + " PART " + named_channel); + } + } +} + +void User::privmsg_cmd(IRCCommand* cmd) { + std::string named_target = cmd->get_payload(0); + + if (server->has_addressable_name(named_target)) { + Nameable* target = server->resolve_addressable_name(named_target); + for (Nameable* associate : target->get_associates()) { + if (associate->get_addressable_name() != this->get_nick()) + associate->send_direct(":" + this->get_nick() + " PRIVMSG " + named_target + " :" + cmd->get_payload(1)); + } + } +} + +void User::quit_cmd(IRCCommand* cmd) { + destroy(); +} + +void User::who_cmd(IRCCommand* cmd) { + if (!server->has_addressable_name(cmd->get_payload(0))) + return; + + Nameable* target = server->resolve_addressable_name(cmd->get_payload(0)); + if (target->what_are_you() != NT_User) + return; + + User* user = (User*)target; + + send_direct(":" + server->get_hostname() + " 352 " + this->get_nick() + " * " + user->get_username() + " " /*+ user->get_hostname()*/ + " " + server->get_hostname() + " H :0 " + user->get_realname()); + send_direct(":" + server->get_hostname() + " 315 " + this->get_nick() + " " + user->get_nick() + " :End of WHO listing."); +} + +void User::whois_cmd(IRCCommand* cmd) { + if (!server->has_addressable_name(cmd->get_payload(0))) + return; + + Nameable* target = server->resolve_addressable_name(cmd->get_payload(0)); + if (target->what_are_you() != NT_User) + return; + + User* user = (User*)target; +} + +void User::topic_cmd(IRCCommand* cmd) { + if (!server->has_addressable_name(cmd->get_payload(0))) + return; + + Nameable* target = server->resolve_addressable_name(cmd->get_payload(0)); + if (target->what_are_you() != NT_Channel) + return; + + ((Channel*)target)->set_topic(cmd->get_payload(1)); +} + +void User::names_cmd(IRCCommand* cmd) { + std::string named_channel = cmd->get_payload(0); + if (!server->has_addressable_name(named_channel)) + return; + Nameable* resolved = server->resolve_addressable_name(named_channel); + if (resolved->what_are_you() != NT_Channel) + return; + Channel* chan = (Channel*)resolved; + this->send_direct(":" + server->get_hostname() + " 353 " + this->get_nick() + " " + named_channel + " :" + chan->associates_as_string()); +} + +void User::process_cmd(IRCCommand* cmd) { + auto command = commands.find(cmd->get_command()); + if (command == commands.end()) { + send_direct(":" + server->get_hostname() + " 421 " + get_nick() + " " + cmd->get_command() + " :Unknown Command."); + return; + } + + if (cmd->get_payload_count() < std::get<0>(command->second)) { + send_direct(":" + server->get_hostname() + " 461 " + get_nick() + " " + cmd->get_command() + " :Too few parameters."); + return; + } + + std::get<1>(command->second)(this, cmd); +} + +void User::set_nick(std::string nick) { + bool success; + std::string old_nick = this->get_nick(); + if (this->has_nick()) + success = this->rename(nick); + else + success = this->set_addressable_name(nick); + + if (success) { + if (old_nick != "") + send_direct(":" + old_nick + " NICK :" + this->get_nick()); + } else { + send_direct(":" + server->get_hostname() + " 433 * " + nick + " Nickname is already in use!"); + } +} + +void User::set_username(std::string username) { + this->username = username; +} + +void User::set_realname(std::string realname) { + this->realname = realname; +} + +bool User::has_nick() { + return has_addressable_name(); +} + +bool User::has_username(){ + return (username!=""); +} + +bool User::has_realname(){ + return (realname!=""); +} + +std::string User::get_nick(){ + return get_addressable_name(); +} + +std::string User::get_username(){ + return username; +} + +std::string User::get_realname(){ + return realname; +} + +void User::send_direct(std::string message) { + std::cout << message << "\n"; + this->connection->send(message); +} + +NameableType User::what_are_you() { + return NT_User; +} + +void User::destroy() { + Connection* conn = connection; + delete this; + conn->kill(); +} \ No newline at end of file diff --git a/user.h b/user.h new file mode 100644 index 0000000..1372cda --- /dev/null +++ b/user.h @@ -0,0 +1,69 @@ +#ifndef USER_H +#define USER_H + +#include +#include +#include +#include + +#include "irccommand.h" +#include "ircserver.h" +#include "userconnection.h" +#include "nameable.h" +#include "channel.h" + +class UserConnection; +class User: public Nameable { +private: + std::string username, realname = ""; + Connection* connection; + + void nick_cmd(IRCCommand* cmd); + void ping_cmd(IRCCommand* cmd); + void who_cmd(IRCCommand* cmd); + void whois_cmd(IRCCommand* cmd); + void join_cmd(IRCCommand* cmd); + void part_cmd(IRCCommand* cmd); + void quit_cmd(IRCCommand* cmd); + void privmsg_cmd(IRCCommand* cmd); + void topic_cmd(IRCCommand* cmd); + void names_cmd(IRCCommand* cmd); + + static std::unordered_map>> commands; + + //std::string construct_string(int count, std::string source, std::string command, std::string parameters...); + template + std::string construct_string(std::string source, std::string command, T... parameters); + +public: + User(IRCServer* server, UserConnection* conn); + ~User(); + + void process_cmd(IRCCommand* cmd); + + void set_nick(std::string nick); + + void set_username(std::string username); + + void set_realname(std::string realname); + + bool has_nick(); + + bool has_username(); + + bool has_realname(); + + std::string get_nick(); + + std::string get_username(); + + std::string get_realname(); + + void send_direct(std::string message); + + NameableType what_are_you(); + + void destroy(); +}; + +#endif \ No newline at end of file diff --git a/userconnection.cpp b/userconnection.cpp new file mode 100644 index 0000000..32bb3c6 --- /dev/null +++ b/userconnection.cpp @@ -0,0 +1,50 @@ +#include "userconnection.h" + +#include + +UserConnection::UserConnection(int fd, IRCServer* server): Connection(fd) { + this->server = server; + this->user = new User(server, this); +} + +UserConnection::~UserConnection() {} + +void UserConnection::process_cmd(std::string cmd_in) { + if (cmd_in == "") + return; + + IRCCommand* cmd = new IRCCommand(cmd_in); + std::cout << cmd_in << std::endl; + + if (state == Registered) { + user->process_cmd(cmd); + delete cmd; + return; + } + + std::string command = cmd->get_command(); + + if (command == "NICK" && cmd->has_payload()) { + user->set_nick(cmd->get_payload(0)); + } + + if (command == "USER" && cmd->has_payload()) { + user->set_username(cmd->get_payload(0)); + user->set_realname(cmd->get_payload(3)); + } + + if (user->has_nick() && user->has_username()) { + state = Registered; + send(":xnoircd 001 " + user->get_nick() + " :Welcome"); + send(":xnoircd 002 " + user->get_nick() + " :Welcome"); + send(":xnoircd 003 " + user->get_nick() + " :Welcome"); + send(":xnoircd 004 " + user->get_nick() + " xnoircd 0 ABCabc ABCabc"); + send(":xnoircd 422 " + user->get_nick() + " :No MOTD"); + } + + delete cmd; +} + +void UserConnection::destroy() { + this->user->destroy(); +} \ No newline at end of file diff --git a/userconnection.h b/userconnection.h new file mode 100644 index 0000000..6b670c9 --- /dev/null +++ b/userconnection.h @@ -0,0 +1,29 @@ +#ifndef USERCONNECTION_H +#define USERCONNECTION_H + +#include + +#include "connection.h" +#include "ircserver.h" +#include "user.h" + +enum UCState { + Initial, + Registered +}; + +class User; +class UserConnection: public Connection { +private: + User* user; + UCState state = Initial; + IRCServer* server; +public: + UserConnection(int fd, IRCServer* server); + ~UserConnection(); + + void process_cmd(std::string cmd_in); + void destroy(); +}; + +#endif \ No newline at end of file