From cf96c7dae71540dd2fa3cec45ca096ac29f8d1c7 Mon Sep 17 00:00:00 2001 From: Brychan Dempsey Date: Thu, 7 Jan 2021 17:14:55 +1300 Subject: [PATCH] Moved data structures to arrays to minimise utilised memory Implemented UDPClient.Available() to avoid the blocking call to recvfrom (Closes #1) --- Simple DHCP Server (C++)/DHCP.cpp | 8 ++--- Simple DHCP Server (C++)/DHCP.h | 2 +- Simple DHCP Server (C++)/Net.cpp | 36 ++++++++++--------- Simple DHCP Server (C++)/Net.h | 19 ++++++++-- .../Simple DHCP Server (C++).cpp | 23 +++++++----- 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/Simple DHCP Server (C++)/DHCP.cpp b/Simple DHCP Server (C++)/DHCP.cpp index 4696b27..a3f838e 100644 --- a/Simple DHCP Server (C++)/DHCP.cpp +++ b/Simple DHCP Server (C++)/DHCP.cpp @@ -102,14 +102,14 @@ unsigned char DHCP::FindPosByMac(Net::MACAddress MAC, DHCP::DHCPEntry* entries, -std::vector> DHCP::ProcessDHCP(std::vector rxBuffer) { +std::vector> DHCP::ProcessDHCP(unsigned char* rxBuffer, unsigned long bufferLength) { unsigned char txBuffer[Net::TYPICAL_MTU] = {}; // ensure we have base zeros u_long destAddress = ULLONG_MAX; if (rxBuffer[236] == DHCP::MAGIC_COOKIE[0] && rxBuffer[237] == DHCP::MAGIC_COOKIE[1] && rxBuffer[238] == DHCP::MAGIC_COOKIE[2] && rxBuffer[239] == DHCP::MAGIC_COOKIE[3]) { unsigned int position = 240; // Find all options std::vector RXOptions; - while (rxBuffer[position] != 0xFF && position < Net::TYPICAL_MTU) { + while (rxBuffer[position] != 0xFF && position < bufferLength) { unsigned char option = rxBuffer[position++]; unsigned char dataLength = rxBuffer[position++]; DHCP::DHCPOption newOption = DHCP::DHCPOption(); @@ -124,7 +124,7 @@ std::vector> DHCP::ProcessDHCP(std::vector> DHCP::ProcessDHCP(std::vector Generate_DHCP_Option(unsigned char option, unsigned char clientIP); - std::vector> ProcessDHCP(std::vector rxBuffer); + std::vector> ProcessDHCP(unsigned char* rxBuffer, unsigned long bufferLength); DHCP(unsigned char* deviceAddress, unsigned char* subnetMask, unsigned char maxLeases, unsigned char leaseStart, unsigned int leaseTime, unsigned int* dnsServers, unsigned char dnsServerCount); ~DHCP(); diff --git a/Simple DHCP Server (C++)/Net.cpp b/Simple DHCP Server (C++)/Net.cpp index c6527a2..6af4ae4 100644 --- a/Simple DHCP Server (C++)/Net.cpp +++ b/Simple DHCP Server (C++)/Net.cpp @@ -69,29 +69,33 @@ void Net::UdpClient::Socket::Bind(unsigned char* IP, unsigned short Port) { Bind(ep); } -std::vector Net::UdpClient::Recieve(IPEndPoint* remote, unsigned short BufferSize) { - std::vector recievedBytes; +unsigned char* Net::UdpClient::Recieve(IPEndPoint* remote, unsigned short BufferSize) { char* buffer = new char[BufferSize]; - // As recvfrom is blocking, this space must be reserved in memory pretty much at all times(typically 1480 bytes) int remoteSize = sizeof(remote->socks); int r = recvfrom(Client.sock, buffer, BufferSize, 0, (SOCKADDR*)&remote->socks, &remoteSize); - if (r > 0) { - recievedBytes.resize(r); - for (int i = 0; i < r; i++) - { - recievedBytes[i] = buffer[i]; - } - } - delete[] buffer; - return recievedBytes; + return (unsigned char*)buffer; } -int Net::UdpClient::Send(std::vector Datagram, int dGramSize, IPEndPoint ep) { - return sendto(Client.sock, (char*)Datagram.data(), dGramSize, 0, (SOCKADDR*)&ep.socks, sizeof(ep.socks)); +int Net::UdpClient::Send(char* Datagram, short DatagramSize, IPEndPoint ep) { + return sendto(Client.sock, Datagram, DatagramSize, 0, (SOCKADDR*)&ep.socks, sizeof(ep.socks)); } -int Net::UdpClient::Send(std::vector Datagram, int dGramSize, std::vector DestinationIP, int DestPort) { +int Net::UdpClient::Send(std::vector Datagram, IPEndPoint ep) { + return Send((char*)Datagram.data(), Datagram.size(), ep); +} + +int Net::UdpClient::Send(std::vector Datagram, std::vector DestinationIP, int DestPort) { IPEndPoint ep = IPEndPoint(DestinationIP.data(), (u_short)DestPort); - return Send(Datagram, dGramSize, ep); + return Send(Datagram, ep); +} + +int Net::UdpClient::Available() +{ + unsigned long availableBytes = 0; + int result = ioctlsocket(Client.sock, FIONREAD, &availableBytes); + if (result != 0) { + // Error occured + } + return availableBytes; } Net::MACAddress::MACAddress(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5, unsigned char c6) diff --git a/Simple DHCP Server (C++)/Net.h b/Simple DHCP Server (C++)/Net.h index 4fcc9eb..9cd3549 100644 --- a/Simple DHCP Server (C++)/Net.h +++ b/Simple DHCP Server (C++)/Net.h @@ -44,10 +44,23 @@ public: Socket Client; UdpClient(); - std::vector Recieve(IPEndPoint* remote, unsigned short BufferSize = 1480); - int Send(std::vector Datagram, int dGramSize, IPEndPoint ep); + unsigned char* Recieve(IPEndPoint* remote, unsigned short BufferSize = 1480); + int Send(char* Datagram, short DatagramSize, IPEndPoint ep); - int Send(std::vector Datagram, int dGramSize, std::vector DestinationIP, int DestPort); + int Send(std::vector Datagram, IPEndPoint ep); + /// + /// Sends the data in Datagram to the destination IP address & port. + /// + /// A std::vector<u_char> of the data to be sent + /// The destination IP address (Little Endian) + /// The destination port (Little Endian) + /// A value less than zero if an error occured + int Send(std::vector Datagram, std::vector DestinationIP, int DestPort); + /// + /// Gets the amount of bytes available, or zero if no connection is yet available + /// + /// + int Available(); }; struct MACAddress { diff --git a/Simple DHCP Server (C++)/Simple DHCP Server (C++).cpp b/Simple DHCP Server (C++)/Simple DHCP Server (C++).cpp index 428f583..7117d2e 100644 --- a/Simple DHCP Server (C++)/Simple DHCP Server (C++).cpp +++ b/Simple DHCP Server (C++)/Simple DHCP Server (C++).cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "Net.h" #include "DHCP.h" @@ -18,17 +19,21 @@ int main() Net::UdpClient udpClient = Net::UdpClient(); udpClient.Client.Bind(Net::IPEndPoint(new unsigned char[] {dhcp.localAddress1, dhcp.localAddress2, dhcp.localAddress3, dhcp.deviceIP}, 67)); Net::IPEndPoint remote = Net::IPEndPoint(new unsigned char[] {0, 0, 0, 0}, 0); + unsigned long waitingBytes = 0; while (true) { - std::vector buffer = udpClient.Recieve(&remote, 1480); - std::vector> result = dhcp.ProcessDHCP(buffer); - if (result.size() == 2) { - if (remote.Address.Equals(Net::IPAddress::Empty())) { - udpClient.Send(result[1], result[1].size(), result[0], 68); - } - else { - udpClient.Send(result[1], result[1].size(), remote); + waitingBytes = udpClient.Available(); + if (waitingBytes > 240) { // DHCP requires *at least* 240 bytes, the packet is malformed or incorrect if it is less + std::vector> result = dhcp.ProcessDHCP(udpClient.Recieve(&remote, waitingBytes), waitingBytes); + if (result.size() == 2) { + if (remote.Address.Equals(Net::IPAddress::Empty())) { + udpClient.Send(result[1], result[0], 68); + } + else { + udpClient.Send(result[1], remote); + } } } - + // Artificial delay + std::this_thread::sleep_for(std::chrono::milliseconds(2)); } }