From e6e1b811e720d871e4f5b7093ac59de6960240fa Mon Sep 17 00:00:00 2001 From: Valentin Alexeev Date: Thu, 24 Jan 2013 16:54:34 +0400 Subject: [PATCH] Feature: allow library user to provide callbacks for custom DHCP options. --- libraries/Ethernet/Dhcp.cpp | 39 +++++++++++++++++++++++++-------- libraries/Ethernet/Dhcp.h | 12 +++++++++- libraries/Ethernet/Ethernet.cpp | 9 ++++++-- libraries/Ethernet/Ethernet.h | 1 + 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/libraries/Ethernet/Dhcp.cpp b/libraries/Ethernet/Dhcp.cpp index 56d5b69516e..f06ced1085c 100755 --- a/libraries/Ethernet/Dhcp.cpp +++ b/libraries/Ethernet/Dhcp.cpp @@ -242,10 +242,16 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) buffer[5] = domainName; buffer[6] = dhcpT1value; buffer[7] = dhcpT2value; - buffer[8] = endOption; - + //put data in W5100 transmit buffer - _dhcpUdpSocket.write(buffer, 9); + _dhcpUdpSocket.write(buffer, 8); + + if (_optionProvider != NULL) { + // If we have a custom option provider - pass the socket to it. + (*_optionProvider)(messageType, &_dhcpUdpSocket); + } + + _dhcpUdpSocket.write(endOption); _dhcpUdpSocket.endPacket(); } @@ -254,6 +260,7 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr { uint8_t type = 0; uint8_t opt_len = 0; + uint8_t optionType = 0; unsigned long startTime = millis(); @@ -291,7 +298,8 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr while (_dhcpUdpSocket.available() > 0) { - switch (_dhcpUdpSocket.read()) + optionType = _dhcpUdpSocket.read(); + switch (optionType) { case endOption : break; @@ -364,11 +372,16 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr break; default : - opt_len = _dhcpUdpSocket.read(); - // Skip over the rest of this option - while (opt_len--) - { - _dhcpUdpSocket.read(); + if (_optionParser != NULL) { + // If we have a custom option parser - pass the value to it. + (*_optionParser)(optionType, &_dhcpUdpSocket); + } else { + opt_len = _dhcpUdpSocket.read(); + // Skip over the rest of this option + while (opt_len--) + { + _dhcpUdpSocket.read(); + } } break; } @@ -478,3 +491,11 @@ void DhcpClass::printByte(char * buf, uint8_t n ) { *str-- = c < 10 ? c + '0' : c + 'A' - 10; } while(n); } + +void DhcpClass::setOptionParser(DhcpOptionParser* parser) { + _optionParser = parser; +} + +void DhcpClass::setOptionProvider(DhcpOptionProvider* provider) { + _optionProvider = provider; +} diff --git a/libraries/Ethernet/Dhcp.h b/libraries/Ethernet/Dhcp.h index 4a47936f0f2..d8911ba6da2 100755 --- a/libraries/Ethernet/Dhcp.h +++ b/libraries/Ethernet/Dhcp.h @@ -115,7 +115,7 @@ enum dhcpMaxMsgSize = 57,*/ dhcpT1value = 58, dhcpT2value = 59, - /*dhcpClassIdentifier = 60,*/ + dhcpClassIdentifier = 60, dhcpClientIdentifier = 61, endOption = 255 }; @@ -136,6 +136,9 @@ typedef struct _RIP_MSG_FIXED uint8_t chaddr[6]; }RIP_MSG_FIXED; +typedef void (DhcpOptionParser)(uint8_t optionType, EthernetUDP *client); +typedef void (DhcpOptionProvider)(uint8_t messageType, EthernetUDP *client); + class DhcpClass { private: uint32_t _dhcpInitialTransactionId; @@ -156,6 +159,8 @@ class DhcpClass { unsigned long _secTimeout; uint8_t _dhcp_state; EthernetUDP _dhcpUdpSocket; + DhcpOptionProvider* _optionProvider; + DhcpOptionParser* _optionParser; int request_DHCP_lease(); void reset_DHCP_lease(); @@ -165,6 +170,8 @@ class DhcpClass { uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); public: + DhcpClass() : _optionParser(NULL), _optionProvider(NULL) {}; + IPAddress getLocalIp(); IPAddress getSubnetMask(); IPAddress getGatewayIp(); @@ -173,6 +180,9 @@ class DhcpClass { int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int checkLease(); + + void setOptionParser(DhcpOptionParser* optionParser); + void setOptionProvider(DhcpOptionProvider* optionProvider); }; #endif diff --git a/libraries/Ethernet/Ethernet.cpp b/libraries/Ethernet/Ethernet.cpp index c31a85f0936..e37b0e2c652 100644 --- a/libraries/Ethernet/Ethernet.cpp +++ b/libraries/Ethernet/Ethernet.cpp @@ -8,11 +8,12 @@ uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { 0, 0, 0, 0 }; -int EthernetClass::begin(uint8_t *mac_address) +int EthernetClass::begin(uint8_t *mac_address, DhcpOptionParser* optionParser, DhcpOptionProvider* optionProvider) { static DhcpClass s_dhcp; _dhcp = &s_dhcp; - + _dhcp->setOptionParser(optionParser); + _dhcp->setOptionProvider(optionProvider); // Initialise the basic info W5100.init(); @@ -34,6 +35,10 @@ int EthernetClass::begin(uint8_t *mac_address) return ret; } +int EthernetClass::begin(uint8_t *mac_address) { + return begin(mac_address, NULL, NULL); +} + void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip) { // Assume the DNS server will be the machine on the same network as the local IP diff --git a/libraries/Ethernet/Ethernet.h b/libraries/Ethernet/Ethernet.h index 2a07ff35f7f..12fc85f3cf6 100644 --- a/libraries/Ethernet/Ethernet.h +++ b/libraries/Ethernet/Ethernet.h @@ -21,6 +21,7 @@ class EthernetClass { // configuration through DHCP. // Returns 0 if the DHCP configuration failed, and 1 if it succeeded int begin(uint8_t *mac_address); + int begin(uint8_t *mac_address, DhcpOptionParser* parser, DhcpOptionProvider* provider); void begin(uint8_t *mac_address, IPAddress local_ip); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway);