Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 20640e766e | |||
| 75563091c1 |
@@ -2,4 +2,3 @@
|
||||
.xmake
|
||||
build
|
||||
compile_commands.json
|
||||
ignore
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "packet_sniffer_cli.hpp"
|
||||
#include <boost/program_options/value_semantic.hpp>
|
||||
|
||||
PacketSnifferCli::PacketSnifferCli()
|
||||
: CliBase("Packet Sniffer Options")
|
||||
, ip_("")
|
||||
{
|
||||
}
|
||||
|
||||
void PacketSnifferCli::setupOptions()
|
||||
{
|
||||
// clang-format off
|
||||
desc_.add_options()
|
||||
("help,h", "Show help")
|
||||
("ip,H", withDefault(ip_, "<IP>"), "Local IPv4 to sniff (e.g. 192.168.1.42)")
|
||||
("mask,m", boost::program_options::value<bool>()->default_value(false)->implicit_value(true),
|
||||
"Mask IP addresses in output (demo)");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
std::string PacketSnifferCli::getIp() const
|
||||
{
|
||||
return vm_.at("ip").as<std::string>();
|
||||
}
|
||||
|
||||
bool PacketSnifferCli::isMaskEnabled() const
|
||||
{
|
||||
const auto it = vm_.find("mask");
|
||||
return (it != vm_.end()) ? it->second.as<bool>() : false;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "cli_base.hpp"
|
||||
#include "option_utils.hpp"
|
||||
#include <string>
|
||||
|
||||
class PacketSnifferCli : public CliBase, protected OptionUtils
|
||||
{
|
||||
public:
|
||||
PacketSnifferCli();
|
||||
|
||||
std::string getIp() const;
|
||||
bool isMaskEnabled() const;
|
||||
|
||||
protected:
|
||||
void setupOptions() override;
|
||||
|
||||
private:
|
||||
std::string ip_;
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "echo_client.hpp"
|
||||
#include <boost/asio/connect.hpp>
|
||||
|
||||
EchoClient::EchoClient(IoContext &io, std::string host, unsigned short port)
|
||||
: io_(io)
|
||||
, host_(std::move(host))
|
||||
, port_(port)
|
||||
, socket_(io_)
|
||||
{
|
||||
}
|
||||
|
||||
bool EchoClient::run(const std::string &message)
|
||||
{
|
||||
if (!connect()) {
|
||||
Logger::error("EchoClient: connect failed");
|
||||
return false;
|
||||
}
|
||||
const bool ok = send(message);
|
||||
close();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool EchoClient::connect()
|
||||
{
|
||||
try {
|
||||
boost::asio::ip::tcp::resolver resolver(io_);
|
||||
auto results = resolver.resolve(host_, std::to_string(port_));
|
||||
boost::asio::connect(socket_, results);
|
||||
Logger::info(
|
||||
"EchoClient: connected to " + host_ + ":" + std::to_string(port_)
|
||||
);
|
||||
return true;
|
||||
} catch (const std::exception &ex) {
|
||||
Logger::error(
|
||||
std::string("EchoClient: connect exception: ") + ex.what()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EchoClient::send(const std::string &message)
|
||||
{
|
||||
try {
|
||||
auto bytes = boost::asio::write(socket_, boost::asio::buffer(message));
|
||||
Logger::info("EchoClient: sent " + std::to_string(bytes) + " bytes");
|
||||
return true;
|
||||
} catch (const std::exception &ex) {
|
||||
Logger::error(std::string("EchoClient: send exception: ") + ex.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EchoClient::close()
|
||||
{
|
||||
ErrorCode ec;
|
||||
socket_.shutdown(TcpSocket::shutdown_both, ec);
|
||||
socket_.close(ec);
|
||||
Logger::info("EchoClient: connection closed");
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "aliases.hpp"
|
||||
#include "logger.hpp"
|
||||
#include <string>
|
||||
|
||||
class EchoClient final
|
||||
{
|
||||
public:
|
||||
EchoClient(IoContext &io, std::string host, unsigned short port);
|
||||
|
||||
bool run(const std::string &message);
|
||||
|
||||
private:
|
||||
bool connect();
|
||||
bool send(const std::string &message);
|
||||
void close();
|
||||
|
||||
private:
|
||||
IoContext &io_;
|
||||
std::string host_;
|
||||
unsigned short port_;
|
||||
TcpSocket socket_{io_};
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "echo_client_cli.hpp"
|
||||
#include <boost/program_options/value_semantic.hpp>
|
||||
|
||||
EchoClientCli::EchoClientCli()
|
||||
: CliBase("Echo Client Options")
|
||||
, host_("127.0.0.1")
|
||||
, port_(9000)
|
||||
, message_("Hello from client")
|
||||
{
|
||||
}
|
||||
|
||||
void EchoClientCli::setupOptions()
|
||||
{
|
||||
// clang-format off
|
||||
desc_.add_options()
|
||||
("help,h", "Show help")
|
||||
("host,H", withDefault(host_, "<HOST>"), "Server host (IP or DNS)")
|
||||
("port,p", withDefault(port_, "<PORT>"), "Server port")
|
||||
("message,m", withDefault(message_, "<TEXT>"), "Message to send");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
std::string EchoClientCli::getHost() const
|
||||
{
|
||||
return vm_.at("host").as<std::string>();
|
||||
}
|
||||
int EchoClientCli::getPort() const
|
||||
{
|
||||
return vm_.at("port").as<int>();
|
||||
}
|
||||
std::string EchoClientCli::getMessage() const
|
||||
{
|
||||
return vm_.at("message").as<std::string>();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "cli_base.hpp"
|
||||
#include "option_utils.hpp"
|
||||
#include <string>
|
||||
|
||||
class EchoClientCli : public CliBase, protected OptionUtils
|
||||
{
|
||||
public:
|
||||
EchoClientCli();
|
||||
|
||||
std::string getHost() const;
|
||||
int getPort() const;
|
||||
std::string getMessage() const;
|
||||
|
||||
protected:
|
||||
void setupOptions() override;
|
||||
|
||||
private:
|
||||
// defaults (used only to show defaults in help via withDefault)
|
||||
std::string host_;
|
||||
int port_;
|
||||
std::string message_;
|
||||
};
|
||||
@@ -1,29 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
// --- Error handling ---
|
||||
using ErrorCode = boost::system::error_code;
|
||||
|
||||
// --- Asio types ---
|
||||
// --- IO Context ---
|
||||
using IoContext = boost::asio::io_context;
|
||||
using SteadyTimer = boost::asio::steady_timer;
|
||||
|
||||
// --- Ip types ---
|
||||
using IpAddress = boost::asio::ip::address;
|
||||
|
||||
// --- TCP types ---
|
||||
// --- TCP ---
|
||||
using TcpSocket = boost::asio::ip::tcp::socket;
|
||||
using TcpAcceptor = boost::asio::ip::tcp::acceptor;
|
||||
using TcpEndpoint = boost::asio::ip::tcp::endpoint;
|
||||
|
||||
// --- UDP types ---
|
||||
// --- UDP (для DNS) ---
|
||||
using UdpSocket = boost::asio::ip::udp::socket;
|
||||
using UdpEndpoint = boost::asio::ip::udp::endpoint;
|
||||
|
||||
// --- Таймеры ---
|
||||
using SteadyTimer = boost::asio::steady_timer;
|
||||
|
||||
// --- Program options ---
|
||||
using OptionsDescription = boost::program_options::options_description;
|
||||
using VariablesMap = boost::program_options::variables_map;
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#include "session_base.hpp"
|
||||
#include "logger.hpp"
|
||||
#include <boost/asio/write.hpp>
|
||||
|
||||
SessionBase::SessionBase(TcpSocket socket)
|
||||
: socket_(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
void SessionBase::start()
|
||||
{
|
||||
doRead();
|
||||
}
|
||||
|
||||
void SessionBase::doRead()
|
||||
{
|
||||
using namespace boost::asio;
|
||||
|
||||
auto self = shared_from_this();
|
||||
|
||||
auto handler = [this, self](ErrorCode ec, std::size_t bytesTransferred) {
|
||||
onRead(ec, bytesTransferred);
|
||||
};
|
||||
|
||||
socket_.async_read_some(buffer(buffer_), handler);
|
||||
}
|
||||
|
||||
void SessionBase::onRead(ErrorCode ec, std::size_t bytesTransferred)
|
||||
{
|
||||
if (ec) {
|
||||
Logger::error("Read error: " + ec.message());
|
||||
return;
|
||||
}
|
||||
|
||||
std::string rawRequest(buffer_.data(), bytesTransferred);
|
||||
Logger::info("Received request:\n" + rawRequest);
|
||||
|
||||
try {
|
||||
handleRequest(rawRequest);
|
||||
} catch (const std::exception &ex) {
|
||||
Logger::error(std::string("Request handling failed: ") + ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void SessionBase::doWrite(const std::string &response)
|
||||
{
|
||||
using namespace boost::asio;
|
||||
|
||||
auto self = shared_from_this();
|
||||
auto onWriteHandler =
|
||||
[this, self](ErrorCode ec, std::size_t /*bytesTransferred*/) {
|
||||
if (ec) {
|
||||
Logger::error("Write error: " + ec.message());
|
||||
}
|
||||
|
||||
ErrorCode shutdownEc;
|
||||
if (socket_.shutdown(TcpSocket::shutdown_both, shutdownEc)) {
|
||||
Logger::warn("Shutdown error: " + shutdownEc.message());
|
||||
}
|
||||
|
||||
ErrorCode closeEc;
|
||||
if (socket_.close(closeEc)) {
|
||||
Logger::warn("Close error: " + closeEc.message());
|
||||
} else {
|
||||
Logger::info("Connection closed");
|
||||
}
|
||||
};
|
||||
|
||||
async_write(socket_, buffer(response), onWriteHandler);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "aliases.hpp"
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class SessionBase : public std::enable_shared_from_this<SessionBase>
|
||||
{
|
||||
public:
|
||||
explicit SessionBase(TcpSocket socket);
|
||||
virtual ~SessionBase() = default;
|
||||
|
||||
void start();
|
||||
|
||||
protected:
|
||||
virtual void handleRequest(const std::string_view rawRequest) = 0;
|
||||
|
||||
void doRead();
|
||||
void onRead(ErrorCode ec, std::size_t bytesTransferred);
|
||||
void doWrite(const std::string &response);
|
||||
|
||||
TcpSocket socket_;
|
||||
std::array<char, 8192> buffer_;
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "tcp_server_base.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
TcpServerBase::TcpServerBase(IoContext &io, unsigned short port)
|
||||
: acceptor_(io, TcpEndpoint(boost::asio::ip::tcp::v4(), port))
|
||||
{
|
||||
}
|
||||
|
||||
void TcpServerBase::start()
|
||||
{
|
||||
auto doAccept = [this]() {
|
||||
acceptor_.async_accept([this](ErrorCode ec, TcpSocket socket) {
|
||||
if (!ec) {
|
||||
Logger::info("New client connected");
|
||||
createSession(std::move(socket));
|
||||
} else {
|
||||
Logger::error("Accept error: " + ec.message());
|
||||
}
|
||||
start(); // continue accepting
|
||||
});
|
||||
};
|
||||
doAccept();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "aliases.hpp"
|
||||
|
||||
class TcpServerBase
|
||||
{
|
||||
public:
|
||||
TcpServerBase(IoContext &io, unsigned short port);
|
||||
virtual ~TcpServerBase() = default;
|
||||
|
||||
void start();
|
||||
|
||||
protected:
|
||||
virtual void createSession(TcpSocket socket) = 0;
|
||||
|
||||
TcpAcceptor acceptor_;
|
||||
};
|
||||
@@ -1,135 +0,0 @@
|
||||
#include "sniffer.hpp"
|
||||
#include "logger.hpp"
|
||||
#include <tins/tins.h>
|
||||
|
||||
Sniffer::Sniffer(std::string localIp, bool maskIp)
|
||||
: ip_(std::move(localIp))
|
||||
, mask_(maskIp)
|
||||
{
|
||||
}
|
||||
|
||||
int Sniffer::run()
|
||||
{
|
||||
const auto ifaceName = resolveIfaceNameByIp(ip_);
|
||||
|
||||
Tins::SnifferConfiguration cfg;
|
||||
cfg.set_promisc_mode(true);
|
||||
cfg.set_immediate_mode(true);
|
||||
|
||||
Tins::Sniffer sniffer(ifaceName, cfg);
|
||||
|
||||
auto running = [this] { return !stop_.load(std::memory_order_relaxed); };
|
||||
|
||||
auto handler = [&](Tins::PDU &pdu) -> bool {
|
||||
if (!running())
|
||||
return false;
|
||||
|
||||
std::string src, dst;
|
||||
const char *type = "OTHER";
|
||||
uint16_t sport = 0, dport = 0;
|
||||
|
||||
if (auto *arp = pdu.find_pdu<Tins::ARP>()) {
|
||||
src = arp->sender_ip_addr().to_string();
|
||||
dst = arp->target_ip_addr().to_string();
|
||||
type = "ARP";
|
||||
} else if (auto *ip4 = pdu.find_pdu<Tins::IP>()) {
|
||||
src = ip4->src_addr().to_string();
|
||||
dst = ip4->dst_addr().to_string();
|
||||
|
||||
if (auto *tcp = pdu.find_pdu<Tins::TCP>()) {
|
||||
type = "TCP";
|
||||
sport = tcp->sport();
|
||||
dport = tcp->dport();
|
||||
} else if (auto *udp = pdu.find_pdu<Tins::UDP>()) {
|
||||
type = "UDP";
|
||||
sport = udp->sport();
|
||||
dport = udp->dport();
|
||||
} else if (pdu.find_pdu<Tins::ICMP>()) {
|
||||
type = "ICMP";
|
||||
} else {
|
||||
type = "IP";
|
||||
}
|
||||
} else if (auto *ip6 = pdu.find_pdu<Tins::IPv6>()) {
|
||||
src = ip6->src_addr().to_string();
|
||||
dst = ip6->dst_addr().to_string();
|
||||
|
||||
if (auto *tcp = pdu.find_pdu<Tins::TCP>()) {
|
||||
type = "TCP";
|
||||
sport = tcp->sport();
|
||||
dport = tcp->dport();
|
||||
} else if (auto *udp = pdu.find_pdu<Tins::UDP>()) {
|
||||
type = "UDP";
|
||||
sport = udp->sport();
|
||||
dport = udp->dport();
|
||||
} else if (pdu.find_pdu<Tins::ICMPv6>()) {
|
||||
type = "ICMPv6";
|
||||
} else {
|
||||
type = "IPv6";
|
||||
}
|
||||
} else {
|
||||
Logger::info("(unknown src) -> (unknown dst) [OTHER]");
|
||||
return running();
|
||||
}
|
||||
|
||||
if (mask_) {
|
||||
src = hideHalf(src);
|
||||
dst = hideHalf(dst);
|
||||
}
|
||||
|
||||
printLine(src, dst, type, sport, dport);
|
||||
return running();
|
||||
};
|
||||
|
||||
sniffer.sniff_loop(handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Sniffer::stop()
|
||||
{
|
||||
stop_.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::string Sniffer::hideHalf(const std::string &s) const
|
||||
{
|
||||
if (s.empty()) {
|
||||
return s;
|
||||
}
|
||||
|
||||
const size_t n = s.size();
|
||||
const size_t hide = n / 2;
|
||||
const size_t keep = n - hide;
|
||||
std::string out = s.substr(0, keep);
|
||||
out.append(hide, '*');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string Sniffer::resolveIfaceNameByIp(const std::string &ip)
|
||||
{
|
||||
const Tins::IPv4Address want(ip);
|
||||
for (const auto &iface : Tins::NetworkInterface::all()) {
|
||||
const auto info = iface.addresses(); // .ip_addr/.netmask/...
|
||||
if (info.ip_addr == want) {
|
||||
return iface.name();
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("Interface with IP " + ip + " not found");
|
||||
}
|
||||
|
||||
void Sniffer::printLine(
|
||||
const std::string &src,
|
||||
const std::string &dst,
|
||||
const char *type,
|
||||
uint16_t sport,
|
||||
uint16_t dport
|
||||
)
|
||||
{
|
||||
if (sport || dport) {
|
||||
Logger::info(
|
||||
std::string(src) + ":" + std::to_string(sport) + " -> " + dst + ":"
|
||||
+ std::to_string(dport) + " [" + type + "]"
|
||||
);
|
||||
} else {
|
||||
Logger::info(std::string(src) + " -> " + dst + " [" + type + "]");
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class Sniffer
|
||||
{
|
||||
public:
|
||||
explicit Sniffer(std::string localIp, bool maskIp = false);
|
||||
|
||||
Sniffer(const Sniffer &) = delete;
|
||||
Sniffer &operator=(const Sniffer &) = delete;
|
||||
|
||||
std::string hideHalf(const std::string &s) const;
|
||||
|
||||
int run();
|
||||
void stop();
|
||||
|
||||
private:
|
||||
static std::string resolveIfaceNameByIp(const std::string &ip);
|
||||
static void printLine(
|
||||
const std::string &src,
|
||||
const std::string &dst,
|
||||
const char *type,
|
||||
uint16_t sport = 0,
|
||||
uint16_t dport = 0
|
||||
);
|
||||
|
||||
std::string ip_;
|
||||
std::atomic<bool> stop_{false};
|
||||
bool mask_{false};
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
#include "logger.hpp"
|
||||
#include "packet_sniffer_cli.hpp"
|
||||
#include "sniffer.hpp"
|
||||
#include <exception>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Logger::init(true);
|
||||
try {
|
||||
PacketSnifferCli cli;
|
||||
cli.parse(argc, argv);
|
||||
if (cli.isHelp()) {
|
||||
cli.printHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sniffer sniffer(cli.getIp(), cli.isMaskEnabled());
|
||||
return sniffer.run();
|
||||
} catch (const std::exception &ex) {
|
||||
Logger::fatal(ex.what());
|
||||
return 1;
|
||||
} catch (...) {
|
||||
Logger::fatal("unknown error");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "aliases.hpp"
|
||||
#include "echo_client.hpp"
|
||||
#include "echo_client_cli.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
EchoClientCli cli;
|
||||
cli.parse(argc, argv);
|
||||
if (cli.isHelp()) {
|
||||
cli.printHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Logger::init(true);
|
||||
|
||||
IoContext io;
|
||||
const std::string host = cli.getHost();
|
||||
const auto port = static_cast<unsigned short>(cli.getPort());
|
||||
const std::string message = cli.getMessage();
|
||||
|
||||
EchoClient client(io, host, port);
|
||||
const bool ok = client.run(message);
|
||||
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "aliases.hpp"
|
||||
#include "echo_server.hpp"
|
||||
#include "echo_server_cli.hpp"
|
||||
#include "logger.hpp"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
EchoServerCli cli;
|
||||
cli.parse(argc, argv);
|
||||
if (cli.isHelp()) {
|
||||
cli.printHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Logger::init(true);
|
||||
|
||||
IoContext io;
|
||||
const auto port = static_cast<unsigned short>(cli.getPort());
|
||||
EchoServer server(io, port);
|
||||
|
||||
Logger::info("EchoServer starting on port " + std::to_string(port));
|
||||
server.start();
|
||||
|
||||
io.run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "echo_server.hpp"
|
||||
#include "echo_session.hpp"
|
||||
|
||||
void EchoServer::createSession(TcpSocket socket)
|
||||
{
|
||||
auto session = std::make_shared<EchoSession>(std::move(socket));
|
||||
session->start();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_server_base.hpp"
|
||||
|
||||
class EchoServer final : public TcpServerBase
|
||||
{
|
||||
public:
|
||||
EchoServer(IoContext &io, unsigned short port)
|
||||
: TcpServerBase(io, port)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void createSession(TcpSocket socket) override;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "echo_server_cli.hpp"
|
||||
|
||||
EchoServerCli::EchoServerCli()
|
||||
: CliBase("Echo Server Options")
|
||||
, port_(9000)
|
||||
, address_("0.0.0.0")
|
||||
{
|
||||
}
|
||||
|
||||
void EchoServerCli::setupOptions()
|
||||
{
|
||||
// clang-format off
|
||||
desc_.add_options()
|
||||
("help,h", "Show help")
|
||||
("port,p", withDefault(port_, "<PORT>"), "Port to listen on")
|
||||
("address,a", withDefault(address_, "<ADDRESS>"), "Bind address (e.g. 0.0.0.0)");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
int EchoServerCli::getPort() const
|
||||
{
|
||||
return vm_.at("port").as<int>();
|
||||
}
|
||||
std::string EchoServerCli::getAddress() const
|
||||
{
|
||||
return vm_.at("address").as<std::string>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "cli_base.hpp"
|
||||
#include "option_utils.hpp"
|
||||
#include <string>
|
||||
|
||||
class EchoServerCli : public CliBase, protected OptionUtils
|
||||
{
|
||||
public:
|
||||
EchoServerCli();
|
||||
|
||||
int getPort() const;
|
||||
std::string getAddress() const;
|
||||
|
||||
protected:
|
||||
void setupOptions() override;
|
||||
|
||||
private:
|
||||
int port_;
|
||||
std::string address_;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "echo_session.hpp"
|
||||
#include "logger.hpp"
|
||||
#include <utility> // std::move
|
||||
|
||||
EchoSession::EchoSession(TcpSocket socket)
|
||||
: SessionBase(std::move(socket))
|
||||
{
|
||||
}
|
||||
|
||||
void EchoSession::handleRequest(const std::string_view rawRequest)
|
||||
{
|
||||
Logger::info(
|
||||
std::string("EchoSession received: ") + std::string(rawRequest)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "session_base.hpp"
|
||||
|
||||
class EchoSession final : public SessionBase
|
||||
{
|
||||
public:
|
||||
explicit EchoSession(TcpSocket socket);
|
||||
|
||||
protected:
|
||||
void handleRequest(const std::string_view rawRequest) override;
|
||||
};
|
||||
@@ -10,12 +10,20 @@ add_requires("cmake::Boost", {
|
||||
},
|
||||
})
|
||||
|
||||
add_requires("cmake::libtins", { alias = "libtins", system = true })
|
||||
|
||||
target "packet_sniffer"
|
||||
-- Echo server target
|
||||
target "echo_server"
|
||||
do
|
||||
set_kind "binary"
|
||||
add_files("src/main.cpp", "src/cli/*.cpp", "src/common/*.cpp", "src/core/*.cpp")
|
||||
add_includedirs("src", "src/cli", "src/common", "src/core", { public = true })
|
||||
add_packages("boost", "libtins")
|
||||
add_files("src/main/echo_server_main.cpp", "src/server/*.cpp", "src/session/*.cpp", "src/common/*.cpp")
|
||||
add_includedirs("src", "src/server", "src/session", "src/common", { public = true })
|
||||
add_packages "boost"
|
||||
end
|
||||
|
||||
-- Echo client target
|
||||
target "echo_client"
|
||||
do
|
||||
set_kind "binary"
|
||||
add_files("src/main/echo_client_main.cpp", "src/client/*.cpp", "src/session/*.cpp", "src/common/*.cpp")
|
||||
add_includedirs("src", "src/client", "src/session", "src/common", { public = true })
|
||||
add_packages "boost"
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user