mirror of
https://github.com/Brychan22/Simple-DHCP-Server.git
synced 2025-02-13 00:08:55 +13:00
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:
parent
99a7014825
commit
cf96c7dae7
@ -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
|
||||
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<DHCP::DHCPOption> 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<std::vector<unsigned char>> DHCP::ProcessDHCP(std::vector<unsigned c
|
||||
}
|
||||
// Check first option is DHCP
|
||||
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 clientIP;
|
||||
if (leaseIndex == 255) {
|
||||
@ -146,7 +146,7 @@ std::vector<std::vector<unsigned char>> DHCP::ProcessDHCP(std::vector<unsigned c
|
||||
txBuffer[i] = rxBuffer[i];
|
||||
}
|
||||
// Clear the rxBuffer, we have read all we need
|
||||
rxBuffer.clear();
|
||||
delete[] rxBuffer;
|
||||
|
||||
txBuffer[16] = localAddress1;
|
||||
txBuffer[17] = localAddress2;
|
||||
|
@ -50,7 +50,7 @@ public:
|
||||
|
||||
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();
|
||||
|
@ -69,29 +69,33 @@ void Net::UdpClient::Socket::Bind(unsigned char* IP, unsigned short Port) {
|
||||
Bind(ep);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> Net::UdpClient::Recieve(IPEndPoint* remote, unsigned short BufferSize) {
|
||||
std::vector<unsigned char> 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<unsigned char> 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<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);
|
||||
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)
|
||||
|
@ -44,10 +44,23 @@ public:
|
||||
Socket Client;
|
||||
UdpClient();
|
||||
|
||||
std::vector<unsigned char> Recieve(IPEndPoint* remote, unsigned short BufferSize = 1480);
|
||||
int Send(std::vector<unsigned char> 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<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 & port.
|
||||
/// </summary>
|
||||
/// <param name="Datagram">A std::vector<u_char> 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 {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#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<unsigned char> buffer = udpClient.Recieve(&remote, 1480);
|
||||
std::vector<std::vector<unsigned char>> result = dhcp.ProcessDHCP(buffer);
|
||||
waitingBytes = udpClient.Available();
|
||||
if (waitingBytes > 240) { // DHCP requires *at least* 240 bytes, the packet is malformed or incorrect if it is less
|
||||
std::vector<std::vector<unsigned char>> result = dhcp.ProcessDHCP(udpClient.Recieve(&remote, waitingBytes), waitingBytes);
|
||||
if (result.size() == 2) {
|
||||
if (remote.Address.Equals(Net::IPAddress::Empty())) {
|
||||
udpClient.Send(result[1], result[1].size(), result[0], 68);
|
||||
udpClient.Send(result[1], result[0], 68);
|
||||
}
|
||||
else {
|
||||
udpClient.Send(result[1], result[1].size(), remote);
|
||||
udpClient.Send(result[1], remote);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Artificial delay
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user