Skip to content

Commit

Permalink
Fixed handling of upstream disconnects.
Browse files Browse the repository at this point in the history
# Changes
- Increased the socket receive timeout to better allow for variable data latency
- Increased the default connection timeout in the C++ client

# Fixes
- Fixed handling of upstream socket disconnects in POSIX (behavioral difference between POSIX and FreeRTOS)

Merge pull request #40.
  • Loading branch information
adamshapiro0 authored Apr 26, 2021
2 parents d5f1388 + dcf96f8 commit 673fbe9
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
48 changes: 37 additions & 11 deletions c/src/point_one/polaris/polaris.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,21 +490,41 @@ int Polaris_Work(PolarisContext_t* context) {
recv(context->socket, context->recv_buffer, POLARIS_RECV_BUFFER_SIZE, 0);
#endif

#ifdef P1_FREERTOS
// FreeRTOS does not use errno for recv() errors, but instead returns the
// equivalent error value. On a socket timeout, it returns 0 instead of
// ETIMEDOUT.
//
// We try to mimick the actual POSIX behavior to simplify the code below.
if (bytes_read == 0) {
bytes_read = -1;
errno = ETIMEDOUT;
} else if (bytes_read < 0) {
errno = (int)bytes_read;
}
#endif

if (bytes_read < 0) {
if (errno == EAGAIN || errno == ETIMEDOUT) {
P1_DebugPrint("Socket timed out.\n");
return 0;
} else {
P1_DebugPrint(
"Connection terminated. [ret=%d, errno=%d, "
"disconnected=%d]\n",
(int)bytes_read, errno, context->disconnected);
CloseSocket(context, 1);
// Typically ENOTCONN, but could be another error condition.
int ret;
if (context->disconnected) {
return 0;
P1_DebugPrint(
"Connection terminated by user request. [ret=%d, errno=%d]\n",
(int)bytes_read, errno);
ret = 0;
} else {
return POLARIS_CONNECTION_CLOSED;
P1_DebugPrint(
"Connection terminated upstream. [ret=%d, errno=%d]\n",
(int)bytes_read, errno);
ret = POLARIS_CONNECTION_CLOSED;
}

CloseSocket(context, 1);
return ret;
}
} else if (bytes_read == 0) {
// If recv() times out before we've gotten anything, the socket was probably
Expand All @@ -516,11 +536,17 @@ int Polaris_Work(PolarisContext_t* context) {
CloseSocket(context, 1);
return POLARIS_FORBIDDEN;
}
// Otherwise, there may just not be new data available (e.g., user hasn't
// sent a position yet, network connection temporarily broken, etc.).
// A 0 return means the socket had an "orderly shutdown", i.e., it was
// either closed by user request or disconnected upstream by the Polaris
// service.
else {
P1_DebugPrint("Received 0 bytes/socket timed out.\n");
return 0;
if (context->disconnected) {
P1_DebugPrint("Connection terminated by user request.\n");
} else {
P1_DebugPrint("Connection terminated upstream.\n");
}
CloseSocket(context, 1);
return POLARIS_CONNECTION_CLOSED;
}
} else {
P1_DebugPrint("Received %u bytes.\n", (unsigned)bytes_read);
Expand Down
2 changes: 1 addition & 1 deletion c/src/point_one/polaris/polaris.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
* single receive call (@ref Polaris_Work()).
*/
#ifndef POLARIS_RECV_TIMEOUT_MS
# define POLARIS_RECV_TIMEOUT_MS 1000
# define POLARIS_RECV_TIMEOUT_MS 5000
#endif

/**
Expand Down
4 changes: 2 additions & 2 deletions src/point_one/polaris/polaris_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class PolarisClient {

void RequestBeacon(const std::string& beacon_id);

void Run(double timeout_sec = 15.0);
void Run(double timeout_sec = 30.0);

void RunAsync(double timeout_sec = 15.0);
void RunAsync(double timeout_sec = 30.0);

void Disconnect();

Expand Down

0 comments on commit 673fbe9

Please sign in to comment.