-
Notifications
You must be signed in to change notification settings - Fork 13.3k
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
TCP keepalive(2h,75s,9) API + status helper + change/disable methods (not enabled by default) #3937
Conversation
void disableKeepAlive () { keepAlive(0, 0, 0); } | ||
|
||
static void setKeepAlive (void* pcb, uint16_t idle_sec, uint16_t intv_sec, uint8_t count); | ||
static void getKeepAlive (void* pcb, uint16_t* idle_sec, uint16_t* intv_sec, uint8_t* count); |
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.
How about moving these two into ClienContext? Exposing details such as pcb does not look right...
If you move it into ClienContext, then the first argument can also be changed from void* to tcp_pcb*.
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.
WiFiClient.cpp has <lwip/.h>
ClientContext has private _pcb
You make me realize that since ClientContext knows tcp_pcb, it has <lwip/.h> too.
will fix :)
@@ -31,6 +31,10 @@ extern "C" void esp_schedule(); | |||
|
|||
#include "DataSource.h" | |||
|
|||
#define TCP_DEFAULT_KEEPALIVE_IDLE_SEC 7200 // 2 hours | |||
#define TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC 75 // 75 sec | |||
#define TCP_DEFAULT_KEEPALIVE_COUNT 9 // fault after 9 failures |
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.
Do you think that releasing 2.4.0 with keepalives enabled by default, after two release candidates didn't have them, may cause some issues? How about adding methods to enable keepalives first, and then enable them by default after the release?
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 set up an example with 5s idle-keep-alive (default value is 2 hours), logs are:
16:41:47.308767 IP 10.43.1.163.23 > 10.43.1.254.51006: Flags [.], ack 28, win 2117, length 0
16:41:47.308797 IP 10.43.1.254.51006 > 10.43.1.163.23: Flags [.], ack 1, win 29200, length 0
16:41:52.808481 IP 10.43.1.163.23 > 10.43.1.254.51006: Flags [.], ack 28, win 2117, length 0
16:41:52.808512 IP 10.43.1.254.51006 > 10.43.1.163.23: Flags [.], ack 1, win 29200, length 0
.163 is esp with tcpserial example. We can see that tcp sends empty packets which are answered by peer. WiFiClient::connected()
will answer false once keep-alive-count
packets are not answered. Libraries and Sketchs already take care of ::connected()
result, so yes I think there will be no harm.
I understand and agree that we can never predict side effects. I made this PR so that #2750 can see and test, it can wait 2.5, or I can disable it by default for 2.4.
82b7d6e
to
7e607e5
Compare
keepalive PR is squash-updated |
_pcb->so_options &= ~SOF_KEEPALIVE; | ||
} | ||
|
||
void getKeepAlive (uint16_t* idle_sec, uint16_t* intv_sec, uint8_t* count) |
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.
Maybe use of references instead of pointers would be better here?
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 way with pointers let the user choose which value to get, like with gettimeofday(&tv, NULL)
we never want the second one. This can't be done with references
I put this getKeepAlive()
method mainly for the user to be informed if keep-alive is activated through WiFiClient::
since ClientContext
is not accessible.
I'm open to any other method than this one.
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 missed your original intent. In that case, I think I'd prefer three inline methods, one for each value, each returning the requested value, plus a 4th inline method that just returns the enabled flag as a bool, something along the lines of:
getKeepAliveCount()
getKeepAliveInterval()
getKeepAliveIdle()
isKeepAliveEnabled()
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.
Body could be like this:
return isKeepAliveEnabled() ? _pcb-> blah : 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.
keepalive-api is updated, PR squashed-rebased
@@ -325,6 +328,26 @@ class ClientContext | |||
return _write_from_source(new BufferedStreamDataSource<ProgmemStream>(stream, size)); | |||
} | |||
|
|||
void keepAlive (uint16_t idle_sec = TCP_DEFAULT_KEEPALIVE_IDLE_SEC, uint16_t intv_sec = TCP_DEFAULT_KEEPALIVE_INTERVAL_SEC, uint8_t count = TCP_DEFAULT_KEEPALIVE_COUNT) | |||
{ | |||
if (idle_sec && intv_sec && count) { |
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.
What happens if any 2 of the 3 values are non-zero? Are all combinations allowed?
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.
(mostly thinking of sanity checks, if necessary)
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.
any 0 is an invalid value for keep-alive api, so any 0 disables keep-alive.
void getKeepAlive (uint16_t* idle_sec, uint16_t* intv_sec, uint8_t* count) | ||
{ | ||
bool enabled = _pcb->so_options & SOF_KEEPALIVE; | ||
if (idle_sec) *idle_sec = enabled? (_pcb->keep_idle + 500) / 1000: 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.
Indentation (body of the if statement on a new line)
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.
function removed
@@ -30,6 +30,10 @@ | |||
|
|||
#define WIFICLIENT_MAX_PACKET_SIZE 1460 | |||
|
|||
#define TCP_DEFAULT_KEEPALIVE_IDLE_SEC 7200 // 2 hours |
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.
Do #defines count against available heap, or is it better to make these static const and put them in flash?
(I'm thinking of the free heap project, every byte counts)
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.
unlike static const
, #define
count for nothing in ram nor flash.
@d-a-v if you add the getter, I think this can be merged |
The getters are already present (I push-squashed to reduce the number of commits). |
@d-a-v isn't WiFiClient missing a getter isKeepAliveEnabled()? |
right, this is fixed |
uint16_t getKeepAliveIdle () const; | ||
uint16_t getKeepAliveInterval () const; | ||
uint8_t getKeepAliveCount () const; | ||
void disableKeepAlive () { keepAlive(0, 0, 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.
What about a getter for keepAliveEnabled?
bool isKeepAliveEnabled() {return _client->isKeepAliveEnabled();}
Still pending: verify if the defaults are ok, but that can be a different issue. |
Why isn't keepAlive enabled by default? |
Because we did not check all side effects yet.
keepAlive is for TCP stream (WiFiClient here). |
This is unrelated. This pull-request is about keep-alive TCP's feature, not connection type in HTTP header. |
(not yed automatic) tcp-keep-alive for all new connections with standard default values
#2750