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

Force socketFree() when the socket is remotely closed on Electron #885

Merged
merged 3 commits into from Mar 10, 2016

Conversation

@technobly
Copy link
Member

commented Feb 23, 2016

/*
 * Problem: On the Electron you can create TCP or UDP sockets and once you get to 7 total,
 * the socket_create() function won’t return valid handles.  This will not knock
 * the Electron off the cloud.  If you use disconnect from the cloud, then use up
 * all the sockets, then try to reconnect, it attempts to recover, can’t, so it
 * disconnects and resets the Cellular module which generates a URC for socket closed
 * remotely, but the system did not free up the sockets because they were never set
 * to a .connected status.  Each time the system then tries to allocate a new socket
 * for the Cloud, it finds that they are all in use so the system is stuck with all
 * sockets open (but not really, they were remotely closed).
 *
 * Solution: Force socketFree() when the socket is remotely closed.
 *
 * Test: disconnect from the Cloud, and use up all available sockets.  Then reconnect
 * and watch the system attempt to recover by power cycling the modem which causes
 * all sockets to be remotely disconnected.  They are freed and the Cloud socket can
 * be created and connected.
 */

See test app

@technobly technobly added this to the 0.5.x milestone Feb 23, 2016

@m-mcgowan

This comment has been minimized.

Copy link
Contributor

commented Feb 23, 2016

This is a perfect test to automate! Can you explain it to me? Looking at the test code, I'm a bit confused how the socket can be closed by the remote host, since the socket hasn't been connected.

@technobly

This comment has been minimized.

Copy link
Member Author

commented Feb 23, 2016

@m-mcgowan Sure! The idea is to use up all of the sockets fictitiously by just creating them, with no intension of using them. Then let the system try to connect to the Cloud. Under this case, it will need a socket, and none will be available. To recover currently it tries to "reboot" the networking device by power cycling it. This is gracefully handled with the cellular modem with AT commands. In that process of powering off, the modem must send some signal in the background that closes open sockets with the cellular network. The observed outcome of that is that we receive a remote socket closed URC, which we can use to fix up our locally stored "state" of the available sockets.

Feature: Cloud Socket

Background: A connected device

Scenario: The system will automatically recover and connect to the Cloud even when all TCP socket types are in use
Given the system is currently disconnected from the Cloud
When all available TCP sockets are created
And the system attempts to connect to the Cloud
Then the system overcomes this socket obstacle and connects to the Cloud

Scenario: The system will automatically recover and connect to the Cloud even when all UDP socket types are in use
Given the system is currently disconnected from the Cloud
When all available TCP sockets are created
And the system attempts to connect to the Cloud
Then the system overcomes this socket obstacle and connects to the Cloud

Scenario: The system will automatically recover and connect to the Cloud even when a mix of all sockets types are in use
Given the system is currently disconnected from the Cloud
When half of all available TCP sockets are created
And the remaining available UDP sockets are created
And the system attempts to connect to the Cloud
Then the system overcomes this socket obstacle and connects to the Cloud

@m-mcgowan

This comment has been minimized.

Copy link
Contributor

commented Feb 23, 2016

Thanks for the explanation - makes perfect sense! Great to start thinking about how we start implementing those tests. In fact, since the device does this standalone, we could in principle write them now in the no_fixture test suite.

The photon has different limits and behavior so some parts of this will be platform-specific. Even so, having this working on just the Electron would be a huge first step!

To start coding this in the no_fixture repo, we can take each step and code it as a function. E.g.

Given the system is currently disconnected from the Cloud
When all available TCP sockets are created
And the system attempts to connect to the Cloud
Then the system overcomes this socket obstacle and connects to the Cloud

void disconnec_from_cloud(system_tick_t timeout)
{
    Particle.disconnect();
    waitFor(Particle.disconnected, timeout);
}

void consume_all_tcp_sockets()
{
    while (!socket_create(....));   // create lots of sockets until failure
}

test(the_device_will_connect_to_the_cloud_when_all_tcp_sockets_are_consumed) {

//Given the system is currently disconnected from the Cloud
   connect_to_cloud(30*1000);

//When all available TCP sockets are created
   consume_tcp_sockets();

// And the system attempts to connect to the Cloud
   Particle.connect();

// Then the system overcomes this socket obstacle and connects to the Cloud
   waitFor(Particle.connected, 60*1000);   
}
adds socketfree tests to wiring/no_fixture/cellular.cpp
required for this to compile and run `git cherry-pick 3076956`
also will merge with cellular.cpp from feature/electron/localip
m-mcgowan added a commit that referenced this pull request Mar 10, 2016
Merge pull request #885 from spark/feature/electron/socketfree
Force socketFree() when the socket is remotely closed on Electron

@m-mcgowan m-mcgowan merged commit 992ea54 into develop Mar 10, 2016

2 checks passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details

@m-mcgowan m-mcgowan deleted the feature/electron/socketfree branch Sep 27, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.