Skip to content

Commit

Permalink
Merge pull request #55 from ArthanIRC/bot-client-lowlevel
Browse files Browse the repository at this point in the history
feat: implement first low-level building bots for the Bot client
  • Loading branch information
aurlic authored Sep 14, 2024
2 parents d212988 + da30009 commit ab13099
Show file tree
Hide file tree
Showing 16 changed files with 357 additions and 93 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ objs

# Executables
ircserv
ircbot
*.exe
*.out
*.app
Expand Down
25 changes: 20 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#* ************************************************************************** *#

TARGET := ircserv
TARGET_2 := ircbot

#* ************************************************************************** *#
#* * COMPILATION * *#
Expand All @@ -28,28 +29,31 @@ STD := -std=c++98
#* * INCLUDES * *#
#* ************************************************************************** *#

INCLUDES := include include/Commands
INCLUDES := include include/Commands bot/include
INCLUDES_FLAGS += $(addprefix -I, $(INCLUDES))

#* ************************************************************************** *#
#* * SOURCES * *#
#* ************************************************************************** *#

SRCDIR := ./src/
SRCDIR_2 := ./bot/src/
-include make/sources.mk
SRCDIR := src

#* ************************************************************************** *#
#* * OBJECTS * *#
#* ************************************************************************** *#

OBJDIR := obj
OBJECTS := ${SOURCES:%.cpp=${OBJDIR}/%.o}
OBJECTS_2 := ${SOURCES_2:%.cpp=${OBJDIR}/%.o}

#* ************************************************************************** *#
#* * DEPENDENCIES * *#
#* ************************************************************************** *#

DEPENDENCIES := $(OBJECTS:.o=.d)
DEPENDENCIES_2 := $(OBJECTS_2:.o=.d)

#* ************************************************************************** *#
#* * TEXT CONSTANTS * *#
Expand Down Expand Up @@ -101,13 +105,13 @@ endef
#* * MAKEFILE RULES * *#
#* ************************************************************************** *#

all: $(TARGET)
all: $(TARGET) $(TARGET_2)

# -------------------- #
# Create object files. #
# -------------------- #

$(OBJECTS): $(OBJDIR)/%.o: %.cpp
$(OBJECTS) $(OBJECTS_2): $(OBJDIR)/%.o: %.cpp
@mkdir -p $(@D)
@$(call compile_message)
@$(CC) $(CPPFLAGS) $(STD) -MMD -MF $(@:.o=.d) $(INCLUDES_FLAGS) -c $< -o $@
Expand All @@ -124,6 +128,14 @@ $(TARGET): $(OBJECTS)
@echo ""
@$(call success_message)

-include $(DEPENDENCIES_2)
ircbot: $(OBJECTS) $(OBJECTS_2)
@echo ""
@$(call linking_message)
@$(CC) $(CPPFLAGS) $(STD) $(INCLUDES_FLAGS) -o $@ $(filter-out obj/./src/main.o,$(OBJECTS)) $(OBJECTS_2)
@echo ""
@$(call success_message)

# --------------------- #
# Delete compiled data. #
# --------------------- #
Expand All @@ -134,6 +146,7 @@ clean:

fclean: clean
@rm -rf $(TARGET)
@rm -rf $(TARGET_2)
@printf "$(YELLOW)Deleting $(CYAN)$(NAME) executable $(YELLOW)...$(RESET_COLOR)\n"

# ------------------------------- #
Expand All @@ -142,7 +155,9 @@ fclean: clean

gmk:
if [ -d make ];then echo ok;else mkdir make;fi
@find ./src/ -name '*.cpp' -printf "%d%p\n" | sort -n | sed 's/^[[:digit:]]/SOURCES += /' > make/sources.mk
@find $(SRCDIR) -name '*.cpp' -printf "%d%p\n" | sort -n | sed 's/^[[:digit:]]/SOURCES += /' > make/sources.mk
@find $(SRCDIR_2) -name '*.cpp' -printf "%d%p\n" | sort -n | sed 's/^[[:digit:]]/SOURCES_2 += /' >> make/sources.mk


# --------------------- #
# Recompile. #
Expand Down
37 changes: 37 additions & 0 deletions bot/include/Bot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <exception>
#include <string>

#include "BotSocket.hpp"

class Bot {
private:
BotSocket _socket;
std::string _password;
bool _running;
bool _registered;

Bot();
Bot(Bot const&);
void operator=(Bot const&);

void login();

public:
~Bot();

void init(int ac, char** data);
void run();
void stop();

static Bot& getInstance();

class InvalidNumberOfParametersException : public std::exception {
virtual const char* what() const throw();
};

class InvalidPortException : public std::exception {
virtual const char* what() const throw();
};
};
26 changes: 26 additions & 0 deletions bot/include/BotSocket.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <string>

#include "Socket.hpp"

class BotSocket : public Socket {
private:
struct addrinfo* _ai;
bool _registered;
bool _eof;
std::string _rem;

public:
BotSocket();
~BotSocket();

void init(const char* ip, const char* port);
void connect();
std::string receive();
void sendMessage(std::string message);
void onPoll(uint32_t events);
void setRegistered();
bool isRegistered();
bool isEof();
};
62 changes: 62 additions & 0 deletions bot/src/Bot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <cstdlib>

#include "Bot.hpp"
#include "Server.hpp"

using std::string;

static const string defaultPort = "6667";

Bot::Bot() {}

Bot::~Bot() {}

void Bot::init(int ac, char** data) {
if (ac < 3 || ac > 4)
throw Bot::InvalidNumberOfParametersException();

string port;
if (ac == 3)
port = defaultPort;
else
port = Server::parsePort(data[3]);

this->_password = Server::parsePassword(data[2]);
this->_running = true;
this->_registered = false;
this->_socket.init(data[1], port.c_str());
}

void Bot::run() {
this->_socket.connect();

while (_running) {
if (!_registered) {
login();
}
string data = _socket.receive();
if (data.empty() && _socket.isEof())
break;
if (data.empty())
continue;

// TODO: parse data, create response and do things
}
}

void Bot::login() {}

void Bot::stop() { this->_running = false; }

Bot& Bot::getInstance() {
static Bot instance;
return instance;
}

const char* Bot::InvalidNumberOfParametersException::what() const throw() {
return "Error: Usage: ./ircbot <address> <password> [<port>]";
}

const char* Bot::InvalidPortException::what() const throw() {
return "Error: Port has to be between 1 and 65535";
}
75 changes: 75 additions & 0 deletions bot/src/BotSocket.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <cstring>
#include <netdb.h>

#include "BotSocket.hpp"

using std::string;

BotSocket::BotSocket() : Socket(), _registered(false) {}

BotSocket::~BotSocket() { freeaddrinfo(_ai); }

void BotSocket::init(const char* ip, const char* port) {
struct addrinfo hints, *ai;
int rv;

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

if ((rv = getaddrinfo(ip, port, &hints, &ai)) != 0)
throw Socket::AddrInfoException();

this->_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (_fd < 0) {
freeaddrinfo(ai);
throw Socket::SocketCreationException();
}

this->_ai = ai;
}

void BotSocket::connect() {
if (::connect(_fd, _ai->ai_addr, _ai->ai_addrlen) == -1)
throw Socket::ConnectException();
}

void BotSocket::onPoll(uint32_t events) { (void)events; }

bool BotSocket::isEof() { return this->_eof; }

string BotSocket::receive() {
char buf[MAX_LIMIT];
string data;
ssize_t size;
memset(buf, 0, MAX_LIMIT);

if (!_rem.empty()) {
data.append(_rem);
_rem.clear();
}

size = recv(_fd, buf, MAX_LIMIT, 0);
data.append(buf);
if (data.empty() || size == -1) {
_eof = true;
return "";
}

size_t i = data.find("\n");
i = i == string::npos ? string::npos : i + 1;
string line = data.substr(0, i);
data = data.erase(0, i);
if (!line.empty() && i == string::npos) {
_rem = line;
return "";
}
if (!data.empty())
_rem = data;
return line;
}

void BotSocket::sendMessage(string message) {
if (send(_fd, message.c_str(), message.size(), MSG_NOSIGNAL) == -1)
throw Socket::SendException();
}
41 changes: 41 additions & 0 deletions bot/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <csignal>
#include <cstdlib>
#include <iostream>

#include "Bot.hpp"

static void handle_signint(int signal) {
(void)signal;
Bot::getInstance().stop();
}

static int register_sigaction(int signal, void (*handler)(int)) {
struct sigaction action;
sigset_t set;

sigemptyset(&set);
action.sa_handler = handler;
action.sa_mask = set;
action.sa_flags = 0;
if (sigaction(signal, &action, NULL) == -1) {
std::cerr << "Error: sigaction creation failed\n";
return -1;
}
return 0;
}

int main(int ac, char** av) {
if (register_sigaction(SIGINT, &handle_signint) == -1 ||
register_sigaction(SIGQUIT, SIG_IGN) == -1)
return EXIT_FAILURE;

std::setlocale(LC_ALL, "en_US.UTF-8");

try {
Bot::getInstance().init(ac, av);
Bot::getInstance().run();
} catch (std::exception& e) {
std::cerr << e.what() << "\n";
return EXIT_FAILURE;
}
}
1 change: 1 addition & 0 deletions compile_flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
-std=c++98
-Iinclude
-Iinclude/Commands
-Ibot/include
8 changes: 0 additions & 8 deletions include/ClientSocket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <string>

#include "Exception.hpp"
#include "Socket.hpp"

class Client;
Expand All @@ -15,18 +14,11 @@ class ClientSocket : public Socket {
void removeSelf();
void executeCommand(std::string data, Client* client);

const static int MAX_LIMIT = 4096;

public:
ClientSocket(int fd, std::string ip);
~ClientSocket();

void onPoll(uint32_t events);
void sendMessage(std::string message);
std::string const& getIp() const;

class SendException : ServerException {
public:
virtual const char* what() const throw();
};
};
5 changes: 2 additions & 3 deletions include/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,11 @@ class Server {
Server(Server const&);
void operator=(Server const&);

static std::string parsePort(const char* strp);
static std::string parsePassword(std::string pass);

public:
~Server();

static std::string parsePort(const char* strp);
static std::string parsePassword(std::string pass);
void init(int ac, char** data);
void run();
void stop();
Expand Down
Loading

0 comments on commit ab13099

Please sign in to comment.