Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 113 additions & 34 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
NAME = ircserv
NAME := ircserv
ANNOUNCER_NAME := Announcer

CXX = c++
CXX := c++
CXXFLAGS := -Wall -Wextra -Werror -std=c++98 -MMD -MP

SRCS_DIR = ./srcs
INC_DIR = ./incs
OBJ_DIR = ./objs
TEST_DIR = ./tests
SRCS_DIR := ./srcs
INC_DIR := ./incs
OBJ_DIR := ./objs
TEST_DIR := ./tests


INCLUDES = -I$(INC_DIR) \
INCLUDES := -I$(INC_DIR) \
-I$(INC_DIR)/core \
-I$(INC_DIR)/network \
-I$(INC_DIR)/commands
# -I$(INC_DIR)/bot
-I$(INC_DIR)/commands

BONUS_INCLUDES := -I$(INC_DIR)/bot

get_color = $(if $(filter Purple,$(1)),$(shell tput setaf 5),$(if $(filter Red,$(1)),$(shell tput setaf 1),$(if $(filter Cyan,$(1)),$(shell tput setaf 6),$(if $(filter Blue,$(1)),$(shell tput setaf 4),$(if $(filter Yellow,$(1)),$(shell tput setaf 3),$(if $(filter Green,$(1)),$(shell tput setaf 2),$(if $(filter Off,$(1)),$(shell tput sgr0),$(shell tput sgr0))))))))

FLAGS = -Wall -Wextra -Werror -std=c++98 -g3 $(INCLUDES)
ifdef DEBUG
CXXFLAGS += -g3 -DDEBUG_MODE
else ifdef FSAN
CXXFLAGS += -g3 -fsanitize=address -DDEBUG_MODE
endif

SRCS = $(SRCS_DIR)/main.cpp \
SRCS := $(SRCS_DIR)/main.cpp \
$(SRCS_DIR)/core/Config.cpp \
$(SRCS_DIR)/core/Server.cpp \
$(SRCS_DIR)/core/Client.cpp \
Expand Down Expand Up @@ -50,19 +58,103 @@ SRCS = $(SRCS_DIR)/main.cpp \
$(SRCS_DIR)/modes/OperatorMode.cpp \
$(SRCS_DIR)/modes/KeyMode.cpp \
$(SRCS_DIR)/modes/UserLimitMode.cpp \
$(SRCS_DIR)/protocol/IrcUtils.cpp
# $(SRCS_DIR)/bot/BotClient.cpp

OBJ = $(SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/%.o)
$(SRCS_DIR)/protocol/IrcUtils.cpp

BONUS_SRCS := $(SRCS_DIR)/bot/BotClient.cpp \
$(SRCS_DIR)/bot/SixSevenBot.cpp

OBJS := $(SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/%.o)
OBJS_BONUS := $(SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/bonus/%.o) \
$(BONUS_SRCS:$(SRCS_DIR)/%.cpp=$(OBJ_DIR)/bonus/%.o)

BONUS_MARKER := .bonus

all: $(NAME)
.PHONY: all bonus clean fclean re debug fsan format lint lint-fix \
test test_run test_filter docker-test docker-test-shell docker-test-filter

$(NAME): $(OBJ)
$(CXX) $(FLAGS) -o $(NAME) $(OBJ)
all:
@if $(MAKE) --no-print-directory -q $(NAME) 2>/dev/null; then \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Everything is up to date. $(call get_color,Purple)Zzz...$(call get_color,Off)"; \
else \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Starting build of $(call get_color,Purple)$(NAME)$(call get_color,Off)..."; \
$(MAKE) --no-print-directory $(NAME); \
fi

bonus:
@if [ -f $(BONUS_MARKER) ] && $(MAKE) --no-print-directory -q $(BONUS_MARKER) 2>/dev/null; then \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Bonus is already up to date. $(call get_color,Purple)Zzz...$(call get_color,Off)"; \
else \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Starting build of $(call get_color,Yellow)$(NAME)$(call get_color,Off) (with bots. many of these.)..."; \
$(MAKE) --no-print-directory $(BONUS_MARKER); \
fi

-include $(OBJS:.o=.d)
-include $(OBJS_BONUS:.o=.d)

$(OBJ_DIR)/%.o: $(SRCS_DIR)/%.cpp
@mkdir -p $(dir $@)
$(CXX) $(FLAGS) -c $< -o $@
@mkdir -p $(dir $@)
@printf "\r\033[K$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Cyan)Compiling $<$(call get_color,Off)"
@$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ || \
(echo "\n$(call get_color,Red)Compilation failed for $<$(call get_color,Off)" && exit 1)

$(OBJ_DIR)/bonus/%.o: $(SRCS_DIR)/%.cpp
@mkdir -p $(dir $@)
@printf "\r\033[K$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Cyan)Compiling $<$(call get_color,Off)"
@$(CXX) $(CXXFLAGS) -DBONUS $(INCLUDES) $(BONUS_INCLUDES) -c $< -o $@ || \
(echo "\n$(call get_color,Red)Compilation failed for $<$(call get_color,Off)" && exit 1)

$(NAME): $(OBJS)
@printf "\r\033[K$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Green)Linking $(NAME)$(call get_color,Off)\n"
@$(CXX) $(CXXFLAGS) $(INCLUDES) -o $(NAME) $(OBJS) || \
(echo "$(call get_color,Red)Linking failed!$(call get_color,Off)" && exit 1)
@if [ "$(DEBUG)" = "1" ]; then \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Purple)$(NAME)$(call get_color,Off) compiled in $(call get_color,Red)DEBUG$(call get_color,Off) mode!"; \
else \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Purple)$(NAME)$(call get_color,Off) has been compiled! Netsplits are now a philosophical concept and PING timeouts build character :) (discord remains the disaster recovery plan)"; \
fi

$(BONUS_MARKER): $(OBJS_BONUS)
@printf "\r\033[K$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Green)Linking $(NAME) with bonus$(call get_color,Off)\n"
@$(CXX) $(CXXFLAGS) $(INCLUDES) $(BONUS_INCLUDES) -o $(NAME) $(OBJS_BONUS) || \
(echo "$(call get_color,Red)Linking failed!$(call get_color,Off)" && exit 1)
@touch $(BONUS_MARKER)
@if [ "$(DEBUG)" = "1" ]; then \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Purple)$(NAME)$(call get_color,Off) with $(call get_color,Yellow)BONUS$(call get_color,Off) compiled in $(call get_color,Red)DEBUG$(call get_color,Off) mode!"; \
else \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Purple)$(NAME)$(call get_color,Off) with $(call get_color,Yellow)BONUS$(call get_color,Off) has been compiled!"; \
fi

clean:
@echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Cleaning object files..."
@if [ -d $(OBJ_DIR) ]; then \
rm -rf $(OBJ_DIR) && \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Removed object and dependency files"; \
else \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] No object files to clean"; \
fi
@if [ -f $(BONUS_MARKER) ]; then \
rm -f $(BONUS_MARKER) && \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Removed bonus marker"; \
fi
@$(MAKE) --no-print-directory -C $(TEST_DIR) clean

fclean: clean
@if [ -f $(NAME) ]; then \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] Removing $(call get_color,Purple)$(NAME)$(call get_color,Off)..."; \
rm -f $(NAME) && \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Purple)$(NAME)$(call get_color,Off) is GONE!!"; \
else \
echo "$(call get_color,Off)[$(ANNOUNCER_NAME)] $(call get_color,Purple)$(NAME)$(call get_color,Off) is already gone"; \
fi
@$(MAKE) --no-print-directory -C $(TEST_DIR) fclean

re: fclean all

debug:
@$(MAKE) --no-print-directory re DEBUG=1

fsan:
@$(MAKE) --no-print-directory re FSAN=1

test:
@$(MAKE) -C $(TEST_DIR)
Expand All @@ -82,17 +174,6 @@ docker-test-shell:
docker-test-filter:
@$(MAKE) -C $(TEST_DIR) docker-test-filter FILTER=$(FILTER)

clean:
rm -f $(OBJ)
rm -rf $(OBJ_DIR)
$(MAKE) -C $(TEST_DIR) clean

fclean: clean
rm -f $(NAME)
$(MAKE) -C $(TEST_DIR) fclean

re: fclean all

format:
@find . -type f \( -name "*.cpp" -o -name "*.hpp" \) -exec clang-format -i {} +

Expand All @@ -101,5 +182,3 @@ lint:

lint-fix:
run-clang-tidy -fix

.PHONY: all clean fclean re format lint lint-fix test test_run test_filter docker-test docker-test-shell docker-test-filter
1 change: 1 addition & 0 deletions incs/core/IServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ class IServer
virtual void deleteChannelIfEmpty(IChannel* channel) = 0;
virtual size_t getChannelCount() const = 0;
virtual std::string getServerName() const = 0;
virtual void markForDisconnect(int fd) = 0;
};
1 change: 1 addition & 0 deletions incs/core/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@ class Server : public IServer
size_t getChannelCount() const;
std::string getServerName() const;
bool requiresPassword() const;
void markForDisconnect(int fd);
};
5 changes: 5 additions & 0 deletions srcs/commands/QuitCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "IChannel.hpp"
#include "IClient.hpp"
#include "IServer.hpp"
#include "core/IMessageBuffer.hpp"
#include "commands/ACommand.hpp"
#include "commands/CommandRegistration.hpp"
#include "commands/CommandType.hpp"
Expand Down Expand Up @@ -62,6 +63,10 @@ void QuitCommand::doExecute(IClient* client, const Message& message)
m_server.deleteChannelIfEmpty(*it);
}
}

std::string errorMsg = "ERROR :Closing link (" + quitMessage + ")\r\n";
client->getBuffer().appendWrite(errorMsg);
m_server.markForDisconnect(client->getFd());
}

ACommand* QuitCommand::create(IServer& server)
Expand Down
5 changes: 3 additions & 2 deletions srcs/core/Logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,9 @@ void Logger::flush()
{
if (m_lineStarted && m_currentLevel >= m_minLevel)
{
*m_output << m_buffer.str() << "\033[0m" << '\n';
m_output->flush();
std::ostream& out = (m_currentLevel >= ERROR) ? std::cerr : *m_output;
out << m_buffer.str() << "\033[0m" << '\n';
out.flush();
}
m_buffer.str("");
m_buffer.clear();
Expand Down
17 changes: 10 additions & 7 deletions srcs/core/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,8 @@ static void setNonBlocking(int fd)
void Server::disconnectClient(int fd)
{
m_pendingDisconnects.erase(fd);
try
{
m_sm->removeSocket(fd);
}
catch (...)
{ // catch any exception "..."
}

m_sm->removeSocket(fd);
close(fd);
std::map< int, IClient* >::iterator it = m_clients.find(fd);
if (it != m_clients.end())
Expand Down Expand Up @@ -346,6 +341,14 @@ bool Server::requiresPassword() const
return !m_cfg.getPassword().empty();
}

void Server::markForDisconnect(int fd)
{
m_pendingDisconnects.insert(fd);
IClient* client = getClient(fd);
if (client && !client->getBuffer().getWriteBuffer().empty())
m_sm->modifySocket(fd, EPOLLIN | EPOLLOUT);
}

static int createListeningSocket(int port) // fd that listens to all interfaces trying to bind
{
std::stringstream ss;
Expand Down
4 changes: 4 additions & 0 deletions srcs/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ int main(int argc, char** argv)
std::signal(SIGINT, signalHandler);
std::signal(SIGTERM, signalHandler);

#ifdef DEBUG_MODE
Logger::getInstance().setMinLevel(Logger::DEBUG);
#else
Logger::getInstance().setMinLevel(Logger::NOTICE);
#endif

try
{
Expand Down
13 changes: 9 additions & 4 deletions srcs/network/PollSocketManager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "PollSocketManager.hpp"
#include "Logger.hpp"
#include <cerrno>
#include <ostream>

const std::vector< epoll_event >& PollSocketManager::getEvents() const
{
Expand All @@ -11,7 +13,7 @@ int PollSocketManager::wait(int timeout_ms)
int n = epoll_wait(m_epollFd, &m_events[0], (int)m_events.size(), timeout_ms);

if (n == -1 && errno != EINTR)
throw std::runtime_error("epoll_wait failed\n");
throw std::runtime_error("epoll_wait failed");

if (n == (int)m_events.size())
m_events.resize(m_events.size() * 2);
Expand All @@ -29,13 +31,16 @@ void PollSocketManager::modifySocket(int fd, int events)
evt.data.fd = fd;

if (epoll_ctl(m_epollFd, EPOLL_CTL_MOD, fd, &evt) == -1)
throw std::runtime_error("Modification of socket failed\n");
throw std::runtime_error("Modification of socket failed");
}

void PollSocketManager::removeSocket(int fd)
{
// if this fail we most likely don't care as it isn't critical per se
// basically it's caused by the fd already being removed from epoll so that's fine
// we can still log it though :)
if (epoll_ctl(m_epollFd, EPOLL_CTL_DEL, fd, 0) == -1)
throw std::runtime_error("Deletion of socket failed\n");
LOG_WARNING << "Deletion of socket " << fd << " failed" << std::endl;
}

void PollSocketManager::addSocket(int fd, int events)
Expand All @@ -62,4 +67,4 @@ PollSocketManager::~PollSocketManager()
{
if (m_epollFd != -1)
close(m_epollFd);
}
}
5 changes: 5 additions & 0 deletions tests/mocks/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,9 @@ size_t Server::getChannelCount() const
std::string Server::getServerName() const
{
return "mock_server.serv";
}

void Server::markForDisconnect(int fd)
{
MOCK_LOG("Server marking fd " << fd << " for disconnect");
}
1 change: 1 addition & 0 deletions tests/mocks/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ class Server : public IServer
void deleteChannelIfEmpty(IChannel* channel);
size_t getChannelCount() const;
std::string getServerName() const;
void markForDisconnect(int fd);
};