From 0c49a541bab6338796165fdc48bdedd327d4f5d3 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Fri, 11 Dec 2020 20:54:11 +0100 Subject: [PATCH] Prototype implementation of TFTP PUT and move networking code to UpdateScreen (which runs on a different core) --- src/armc-cppstubs.cpp | 10 -- src/armc-cstubs.c | 7 + src/main.cpp | 96 +++++-------- src/net-ipv4.h | 7 + src/net-udp.h | 192 ++++++++++++++++++++++++++ src/net.cpp | 305 ++++++++++++++++++++++++++++++++++++++++-- src/net.h | 85 +++++------- 7 files changed, 562 insertions(+), 140 deletions(-) create mode 100644 src/net-udp.h diff --git a/src/armc-cppstubs.cpp b/src/armc-cppstubs.cpp index e1ea9c5..8a2a95f 100644 --- a/src/armc-cppstubs.cpp +++ b/src/armc-cppstubs.cpp @@ -30,13 +30,3 @@ void operator delete (void* ptr) free(ptr); } -namespace std -{ - void __throw_bad_alloc() - { - } - - void __throw_length_error(char const*e) - { - } -} \ No newline at end of file diff --git a/src/armc-cstubs.c b/src/armc-cstubs.c index 7b16f20..46a875f 100644 --- a/src/armc-cstubs.c +++ b/src/armc-cstubs.c @@ -179,6 +179,13 @@ int _lseek(int file, int ptr, int dir) /* Open a file. Minimal implementation: */ int open(const char *name, int flags, int mode) { + errno = ENOSYS; + return -1; +} + +int _open(const char *name, int flags, int mode) +{ + errno = ENOSYS; return -1; } diff --git a/src/main.cpp b/src/main.cpp index e1ac290..46350cd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -367,6 +367,35 @@ void InitialiseLCD() // printf("\E[1ALED %s%d\E[0m Motor %d Track %0d.%d ATN %d DAT %d CLK %d %s\r\n", LED ? termainalTextRed : termainalTextNormal, LED, Motor, Track >> 1, Track & 1 ? 5 : 0, ATN, DATA, CLOCK, roms.ROMNames[romIndex]); //} +void updateNetwork() +{ + size_t size; + uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE]; + if (!USPiEthernetAvailable() || !USPiReceiveFrame(ipBuffer, &size)) + { + return; + } + + auto header = EthernetFrameHeader::Deserialize(ipBuffer); + + static bool announcementSent = false; + if (!announcementSent) + { + SendArpAnnouncement(GetMacAddress(), Ipv4Address); + announcementSent = true; + } + + switch (header.type) + { + case ETHERTYPE_ARP: + HandleArpFrame(ipBuffer); + break; + case ETHERTYPE_IPV4: + HandleIpv4Frame(ipBuffer); + break; + } +} + // This runs on core0 and frees up core1 to just run the emulator. // Care must be taken not to crowd out the shared cache with core1 as this could slow down core1 so that it no longer can perform its duties in the 1us timings it requires. void UpdateScreen() @@ -630,6 +659,8 @@ void UpdateScreen() //if (options.GetSupportUARTInput()) // UpdateUartControls(refreshUartStatusDisplay, oldLED, oldMotor, oldATN, oldDATA, oldCLOCK, oldTrack, romIndex); + + updateNetwork(); // Go back to sleep. The USB irq will wake us up again. __asm ("WFE"); @@ -1911,7 +1942,6 @@ extern "C" InitialiseLCD(); #if not defined(EXPERIMENTALZERO) - int y_pos = 184; snprintf(tempBuffer, tempBufferSize, "Copyright(C) 2018 Stephen White"); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); snprintf(tempBuffer, tempBufferSize, "This program comes with ABSOLUTELY NO WARRANTY."); @@ -1949,74 +1979,12 @@ extern "C" inputMappings = new InputMappings(); //USPiMouseRegisterStatusHandler(MouseHandler); - MsDelay(3000); while (!USPiEthernetAvailable()) { snprintf(tempBuffer, tempBufferSize, "Waiting for ethernet..."); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); - MsDelay(1000); + MsDelay(500); } - uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE]; - - if (USPiEthernetAvailable()) { - std::array macAddress; - USPiGetMACAddress(macAddress.data()); - - snprintf(tempBuffer, tempBufferSize, "Ethernet found"); - screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); - - // Send an ARP announcement - SendArpAnnouncement(macAddress, Ipv4Address); - - while (true) - { - size_t size; - if (!USPiReceiveFrame(ipBuffer, &size)) - { - /* - const auto targetIp = 0xC0A80128; - const auto targetMacIter = ArpTable.find(targetIp); - - if (targetMacIter != ArpTable.end()) - { - const auto targetMac = targetMacIter->second; - SendIcmpEchoRequest(targetMac, targetIp); - } - else - { - // Send an ARP request to find the MAC address belonging to this IP. - SendArpRequest(MacBroadcast, macAddress, targetIp, Ipv4Address); - } - */ - - MsDelay(100); - continue; - } - - auto header = EthernetFrameHeader::Deserialize(ipBuffer); - - snprintf( - tempBuffer, - tempBufferSize, - "Received frame of ethertype %04x", - header.type - ); - screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); - - if (header.type == ETHERTYPE_ARP) - { - HandleArpFrame(ipBuffer); - } - else if (header.type == ETHERTYPE_IPV4) - { - uint64_t debug = HandleIpv4Frame(ipBuffer); - snprintf(tempBuffer, tempBufferSize, "Debug: %016llx", debug); - screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); - } - } - } - - CheckOptions(); IEC_Bus::SetSplitIECLines(options.SplitIECLines()); diff --git a/src/net-ipv4.h b/src/net-ipv4.h index 12e8540..a79b871 100644 --- a/src/net-ipv4.h +++ b/src/net-ipv4.h @@ -4,6 +4,8 @@ enum IpProtocols { IP_PROTO_ICMP = 1, + IP_PROTO_TCP = 6, + IP_PROTO_UDP = 17, }; struct Ipv4Header @@ -42,6 +44,11 @@ struct Ipv4Header destinationIp(destinationIp) { } + + static constexpr size_t SerializedLength() + { + return sizeof(Ipv4Header); + } size_t Serialize(uint8_t* buffer) { diff --git a/src/net-udp.h b/src/net-udp.h new file mode 100644 index 0000000..56e1596 --- /dev/null +++ b/src/net-udp.h @@ -0,0 +1,192 @@ +#pragma once +#include + +enum TftpOperation +{ + TFTP_OP_READ_REQUEST = 1, + TFTP_OP_WRITE_REQUEST = 2, + TFTP_OP_DATA = 3, + TFTP_OP_ACKNOWLEDGEMENT = 4, + TFTP_OP_ERROR = 5, +}; + +struct UdpDatagramHeader +{ + std::uint16_t sourcePort; + std::uint16_t destinationPort; + std::uint16_t length; + std::uint16_t checksum; + + UdpDatagramHeader() {} + + UdpDatagramHeader(uint16_t sourcePort, uint16_t destinationPort, uint16_t length) : + sourcePort(sourcePort), + destinationPort(destinationPort), + length(length), + checksum(0) + {} + + static constexpr size_t SerializedLength() + { + return + sizeof(sourcePort) + + sizeof(destinationPort) + + sizeof(length) + + sizeof(checksum); + } + + size_t Serialize(uint8_t* buffer) + { + size_t i = 0; + buffer[i++] = sourcePort >> 8; + buffer[i++] = sourcePort; + buffer[i++] = destinationPort >> 8; + buffer[i++] = destinationPort; + buffer[i++] = length >> 8; + buffer[i++] = length; + buffer[i++] = checksum >> 8; + buffer[i++] = checksum; + return i; + } + + static UdpDatagramHeader Deserialize(const uint8_t* buffer) + { + UdpDatagramHeader self; + self.sourcePort = buffer[0] << 8 | buffer[1]; + self.destinationPort = buffer[2] << 8 | buffer[3]; + self.length = buffer[4] << 8 | buffer[5]; + self.checksum = buffer[6] << 8 | buffer[7]; + return self; + } +} __attribute__((packed)); + +template +struct UdpDatagram +{ + UdpDatagramHeader header; + T payload; + + UdpDatagram() {} + + UdpDatagram(uint16_t sourcePort, uint16_t destinationPort, T payload) : + header(sourcePort, destinationPort, sizeof(UdpDatagram)), + payload(payload) + {} +} __attribute__((packed)); + +struct TftpWriteReadRequestPacket +{ + uint16_t opcode; + std::string filename; + std::string mode; + + size_t SerializedLength() const { + return sizeof(opcode) + filename.size() + 1 + mode.size() + 1; + } + + size_t Serialize(uint8_t* buffer) const { + size_t i = 0; + buffer[i++] = opcode >> 8; + buffer[i++] = opcode; + + i += filename.copy(reinterpret_cast(buffer + i), filename.size()); + buffer[i++] = 0; + + i += mode.copy(reinterpret_cast(buffer + i), mode.size()); + buffer[i++] = 0; + + return i; + } + + static TftpWriteReadRequestPacket Deserialize(const uint8_t* buffer) { + TftpWriteReadRequestPacket self; + size_t i = 0; + + self.opcode = buffer[i] << 8 | buffer[i + 1]; + i += 2; + + self.filename = reinterpret_cast(buffer + i); + i += self.filename.size() + 1; + + self.mode = reinterpret_cast(buffer + i); + i += self.mode.size() + 1; + + return self; + } +}; + +struct TftpErrorPacket +{ + uint16_t opcode; + uint16_t errorCode; + std::string message; + + TftpErrorPacket() : opcode(TFTP_OP_ERROR) {} + TftpErrorPacket(uint16_t errorCode, std::string message) : + opcode(TFTP_OP_ERROR), errorCode(errorCode), message(message) + {} + + constexpr size_t SerializedLength() + { + return sizeof(opcode) + sizeof(errorCode) + message.size() + 1; + } + + size_t Serialize(uint8_t* buffer) const + { + size_t i = 0; + buffer[i++] = opcode >> 8; + buffer[i++] = opcode; + buffer[i++] = errorCode >> 8; + buffer[i++] = errorCode; + + i += message.copy(reinterpret_cast(buffer + i), message.size()); + buffer[i++] = 0; + + return i; + } +}; + +struct TftpAcknowledgementPacket +{ + uint16_t opcode; + uint16_t blockNumber; + + TftpAcknowledgementPacket() : opcode(TFTP_OP_ACKNOWLEDGEMENT) {} + + TftpAcknowledgementPacket(uint16_t blockNumber) : + opcode(TFTP_OP_ACKNOWLEDGEMENT), blockNumber(blockNumber) + {} + + constexpr size_t SerializedLength() + { + return sizeof(opcode) + sizeof(blockNumber); + } + + size_t Serialize(uint8_t* buffer) const + { + size_t i = 0; + buffer[i++] = opcode >> 8; + buffer[i++] = opcode; + buffer[i++] = blockNumber >> 8; + buffer[i++] = blockNumber; + return i; + } +}; + +struct TftpDataPacket +{ + uint16_t opcode; + uint16_t blockNumber; + std::vector data; + + TftpDataPacket() : opcode(TFTP_OP_DATA) {} + + static TftpDataPacket Deserialize(const uint8_t* buffer, size_t length) + { + TftpDataPacket self; + self.opcode = buffer[0] << 8 | buffer[1]; + self.blockNumber = buffer[2] << 8 | buffer[3]; + self.data = std::vector(buffer + 4, buffer + length); + return self; + } +}; diff --git a/src/net.cpp b/src/net.cpp index 62ade8e..2878d8d 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -3,9 +3,12 @@ #include "net-ipv4.h" #include "net-arp.h" #include "net-icmp.h" +#include "net-udp.h" #include "types.h" #include +#include +#include "ff.h" // // ARP @@ -79,23 +82,303 @@ void HandleArpFrame(uint8_t* buffer) // // IPv4 // -uint64_t HandleIpv4Frame(const uint8_t* buffer) +void HandleIpv4Frame(const uint8_t* buffer) { const auto frame = EthernetFrame::Deserialize(buffer); const auto header = frame.payload; - if (header.version != 4) return 0x4; - if (header.ihl != 5) return 0x8; // Not supported - if (header.destinationIp != Ipv4Address) return 0x10 | std::uint64_t{header.destinationIp} << 32; - if (header.fragmentOffset != 0) return 0x20; // TODO Support this + // Update ARP table + ArpTable.insert(std::make_pair(frame.payload.sourceIp, frame.header.macSource)); + + if (header.version != 4) return; + if (header.ihl != 5) return; // Not supported + if (header.destinationIp != Ipv4Address) return; + if (header.fragmentOffset != 0) return; // TODO Support this if (header.protocol == IP_PROTO_ICMP) { - return HandleIcmpFrame(buffer) | 0x2; + HandleIcmpFrame(buffer); + } + else if (header.protocol == IP_PROTO_UDP) + { + return HandleUdpFrame(buffer); } - return 0x0; } +// +// UDP +// +void HandleUdpFrame(const uint8_t* buffer) +{ + const auto frame = EthernetFrame>::Deserialize(buffer); + const auto header = frame.payload.payload; + + uint8_t* data = (uint8_t*)malloc(header.length); + memcpy( + data, + buffer + sizeof(EthernetFrameHeader) + sizeof(Ipv4Header) + sizeof(UdpDatagramHeader), + header.length + ); + + if (header.destinationPort == 69) // nice + { + HandleTftpDatagram( + frame.header, + frame.payload.header, + frame.payload.payload, + data + ); + } +} + +FIL tftpFp; +bool shouldReboot = false; +std::string tftpPrevCwd; + +void HandleTftpDatagram( + const EthernetFrameHeader ethernetReqHeader, + const Ipv4Header ipv4ReqHeader, + const UdpDatagramHeader udpReqHeader, + const uint8_t* data +) { + const auto opcode = data[0] << 8 | data[1]; + static auto currentBlockNumber = -1; + if (opcode == TFTP_OP_WRITE_REQUEST) + { + auto packet = TftpWriteReadRequestPacket::Deserialize(data); + if (packet.mode == "octet") + { + currentBlockNumber = 0; + + // Try opening the file + { + char cwd[256]; + f_getcwd(cwd, sizeof(cwd)); + tftpPrevCwd = cwd; + } + + auto separator = packet.filename.rfind('/', packet.filename.size()); + if (separator != std::string::npos) + { + auto path = "/" + packet.filename.substr(0, separator); + f_chdir(path.c_str()); + } + else + { + f_chdir("/"); + separator = 0; + } + + auto filename = packet.filename.substr(separator + 1); + const auto result = f_open(&tftpFp, filename.c_str(), FA_CREATE_ALWAYS | FA_WRITE); + if (result == FR_OK) + { + shouldReboot = + packet.filename == "kernel.img" || packet.filename == "options.txt"; + + TftpAcknowledgementPacket response(currentBlockNumber); + UdpDatagramHeader udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response.SerializedLength() + UdpDatagramHeader::SerializedLength() + ); + Ipv4Header ipv4RespHeader( + IP_PROTO_UDP, + Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4Header::SerializedLength() + ); + EthernetFrameHeader ethernetRespHeader( + ArpTable[ipv4RespHeader.destinationIp], + GetMacAddress(), + ETHERTYPE_IPV4 + ); + + size_t i = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + i += ethernetRespHeader.Serialize(buffer + i); + i += ipv4RespHeader.Serialize(buffer + i); + i += udpRespHeader.Serialize(buffer + i); + i += response.Serialize(buffer + i); + USPiSendFrame(buffer, i); + } + else + { + TftpErrorPacket response(0, "error opening target file"); + UdpDatagramHeader udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response.SerializedLength() + UdpDatagramHeader::SerializedLength() + ); + Ipv4Header ipv4RespHeader( + IP_PROTO_UDP, + Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4Header::SerializedLength() + ); + EthernetFrameHeader ethernetRespHeader( + ArpTable[ipv4RespHeader.destinationIp], + GetMacAddress(), + ETHERTYPE_IPV4 + ); + + size_t i = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + i += ethernetRespHeader.Serialize(buffer + i); + i += ipv4RespHeader.Serialize(buffer + i); + i += udpRespHeader.Serialize(buffer + i); + i += response.Serialize(buffer + i); + USPiSendFrame(buffer, i); + } + } + else + { + TftpErrorPacket response(0, "please use mode octet"); + UdpDatagramHeader udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response.SerializedLength() + UdpDatagramHeader::SerializedLength() + ); + Ipv4Header ipv4RespHeader( + IP_PROTO_UDP, + Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4Header::SerializedLength() + ); + EthernetFrameHeader ethernetRespHeader( + ArpTable[ipv4RespHeader.destinationIp], + GetMacAddress(), + ETHERTYPE_IPV4 + ); + + size_t i = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + i += ethernetRespHeader.Serialize(buffer + i); + i += ipv4RespHeader.Serialize(buffer + i); + i += udpRespHeader.Serialize(buffer + i); + i += response.Serialize(buffer + i); + USPiSendFrame(buffer, i); + } + } + else if (opcode == TFTP_OP_DATA) + { + auto packet = TftpDataPacket::Deserialize( + data, + udpReqHeader.length - UdpDatagramHeader::SerializedLength() + ); + + if (packet.blockNumber == currentBlockNumber + 1) + { + const auto last = packet.data.size() < 512; + currentBlockNumber = packet.blockNumber; + + unsigned int bytesWritten; + const auto response = + f_write(&tftpFp, packet.data.data(), packet.data.size(), &bytesWritten); + if (response == FR_OK || bytesWritten != packet.data.size()) + { + TftpAcknowledgementPacket response(currentBlockNumber); + UdpDatagramHeader udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response.SerializedLength() + UdpDatagramHeader::SerializedLength() + ); + Ipv4Header ipv4RespHeader( + IP_PROTO_UDP, + Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4Header::SerializedLength() + ); + EthernetFrameHeader ethernetRespHeader( + ArpTable[ipv4RespHeader.destinationIp], + GetMacAddress(), + ETHERTYPE_IPV4 + ); + + size_t i = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + i += ethernetRespHeader.Serialize(buffer + i); + i += ipv4RespHeader.Serialize(buffer + i); + i += udpRespHeader.Serialize(buffer + i); + i += response.Serialize(buffer + i); + USPiSendFrame(buffer, i); + + if (last) + { + MsDelay(500); + f_close(&tftpFp); + f_chdir(tftpPrevCwd.c_str()); + tftpPrevCwd.clear(); + + if (shouldReboot) + { + // TODO eww + extern void Reboot_Pi(); + Reboot_Pi(); + } + } + } + else + { + f_close(&tftpFp); + + TftpErrorPacket response(0, "io error"); + UdpDatagramHeader udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response.SerializedLength() + UdpDatagramHeader::SerializedLength() + ); + Ipv4Header ipv4RespHeader( + IP_PROTO_UDP, + Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4Header::SerializedLength() + ); + EthernetFrameHeader ethernetRespHeader( + ArpTable[ipv4RespHeader.destinationIp], + GetMacAddress(), + ETHERTYPE_IPV4 + ); + + size_t i = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + i += ethernetRespHeader.Serialize(buffer + i); + i += ipv4RespHeader.Serialize(buffer + i); + i += udpRespHeader.Serialize(buffer + i); + i += response.Serialize(buffer + i); + USPiSendFrame(buffer, i); + } + } + else + { + TftpErrorPacket response(0, "invalid block number"); + UdpDatagramHeader udpRespHeader( + udpReqHeader.destinationPort, + udpReqHeader.sourcePort, + response.SerializedLength() + UdpDatagramHeader::SerializedLength() + ); + Ipv4Header ipv4RespHeader( + IP_PROTO_UDP, + Ipv4Address, + ipv4ReqHeader.sourceIp, + udpRespHeader.length + Ipv4Header::SerializedLength() + ); + EthernetFrameHeader ethernetRespHeader( + ArpTable[ipv4RespHeader.destinationIp], + GetMacAddress(), + ETHERTYPE_IPV4 + ); + + size_t i = 0; + uint8_t buffer[USPI_FRAME_BUFFER_SIZE]; + i += ethernetRespHeader.Serialize(buffer + i); + i += ipv4RespHeader.Serialize(buffer + i); + i += udpRespHeader.Serialize(buffer + i); + i += response.Serialize(buffer + i); + USPiSendFrame(buffer, i); + } + } +} // // ICMP @@ -115,7 +398,7 @@ void SendIcmpEchoRequest(MacAddress mac, uint32_t ip) USPiSendFrame(buffer, size); } -uint64_t HandleIcmpFrame(const uint8_t* buffer) +void HandleIcmpFrame(const uint8_t* buffer) { const auto frame = EthernetFrame>::Deserialize(buffer); const auto packetHeader = frame.payload.payload; @@ -125,7 +408,7 @@ uint64_t HandleIcmpFrame(const uint8_t* buffer) // TODO This should not be hardcoded lol typedef EthernetFrame>>> Frame; auto frameReq = Frame::Deserialize(buffer); - + auto echoReq = frameReq.payload.payload.payload; IcmpEchoResponse echoResp; @@ -154,10 +437,7 @@ uint64_t HandleIcmpFrame(const uint8_t* buffer) uint8_t bufferResp[USPI_FRAME_BUFFER_SIZE]; const auto size = frameResp.Serialize(bufferResp); USPiSendFrame(bufferResp, size); - - return 0x1; } - return 0x0 | std::uint64_t{packetHeader.type} << 32; } // @@ -278,4 +558,5 @@ MacAddress GetMacAddress() const uint32_t Ipv4Address = 0xC0A80164; const MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +bool FileUploaded = false; std::unordered_map ArpTable; diff --git a/src/net.h b/src/net.h index bb9c69a..5d157c2 100644 --- a/src/net.h +++ b/src/net.h @@ -17,6 +17,9 @@ enum ArpOperation { typedef std::array MacAddress; +// +// ARP +// void HandleArpFrame(uint8_t* buffer); void SendArpPacket(ArpOperation operation, MacAddress targetMac, @@ -33,11 +36,36 @@ void SendArpReply(MacAddress targetMac, uint32_t targetIp); void SendArpAnnouncement(MacAddress mac, uint32_t ip); -uint64_t HandleIpv4Frame(const uint8_t* buffer); +// +// IPv4 +// +void HandleIpv4Frame(const uint8_t* buffer); +// +// UDP +// +struct EthernetFrameHeader; +struct UdpDatagramHeader; +struct Ipv4Header; + +void HandleUdpFrame(const uint8_t* buffer); + +void HandleTftpDatagram( + const EthernetFrameHeader ethernetReqHeader, + const Ipv4Header ipv4ReqHeader, + const UdpDatagramHeader udpReqHeader, + const uint8_t* buffer +); + +// +// ICMP +// void SendIcmpEchoRequest(MacAddress mac, uint32_t ip); -uint64_t HandleIcmpFrame(const uint8_t* buffer); +void HandleIcmpFrame(const uint8_t* buffer); +// +// Helpers +// std::uint32_t Crc32(const std::uint8_t* buffer, std::size_t size); std::uint16_t InternetChecksum(const void* data, std::size_t size); MacAddress GetMacAddress(); @@ -45,56 +73,5 @@ MacAddress GetMacAddress(); extern const MacAddress MacBroadcast; extern const uint32_t Ipv4Address; +extern bool FileUploaded; extern std::unordered_map ArpTable; - -struct UdpDatagramHeader -{ - std::uint16_t sourcePort; - std::uint16_t destinationPort; - std::uint16_t length; - std::uint16_t checksum; - - UdpDatagramHeader() {} - - UdpDatagramHeader(uint16_t sourcePort, uint16_t destinationPort, uint16_t length) : - sourcePort(sourcePort), destinationPort(destinationPort), length(length) - {} - - size_t Serialize(uint8_t* buffer) - { - size_t i = 0; - buffer[i++] = sourcePort >> 8; - buffer[i++] = sourcePort; - buffer[i++] = destinationPort >> 8; - buffer[i++] = destinationPort; - buffer[i++] = length >> 8; - buffer[i++] = length; - buffer[i++] = checksum >> 8; - buffer[i++] = checksum; - return i; - } - - UdpDatagramHeader Deserialize(const uint8_t* buffer) - { - UdpDatagramHeader self; - self.sourcePort = buffer[0] << 8 | buffer[1]; - self.destinationPort = buffer[2] << 8 | buffer[3]; - self.length = buffer[4] << 8 | buffer[5]; - self.checksum = buffer[6] << 8 | buffer[7]; - return self; - } -}; - -template -struct UdpDatagram -{ - UdpDatagramHeader header; - T payload; - - UdpDatagram() {} - - UdpDatagram(uint16_t sourcePort, uint16_t destinationPort, T payload) : - header(sourcePort, destinationPort, sizeof(UdpDatagram)), - payload(payload) - {} -};