Moved data structures to arrays to minimise utilised memory

Implemented UDPClient.Available() to avoid the blocking call to recvfrom (Closes #1)
This commit is contained in:
Brychan Dempsey 2021-01-07 17:14:55 +13:00
parent 99a7014825
commit cf96c7dae7
5 changed files with 55 additions and 33 deletions

View File

@ -102,14 +102,14 @@ unsigned char DHCP::FindPosByMac(Net::MACAddress MAC, DHCP::DHCPEntry* entries,
std::vector<std::vector<unsigned char>> DHCP::ProcessDHCP(std::vector<unsigned char> rxBuffer) { std::vector<std::vector<unsigned char>> DHCP::ProcessDHCP(unsigned char* rxBuffer, unsigned long bufferLength) {
unsigned char txBuffer[Net::TYPICAL_MTU] = {}; // ensure we have base zeros unsigned char txBuffer[Net::TYPICAL_MTU] = {}; // ensure we have base zeros
u_long destAddress = ULLONG_MAX; 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]) { 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; unsigned int position = 240;
// Find all options // Find all options
std::vector<DHCP::DHCPOption> RXOptions; std::vector<DHCP::DHCPOption> RXOptions;
while (rxBuffer[position] != 0xFF && position < Net::TYPICAL_MTU) { while (rxBuffer[position] != 0xFF && position < bufferLength) {
unsigned char option = rxBuffer[position++]; unsigned char option = rxBuffer[position++];
unsigned char dataLength = rxBuffer[position++]; unsigned char dataLength = rxBuffer[position++];
DHCP::DHCPOption newOption = DHCP::DHCPOption(); DHCP::DHCPOption newOption = DHCP::DHCPOption();
@ -124,7 +124,7 @@ std::vector<std::vector<unsigned char>> DHCP::ProcessDHCP(std::vector<unsigned c
} }
// Check first option is DHCP // Check first option is DHCP
if (RXOptions[0].option == 53) { if (RXOptions[0].option == 53) {
Net::MACAddress clientMAC = Net::MACAddress((rxBuffer.data() + 28)); Net::MACAddress clientMAC = Net::MACAddress((rxBuffer + 28));
unsigned char leaseIndex = DHCP::FindPosByMac(clientMAC, DHCPEntries, maxLeases); unsigned char leaseIndex = DHCP::FindPosByMac(clientMAC, DHCPEntries, maxLeases);
unsigned char clientIP; unsigned char clientIP;
if (leaseIndex == 255) { if (leaseIndex == 255) {
@ -146,7 +146,7 @@ std::vector<std::vector<unsigned char>> DHCP::ProcessDHCP(std::vector<unsigned c
txBuffer[i] = rxBuffer[i]; txBuffer[i] = rxBuffer[i];
} }
// Clear the rxBuffer, we have read all we need // Clear the rxBuffer, we have read all we need
rxBuffer.clear(); delete[] rxBuffer;
txBuffer[16] = localAddress1; txBuffer[16] = localAddress1;
txBuffer[17] = localAddress2; txBuffer[17] = localAddress2;

View File

@ -50,7 +50,7 @@ public:
std::vector<unsigned char> Generate_DHCP_Option(unsigned char option, unsigned char clientIP); std::vector<unsigned char> Generate_DHCP_Option(unsigned char option, unsigned char clientIP);
std::vector<std::vector<unsigned char>> ProcessDHCP(std::vector<unsigned char> rxBuffer); std::vector<std::vector<unsigned char>> 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(unsigned char* deviceAddress, unsigned char* subnetMask, unsigned char maxLeases, unsigned char leaseStart, unsigned int leaseTime, unsigned int* dnsServers, unsigned char dnsServerCount);
~DHCP(); ~DHCP();

View File

@ -69,29 +69,33 @@ void Net::UdpClient::Socket::Bind(unsigned char* IP, unsigned short Port) {
Bind(ep); Bind(ep);
} }
std::vector<unsigned char> Net::UdpClient::Recieve(IPEndPoint* remote, unsigned short BufferSize) { unsigned char* Net::UdpClient::Recieve(IPEndPoint* remote, unsigned short BufferSize) {
std::vector<unsigned char> recievedBytes;
char* buffer = new char[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 remoteSize = sizeof(remote->socks);
int r = recvfrom(Client.sock, buffer, BufferSize, 0, (SOCKADDR*)&remote->socks, &remoteSize); int r = recvfrom(Client.sock, buffer, BufferSize, 0, (SOCKADDR*)&remote->socks, &remoteSize);
if (r > 0) { return (unsigned char*)buffer;
recievedBytes.resize(r);
for (int i = 0; i < r; i++)
{
recievedBytes[i] = buffer[i];
}
}
delete[] buffer;
return recievedBytes;
} }
int Net::UdpClient::Send(std::vector<unsigned char> Datagram, int dGramSize, IPEndPoint ep) { int Net::UdpClient::Send(char* Datagram, short DatagramSize, IPEndPoint ep) {
return sendto(Client.sock, (char*)Datagram.data(), dGramSize, 0, (SOCKADDR*)&ep.socks, sizeof(ep.socks)); return sendto(Client.sock, Datagram, DatagramSize, 0, (SOCKADDR*)&ep.socks, sizeof(ep.socks));
} }
int Net::UdpClient::Send(std::vector<unsigned char> Datagram, int dGramSize, std::vector<unsigned char> DestinationIP, int DestPort) { int Net::UdpClient::Send(std::vector<unsigned char> Datagram, IPEndPoint ep) {
return Send((char*)Datagram.data(), Datagram.size(), ep);
}
int Net::UdpClient::Send(std::vector<unsigned char> Datagram, std::vector<unsigned char> DestinationIP, int DestPort) {
IPEndPoint ep = IPEndPoint(DestinationIP.data(), (u_short)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) Net::MACAddress::MACAddress(unsigned char c1, unsigned char c2, unsigned char c3, unsigned char c4, unsigned char c5, unsigned char c6)

View File

@ -44,10 +44,23 @@ public:
Socket Client; Socket Client;
UdpClient(); UdpClient();
std::vector<unsigned char> Recieve(IPEndPoint* remote, unsigned short BufferSize = 1480); unsigned char* Recieve(IPEndPoint* remote, unsigned short BufferSize = 1480);
int Send(std::vector<unsigned char> Datagram, int dGramSize, IPEndPoint ep); int Send(char* Datagram, short DatagramSize, IPEndPoint ep);
int Send(std::vector<unsigned char> Datagram, int dGramSize, std::vector<unsigned char> DestinationIP, int DestPort); int Send(std::vector<unsigned char> Datagram, IPEndPoint ep);
/// <summary>
/// Sends the data in Datagram to the destination IP address &amp; port.
/// </summary>
/// <param name="Datagram">A std::vector&lt;u_char&gt; of the data to be sent</param>
/// <param name="DestinationIP">The destination IP address (Little Endian)</param>
/// <param name="DestPort">The destination port (Little Endian)</param>
/// <returns>A value less than zero if an error occured</returns>
int Send(std::vector<unsigned char> Datagram, std::vector<unsigned char> DestinationIP, int DestPort);
/// <summary>
/// Gets the amount of bytes available, or zero if no connection is yet available
/// </summary>
/// <returns></returns>
int Available();
}; };
struct MACAddress { struct MACAddress {

View File

@ -3,6 +3,7 @@
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
#include <thread>
#include "Net.h" #include "Net.h"
#include "DHCP.h" #include "DHCP.h"
@ -18,17 +19,21 @@ int main()
Net::UdpClient udpClient = Net::UdpClient(); Net::UdpClient udpClient = Net::UdpClient();
udpClient.Client.Bind(Net::IPEndPoint(new unsigned char[] {dhcp.localAddress1, dhcp.localAddress2, dhcp.localAddress3, dhcp.deviceIP}, 67)); 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); Net::IPEndPoint remote = Net::IPEndPoint(new unsigned char[] {0, 0, 0, 0}, 0);
unsigned long waitingBytes = 0;
while (true) { while (true) {
std::vector<unsigned char> buffer = udpClient.Recieve(&remote, 1480); waitingBytes = udpClient.Available();
std::vector<std::vector<unsigned char>> result = dhcp.ProcessDHCP(buffer); if (waitingBytes > 240) { // DHCP requires *at least* 240 bytes, the packet is malformed or incorrect if it is less
if (result.size() == 2) { std::vector<std::vector<unsigned char>> result = dhcp.ProcessDHCP(udpClient.Recieve(&remote, waitingBytes), waitingBytes);
if (remote.Address.Equals(Net::IPAddress::Empty())) { if (result.size() == 2) {
udpClient.Send(result[1], result[1].size(), result[0], 68); if (remote.Address.Equals(Net::IPAddress::Empty())) {
} udpClient.Send(result[1], result[0], 68);
else { }
udpClient.Send(result[1], result[1].size(), remote); else {
udpClient.Send(result[1], remote);
}
} }
} }
// Artificial delay
std::this_thread::sleep_for(std::chrono::milliseconds(2));
} }
} }