-
Notifications
You must be signed in to change notification settings - Fork 7.5k
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
ESPLwIPClient::setTimeout conflict fix with Stream::setTimeout #6676
ESPLwIPClient::setTimeout conflict fix with Stream::setTimeout #6676
Conversation
@me-no-dev @igrr PTAL on these changes. |
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.
Just one note, LGTM otherwise.
Also please check if any examples used WifiClient::setTimeout and see if they should be updated to take milliseconds instead of seconds.
Checked and changed in this commit |
@@ -495,7 +495,7 @@ void HTTPClient::setTimeout(uint16_t timeout) | |||
{ | |||
_tcpTimeout = timeout; | |||
if(connected()) { | |||
_client->setTimeout((timeout + 500) / 1000); | |||
_client->setTimeout(timeout + 500); /* / 1000 removed, WifiClient setTimeout changed to ms */ |
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.
@P-R-O-C-H-Y I would suggest to put notes such as this into commit message body, instead of adding them as comments. The reader of the code is probably not interested in every change which has been done to each line, they just need to understand the final version. (If they are interested in change history, they can use git blame
and git log
and find the details in commit messages.)
For example, I don't understand why there is timeout+500 here.
I think previously +500 in (timeout + 500)/1000 was related to rounding. But with /1000 removed, looks like +500 is not needed anymore?
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.
Yes, this was there for rounding. +500
should be removed
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.
The rounding was removed, missed that.
Thanks for suggestions about commenting the code / commits. Will have it in mind for future changes :)
One more comment about leftover +500 and not using comments as a changelog. Otherwise still LGTM. |
So the titles says that you are fixing a conflict inheriting timeout between Stream and Client, but in the code I see |
I would like to understand SO_RCVTIMEO and SO_SNDTIMEO. Does it make WiFiClient read() and write() blocking? Is it good to have the same timeout for read() (which shouldn't block) as for Stream class's blocking functions (readBytes, parseInt, find) which internally use read()? |
Sorry I do not undestand something about this approach. What would be the correct way of setting the timeout now? I see you removed the setTimeout from WiFiClient and WiFiClientSecure... I'm currently using a MQTT Class that takes a Client inherited class (WiFiClient, WiFiClientSecure, etc) and when you start a MQTT Class object (mqttObject.connect()), it internally calls Client.connect() but without a timeout parameter (this is out of my control unless the author modifies this). If I loose the ability to set the timeout of my Client beforehand it can be problematic because the MQTT class does not call connect passing a timeout parameter. How this situation can be handled with your proposal? |
setTimeout was removed from WifiClient and WifiClientSecure, but you are still able to call setTimeout from base class Stream.h. I was testing the changes on HTTPClient where you cannot pass the timeout parameter and everything works. See example below.
|
Just want to mention, that the implementation is the same as it was before. This PR just resolves the conflict between the setTimeout functions. |
read() should only read what is immediately available in buffer. in embedded systems blocking can be a problem. |
Blocking is a terrible thing for an embedded system. However, P-R-O-C-H-Y 's change replicates the functionality in the previous function The change of timeout from seconds to ms is a breaking change. This needs significant testing before release. @P-R-O-C-H-Y Where is |
We are postponing this Pull Request as more investigation and testing is needed. Added to 2.1.0 milestone. |
Out of my tests setting the client, stream and/or SSL timeouts in ms is an easier way to set all timeouts to the same value. |
Such change will break ANY current library/sketch that sets the timeout in seconds. This API has been such for long time (probably coming from 8266 even). Even worst, it will break it in such way that probably none of the sketched will be able to even connect to anything (imagine having set a timeout of 5 seconds and that turns into 5ms after the change) |
Your right, Or m separate arguments for normal and unit values or by add an argument true/false... I'm still using now the old connect because of the older compability and set the settimeout before or after depending on the class I am using. |
ESP8266 implementation does call Client::setTimeout, which uses msec. On ESP32 it is IMHO done incorrect as it is effectively overriding the existing I'm not sure it will actually break existing implementations as I do expect almost anyone expects this to be in msec. |
relates #6835 |
@P-R-O-C-H-Y can you rebase this please |
+ unnecessary comments removed.
17adb9d
to
b986041
Compare
👋 Hello P-R-O-C-H-Y, we appreciate your contribution to this project! Click to see more instructions ...
Review and merge process you can expect ...
|
@me-no-dev I recommend my PR #8863 instead of this one |
@JAndrassy this PR solves a different thing, which is inheritance of |
so my PR renamed setTimeout to setConnectionTimeout. this one now removed setTimeout, and my PR adds it back as setConnectionTimeout. Except of WiFiClientSecure where this PR didn't remove the shadowing setTimeout so my PR still renames it to setConnectionTimeout. EDIT: sorry, I missed the _lastReadTimeout and _lastWriteTimeout. why was it in one PR? |
struct timeval timeout_tv; | ||
timeout_tv.tv_sec = _timeout / 1000; | ||
timeout_tv.tv_usec = (_timeout % 1000) * 1000; | ||
if(setSocketOption(SO_RCVTIMEO, (char *)&timeout_tv, sizeof(struct timeval)) >= 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.
Cosmethic change, but I suggest to use sizeof(timeout_tv)
instead of sizeof(struct timeval)
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.
I disagree, as it is good practice to actually use the struct/class for the sizeof()
instead of the object.
This way you are less likely to end up with the value 4
(or 8
when compiling for a 64-bit platform) as result of your sizeof()
call when working with pointers instead of reference.
Thus this will reduce the chance of programming errors.
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.
I agree, when it comes to pointers... but imagine you change the type of timeout_tv
somewhere earlier and forget to replace all sizeof (struct timeval)
occurences later in the code. Maybe a better thing is to declare a const variable/define/constexpr timeval_size just after the timeout_tv
declaration and then use this variable later in the code.
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.
Sure, or maybe there is a compiler flag which can warn when sizeof()
is given a pointer as that's the actual problem.
struct timeval timeout_tv; | ||
timeout_tv.tv_sec = _timeout / 1000; | ||
timeout_tv.tv_usec = (_timeout % 1000) * 1000; | ||
if(setSocketOption(SO_SNDTIMEO, (char *)&timeout_tv, sizeof(struct timeval)) >= 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.
Cosmethic change, but I suggest to use sizeof(timeout_tv) instead of sizeof(struct timeval)
struct timeval timeout_tv; | ||
timeout_tv.tv_sec = _timeout / 1000; | ||
timeout_tv.tv_usec = (_timeout % 1000) * 1000; | ||
if(setSocketOption(SO_RCVTIMEO, (char *)&timeout_tv, sizeof(struct timeval)) >= 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.
Cosmethic change, but I suggest to use sizeof(timeout_tv) instead of sizeof(struct timeval)
Description of Change
Arduino Stream::settimeout() is not virtual so it cannot be virtual in ESPLwIPClient.
This change should fix this conflict.
Tests scenarios
Related links
Closes #5558