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
4 changes: 3 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MAKE_FLAGS += -j

SRC := $(wildcard src/*.cpp) $(wildcard src/Pizza/*.cpp) $(wildcard src/Pizza/Pizzas/*.cpp)
SRC := $(wildcard src/*.cpp) $(wildcard src/Pizza/*.cpp) $(wildcard src/Pizza/Pizzas/*.cpp) $(wildcard src/IPC/*.cpp) $(wildcard src/Logger/*.cpp)

BUILD_DIR := .build

Expand All @@ -13,6 +13,8 @@ CXXFLAGS += -Wwrite-strings -Werror=format-nonliteral -Werror=return-type
CXXFLAGS += -std=c++20 -iquote src -iquote src/Server -iquote src/Client -iquote libs/myteams
CXXFLAGS += -Isrc/Pizza
CXXFLAGS += -Isrc/Pizza/Pizzas
CXXFLAGS += -Isrc/IPC
CXXFLAGS += -Isrc/Logger

include utils.mk

Expand Down
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";

outputs = { self, nixpkgs }: let
forAllSystems = function:
nixpkgs.lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
] (system:
let
pkgs = nixpkgs.legacyPackages.${system};

isDarwinAarch64 =
pkgs.stdenv.hostPlatform.isDarwin &&
pkgs.stdenv.hostPlatform.isAarch64;
in
function pkgs isDarwinAarch64
);
in {
devShells = forAllSystems (pkgs: isDarwinAarch64: {
default = pkgs.mkShell {
hardeningDisable = [ "fortify" ];
packages = with pkgs;
[
compiledb
clang
llvm_21
gnumake
criterion
valgrind
];
};
bonus = pkgs.mkShell {
packages = [
(pkgs.python3.withPackages (ps: [ ps.matplotlib ps.numpy ]))
];
};
});

formatter = forAllSystems (pkgs: _: pkgs.alejandra);

packages = forAllSystems (pkgs: _: {
default = self.packages.${pkgs.system}._scom;
_scom = pkgs.callPackage ./nix/package.nix { };
});
};
}
97 changes: 97 additions & 0 deletions src/IPC/Channel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include <cerrno>
#include <cstring>
#include <stdexcept>
#include <string>
#include <unistd.h>

#include "Logger/Logger.hpp"
#include "Channel.hpp"

namespace plazza {

static std::string errstr(const char *prefix) {
return std::string(prefix) + ": " + std::strerror(errno);
}

static const char *msgTypeName(MsgType t) {
switch (t) {
case MsgType::ORDER:
return "ORDER";
case MsgType::READY:
return "READY";
case MsgType::STATUS_REQ:
return "STATUS_REQ";
case MsgType::STATUS_RES:
return "STATUS_RES";
case MsgType::CLOSE:
return "CLOSE";
case MsgType::CLOSED:
return "CLOSED";
}
return "UNKNOWN";
}

Channel::Channel() : _rfd(-1), _wfd(-1) {
if (::pipe(_toChild) == -1 || ::pipe(_toParent) == -1)
throw std::runtime_error(errstr("pipe"));
LOG_DEBUG("Channel created");
}

Channel::~Channel() {
closeFd(_toChild[0]);
closeFd(_toChild[1]);
closeFd(_toParent[0]);
closeFd(_toParent[1]);
}

void Channel::closeFd(int &fd) {
if (fd != -1) {
::close(fd);
fd = -1;
}
}

void Channel::parentSide() {
closeFd(_toChild[0]);
closeFd(_toParent[1]);
_wfd = _toChild[1];
_rfd = _toParent[0];
LOG_DEBUG("Channel configured as parent");
}

void Channel::childSide() {
closeFd(_toChild[1]);
closeFd(_toParent[0]);
_rfd = _toChild[0];
_wfd = _toParent[1];
LOG_DEBUG("Channel configured as child");
}

Channel &Channel::operator<<(const Message &msg) {
LOG_DEBUG(std::string("Channel send: ") + msgTypeName(msg.type));
if (::write(_wfd, &msg, sizeof(msg)) == -1)
throw std::runtime_error(errstr("write"));
return *this;
}

Channel &Channel::operator>>(Message &msg) {
ssize_t n = ::read(_rfd, &msg, sizeof(msg));
if (n == 0) {
LOG_WARN("Channel closed by remote");
throw std::runtime_error("channel closed");
}
if (n == -1)
throw std::runtime_error(errstr("read"));
LOG_DEBUG(std::string("Channel recv: ") + msgTypeName(msg.type));
return *this;
}

bool Channel::tryRead(Message &msg) {
struct pollfd pfd{_rfd, POLLIN, 0};
if (::poll(&pfd, 1, 0) <= 0)
return false;
*this >> msg;
return true;
}

} // namespace plazza
54 changes: 54 additions & 0 deletions src/IPC/Channel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once

#include <poll.h>

#include "IPizza.hpp"

namespace plazza {

static constexpr int INGREDIENT_COUNT = 9;

enum class MsgType {
ORDER = 1,
READY = 2,
STATUS_REQ = 3,
STATUS_RES = 4,
CLOSE = 5,
CLOSED = 6,
};

struct Message {
MsgType type;
PizzaType pizzaType;
PizzaSize pizzaSize;
int cooksBusy;
int cooksTotal;
int pizzasQueued;
int stock[INGREDIENT_COUNT];
};

class Channel {
public:
Channel();
~Channel();

Channel(const Channel &) = delete;
Channel &operator=(const Channel &) = delete;

void parentSide();
void childSide();

Channel &operator<<(const Message &msg);
Channel &operator>>(Message &msg);
bool tryRead(Message &msg);

private:
int _toChild[2];
int _toParent[2];
int _rfd;
int _wfd;

static void closeFd(int &fd);
};

} // namespace plazza
74 changes: 74 additions & 0 deletions src/Logger/Logger.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

#include <chrono>
#include <cstdint>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>

#include "Logger/Sequences.hpp"

enum level_t : uint8_t { L_DEBUG, L_LOG, L_WARN, L_ERROR, L_FATAL };

namespace Logger {

inline level_t &minLevel() {
static level_t level = L_DEBUG;
return level;
}

inline void setLevel(level_t level) { minLevel() = level; }

inline std::string timestamp() {
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()) %
1000;
std::ostringstream oss;
oss << std::put_time(std::localtime(&time), "%H:%M:%S");
oss << '.' << std::setfill('0') << std::setw(3) << ms.count();
return oss.str();
}

inline const char *levelTag(level_t level) {
switch (level) {
case L_DEBUG:
return PURPLE "DBG" RESET;
case L_LOG:
return BLUE "LOG" RESET;
case L_WARN:
return YELLOW "WRN" RESET;
case L_ERROR:
return RED "ERR" RESET;
case L_FATAL:
return BOLD RED "FTL" RESET;
}
return "???";
}

inline void print(level_t level, const char *file, int line, const char *msg) {
if (level < minLevel())
return;
const char *filename = file;
for (const char *p = file; *p; ++p)
if (*p == '/')
filename = p + 1;
std::cout << BLUE << timestamp() << RESET " [" << levelTag(level) << "] "
<< PURPLE << filename << ":" << line << RESET BOLD " - " RESET
<< msg << std::endl;
}

inline void print(level_t level, const char *file, int line,
const std::string &msg) {
print(level, file, line, msg.c_str());
}

} // namespace Logger

#define LOG_DEBUG(msg) Logger::print(L_DEBUG, __FILE__, __LINE__, msg)
#define LOG_INFO(msg) Logger::print(L_LOG, __FILE__, __LINE__, msg)
#define LOG_WARN(msg) Logger::print(L_WARN, __FILE__, __LINE__, msg)
#define LOG_ERROR(msg) Logger::print(L_ERROR, __FILE__, __LINE__, msg)
#define LOG_FATAL(msg) Logger::print(L_FATAL, __FILE__, __LINE__, msg)
14 changes: 14 additions & 0 deletions src/Logger/Sequences.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#define ESC "\033"
#define CFMT(n) ESC "[" #n "m"

#define RESET CFMT(0)
#define BOLD CFMT(1)

#define RED CFMT(31)
#define GREEN CFMT(32)
#define YELLOW CFMT(33)
#define BLUE CFMT(34)
#define PURPLE CFMT(35)
#define CYAN CFMT(36)
2 changes: 1 addition & 1 deletion src/Pizza/IPizza.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static inline std::map<Ingredients, std::string> ingredientsToString = {
namespace plazza {
class IPizza {
public:
IPizza(PizzaSize size){};
IPizza(PizzaSize size) {};
virtual ~IPizza() = default;

virtual PizzaSize getSize() const = 0;
Expand Down