-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Custom dhcp options #8571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom dhcp options #8571
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There are numbers of comments, sorry :]
More generally, you made your former #8451 more complex and ram consuming
by storing user data in a temporary place which is always / not dynamically allocated.
This comment I made was a proposal to keep with the initial simplicity of your original pull request, but with adding the same checks that you wrote several times in this pull request.
The benefit of the former one is simplicity and much more reducing ram consumption.
cores/esp8266/LwipDhcpServer.cpp
Outdated
Serial.print("OfferCode: "); | ||
Serial.println(String(offerCode)+offerContent); | ||
int sizeOfCustomOptions = strlen(dhcpCustomOffers); | ||
if (sizeOfCustomOptions + strlen(offerContent) + 1 < 100){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Constants are generally forbidden in any code.
In this case 100
must be replaced by sizeof(dhcpCustomOffers)
.
cores/esp8266/LwipDhcpServer.cpp
Outdated
uint16 DhcpServer::add_dhcps_custom_options(uint8 offerCode, char *offerContent) | ||
{ | ||
Serial.print("OfferCode: "); | ||
Serial.println(String(offerCode)+offerContent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and below, debug code must be optional with #if DHCPS_DEBUG
barriers and be using os_printf()
,
like in other places in this file.
cores/esp8266/LwipDhcpServer.cpp
Outdated
{ | ||
Serial.print("OfferCode: "); | ||
Serial.println(String(offerCode)+offerContent); | ||
int sizeOfCustomOptions = strlen(dhcpCustomOffers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This name is misleading: sizeof
generally means a constant which is the size of a type.
This name may be changed to lengthOfCustomOptions
.
cores/esp8266/LwipDhcpServer.cpp
Outdated
dhcpCustomOffers[sizeOfCustomOptions +1] = strlen(offerContent); | ||
for(int i = 0; i<(strlen(offerContent)); i++){ | ||
dhcpCustomOffers[sizeOfCustomOptions + 2 + i] = offerContent[i]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may simply want to use strcpy_P(&dhcpCustomOffers[sizeOfCustomOptions + 1], offerContent);
?
(using _P
so user input can be in flash with PROGMEM / PSTR)
cores/esp8266/LwipDhcpServer.cpp
Outdated
@@ -1591,3 +1594,51 @@ uint32 DhcpServer::dhcps_client_update(u8* bssid, struct ipv4_addr* ip) | |||
|
|||
return pdhcps_pool->ip.addr; | |||
} | |||
|
|||
uint16 DhcpServer::add_dhcps_custom_options(uint8 offerCode, char *offerContent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using int8
or int16
generates more code than int
on esp8266.
if 16 is important but not critical, we have int_fast16_t
.
https://en.cppreference.com/w/c/types/integer
const char*
is always preferred than char*
A comment may mention that the first bytes indicates the option length.
cores/esp8266/LwipDhcpServer.cpp
Outdated
{ | ||
for(uint16 i = 0; i < 100; i++){ | ||
dhcpCustomOffers[i] = '\0'; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
memset(dhcpCustomOffers, 0, sizeof(dhcpCustomOffers))
which is libc-optimized ?
cores/esp8266/LwipDhcpServer.cpp
Outdated
Serial.println(sizeOfCustomOptions); | ||
uint16 i = 0; | ||
while (i < sizeOfCustomOptions){ | ||
if((uint16(dhcpCustomOffers[i+1]) +1) < (uint16(312) - uint16(optptr - optionsStart))){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
casting to size_t
is more efficient (casting to 16 or 8 bits produces larger code).
cores/esp8266/LwipDhcpServer.cpp
Outdated
Serial.print("OfferCode: "); | ||
Serial.println(String(offerCode)+offerContent); | ||
int sizeOfCustomOptions = strlen(dhcpCustomOffers); | ||
if (sizeOfCustomOptions + strlen(offerContent) + 1 < 100){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strlen(offerContent)
seems to be invalid, since this is not a regular C-string.
Should it be offerContent[0]
instead ?
(= length of the DHCP option)
cores/esp8266/LwipDhcpServer.cpp
Outdated
Serial.println("DHCP: Made it into IF:"); | ||
Serial.println((uint16(312) - uint16(optptr - optionsStart))); | ||
for(int y = 0; y < uint16(dhcpCustomOffers[i+1]) + 2; y++){ | ||
*optptr++ = dhcpCustomOffers[i+y]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
memcpy(optptr, &dhcpCustomOffers[i+1], dhcpCustomOffers[i+1] + 1)
?
@d-a-v , Thanks so much for the detailed comments! You've got a great point that weak function was much simpler and resulted in less RAM for 99% of cases where this will not be used. My only thought was that it was less clear and inviting to only provide the weak function (users would really have to look closely to see this as an option), where adding the member functions makes it stand out a bit more that this functionality is available. This leads me to two questions:
I'm happy to proceed either way! |
@d-a-v , I revised this to simplify and allow just passing a pointer to the user custom options. Your thoughts? Should I continue down this path and potentially improve/optimize or revert back to the weak function option? |
5c: option content is u8, not string or char. yes, we have unsigned chars, but it is a different type from the compiler pov nonetheless. plus, like you said - if you struggle to find api user for you code, just use it internally where the options are applied? |
@mcspr From user code, I am able to successfully get this to work by calling Are you saying that I should change |
I am suggesting to take a look at existing options prepended inside of the class, and reference RFCs related to options and DHCP itself. Can we write it in a way useful for both? What happens if you get length wrong with the char string encoding? Why not something like vector instead of a fixed-size storage (struct Option { ... }, vector, etc.)? Also note that any option may appear only once https://datatracker.ietf.org/doc/html/rfc2131#section-4.1 |
@mcspr , I feel like I'm not sure where to go with this at this point. I could add more code to validate the custom user options by checking that each option is added only once and iterating through the user provided options to check them. But this would add a lot more complexity to this PR. Should we just leave it as it is now (it works) and allow the user to ensure correct options when/if they choose to use this feature? I don't mind adding the complexity to validate this, I just don't want to bloat the codebase beyond what's needed. Your thoughts? |
Let me write up my proposal as a patch, then. I feel like my comment was not clear enough. |
superseded by #8582 |
Re-write of the PR #8451 which adds class member functions to add custom DHCP options. There is function called add_dhcps_custom_options() which adds a DHCP option to a char[100] array. Everytime add_dhcps_custom_options() is called, the new option is appended to the char[100] array. There is also a remove_dhcps_custom_options() which clears all the options from the char[100] array.
Actually meant for this to be a DRAFT PR. I left
#include "Arduino.h"
and Serial.println's in there to assist with debugging, etc.