Skip to content
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

Merged
merged 3 commits into from
Jan 5, 2018

Conversation

d-a-v
Copy link
Collaborator

@d-a-v d-a-v commented Dec 8, 2017

(not yed automatic) tcp-keep-alive for all new connections with standard default values
#2750

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);
Copy link
Member

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*.

Copy link
Collaborator Author

@d-a-v d-a-v Dec 8, 2017

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
Copy link
Member

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?

Copy link
Collaborator Author

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.

@d-a-v d-a-v force-pushed the keepalive branch 2 times, most recently from 82b7d6e to 7e607e5 Compare December 8, 2017 18:18
@d-a-v
Copy link
Collaborator Author

d-a-v commented Dec 8, 2017

keepalive PR is squash-updated and still enabled by default.

@d-a-v d-a-v changed the title setup keepalive(2h,75s,9) by default + status helper + change/disable methods keepalive(2h,75s,9) API + status helper + change/disable methods (not enabled by default) Dec 8, 2017
_pcb->so_options &= ~SOF_KEEPALIVE;
}

void getKeepAlive (uint16_t* idle_sec, uint16_t* intv_sec, uint8_t* count)
Copy link
Collaborator

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?

Copy link
Collaborator Author

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.

Copy link
Collaborator

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()

Copy link
Collaborator

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;

Copy link
Collaborator Author

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) {
Copy link
Collaborator

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?

Copy link
Collaborator

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)

Copy link
Collaborator Author

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;
Copy link
Collaborator

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)

Copy link
Collaborator Author

@d-a-v d-a-v Dec 12, 2017

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
Copy link
Collaborator

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)

Copy link
Collaborator Author

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.

@devyte
Copy link
Collaborator

devyte commented Jan 2, 2018

@d-a-v if you add the getter, I think this can be merged

@d-a-v
Copy link
Collaborator Author

d-a-v commented Jan 2, 2018

The getters are already present (I push-squashed to reduce the number of commits).
But now we are at pre-2.5, should'nt we enable keepalive by default ?
The default idle value is 2h, It could be 10s (it sends empty packets).
Regarding #2330 what good value could we use for a good start ?

@devyte
Copy link
Collaborator

devyte commented Jan 2, 2018

@d-a-v isn't WiFiClient missing a getter isKeepAliveEnabled()?

@d-a-v
Copy link
Collaborator Author

d-a-v commented Jan 2, 2018

right, this is fixed

uint16_t getKeepAliveIdle () const;
uint16_t getKeepAliveInterval () const;
uint8_t getKeepAliveCount () const;
void disableKeepAlive () { keepAlive(0, 0, 0); }
Copy link
Collaborator

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();}

@devyte
Copy link
Collaborator

devyte commented Jan 5, 2018

Still pending: verify if the defaults are ok, but that can be a different issue.

@devyte devyte merged commit 9cfbbc7 into esp8266:master Jan 5, 2018
@d-a-v d-a-v deleted the keepalive branch January 5, 2018 17:42
@devyte devyte mentioned this pull request Jan 7, 2018
incosystem pushed a commit to incosys/Arduino that referenced this pull request Jan 8, 2018
@Androbin
Copy link
Contributor

Androbin commented Sep 15, 2018

Why isn't keepAlive enabled by default?
And does WiFiServer support keepAlive?
(or ESP8266WebServer respectively)

@d-a-v
Copy link
Collaborator Author

d-a-v commented Sep 15, 2018

Why isn't keepAlive enabled by default?

Because we did not check all side effects yet.
But you can enable it as soon as you have a valid WiFiClient.

And does WiFiServer support keepAlive?

keepAlive is for TCP stream (WiFiClient here).
This is irrelevant for WiFiServer: WiFiServer is awaiting for those streams.

@d-a-v
Copy link
Collaborator Author

d-a-v commented Sep 15, 2018

This is unrelated. This pull-request is about keep-alive TCP's feature, not connection type in HTTP header.
Please open a new issue and fill the issue template.

@d-a-v d-a-v changed the title keepalive(2h,75s,9) API + status helper + change/disable methods (not enabled by default) TCP keepalive(2h,75s,9) API + status helper + change/disable methods (not enabled by default) Sep 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants