#include "net/etherframe.hpp"
#include "utils/conv.hpp"
#include <memory>
using namespace net;
EtherFrameHandler::EtherFrameHandler(EtherFrameProvider &backend,
std::uint16_t etherType)
: backend(backend), etherType(hton(etherType))
{
backend.handlers[this->etherType.BE] = this;
}
EtherFrameHandler::~EtherFrameHandler()
{
if (backend.handlers[etherType.BE] == this) {
backend.handlers[etherType.BE] = nullptr;
}
}
void
EtherFrameHandler::send(NetOrder<std::uint64_t> dstMAC,
span<const std::uint8_t> msg)
{
return backend.send(dstMAC, etherType, msg);
}
NetOrder<std::uint32_t>
EtherFrameHandler::getIPAddress() const
{
return backend.getIPAddress();
}
EtherFrameProvider::EtherFrameProvider(drv::EthernetDriver &backend)
: RawDataHandler(backend)
{
for (std::uint32_t i = 0; i < 65535; ++i) {
handlers[i] = 0;
}
}
bool
EtherFrameProvider::onRawDataReceived(span<std::uint8_t> msg)
{
if (msg.size() < EtherFrameHeader::size()) {
return false;
}
EtherFrameHeader frame(msg.data());
bool sendBack = false;
if (frame.dstMAC == broadcastMAC || frame.dstMAC == backend.getMAC()) {
if (EtherFrameHandler *handler = handlers[frame.etherType.BE]) {
sendBack = handler->onEtherFrameReceived(msg.after(frame.size()));
}
}
if (sendBack) {
frame.dstMAC = frame.srcMAC;
frame.srcMAC = backend.getMAC();
}
return sendBack;
}
void
EtherFrameProvider::send(NetOrder<std::uint64_t> dstMAC,
NetOrder<std::uint16_t> etherType,
span<const std::uint8_t> msg)
{
std::unique_ptr<std::uint8_t[]> buffer {
new std::uint8_t[EtherFrameHeader::size() + msg.size()]
};
EtherFrameHeader frame(buffer.get());
frame.dstMAC = dstMAC;
frame.srcMAC = backend.getMAC();
frame.etherType = etherType;
std::uint8_t *dst = buffer.get() + frame.size();
for (int i = 0; i < msg.size(); ++i) {
dst[i] = msg[i];
}
backend.send({ buffer.get(), msg.size() + frame.size() });
}
NetOrder<std::uint64_t>
EtherFrameProvider::getMACAddress() const
{
return backend.getMAC();
}
NetOrder<std::uint32_t>
EtherFrameProvider::getIPAddress() const
{
return backend.getIPAddress();
}
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master