-
Notifications
You must be signed in to change notification settings - Fork 3k
ESP8266 - fix send buffer exhaustion handling #9309
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -563,6 +563,7 @@ bool ESP8266::dns_lookup(const char *name, char *ip) | |
|
||
nsapi_error_t ESP8266::send(int id, const void *data, uint32_t amount) | ||
{ | ||
nsapi_error_t ret = NSAPI_ERROR_DEVICE_ERROR; | ||
// +CIPSEND supports up to 2048 bytes at a time | ||
// Data stream can be truncated | ||
if (amount > 2048 && _sock_i[id].proto == NSAPI_TCP) { | ||
|
@@ -576,31 +577,50 @@ nsapi_error_t ESP8266::send(int id, const void *data, uint32_t amount) | |
_smutex.lock(); | ||
set_timeout(ESP8266_SEND_TIMEOUT); | ||
_busy = false; | ||
if (_parser.send("AT+CIPSEND=%d,%lu", id, amount) | ||
&& _parser.recv(">") | ||
&& _parser.write((char *)data, (int)amount) >= 0 | ||
&& _parser.recv("SEND OK")) { | ||
// No flow control, data overrun is possible | ||
if (_serial_rts == NC) { | ||
while (_parser.process_oob()); // Drain USART receive register | ||
} | ||
_smutex.unlock(); | ||
return NSAPI_ERROR_OK; | ||
_error = false; | ||
if (!_parser.send("AT+CIPSEND=%d,%lu", id, amount)) { | ||
tr_debug("ESP8266::send(): AT+CIPSEND failed"); | ||
goto END; | ||
} | ||
if (_error) { | ||
_error = false; | ||
|
||
if(!_parser.recv(">")) { | ||
tr_debug("ESP8266::send(): didn't get \">\""); | ||
ret = NSAPI_ERROR_WOULD_BLOCK; | ||
goto END; | ||
} | ||
|
||
if (_parser.write((char *)data, (int)amount) >= 0 && _parser.recv("SEND OK")) { | ||
ret = NSAPI_ERROR_OK; | ||
} | ||
|
||
END: | ||
_process_oob(ESP8266_RECV_TIMEOUT, true); // Drain USART receive register to avoid data overrun | ||
|
||
// error hierarchy, from low to high | ||
if (_busy) { | ||
set_timeout(); | ||
_smutex.unlock(); | ||
tr_debug("returning WOULD_BLOCK"); | ||
return NSAPI_ERROR_WOULD_BLOCK; | ||
ret = NSAPI_ERROR_WOULD_BLOCK; | ||
tr_debug("ESP8266::send(): modem busy"); | ||
} | ||
|
||
if (ret == NSAPI_ERROR_DEVICE_ERROR) { | ||
ret = NSAPI_ERROR_WOULD_BLOCK; | ||
tr_debug("ESP8266::send(): send failed"); | ||
} | ||
|
||
if (_error) { | ||
ret = NSAPI_ERROR_CONNECTION_LOST; | ||
tr_debug("ESP8266::send(): connection disrupted"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this actually true? Should we test that socket is actually closed? We should know that, because OOBs are already handled. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That is done on the next if-clause.
From the documentation. So the question is can there occur an ERROR without socket being closed... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah.. true.. Thanks. |
||
} | ||
|
||
if (!_sock_i[id].open && ret != NSAPI_ERROR_OK) { | ||
ret = NSAPI_ERROR_CONNECTION_LOST; | ||
tr_debug("ESP8266::send(): socket closed abruptly"); | ||
} | ||
|
||
set_timeout(); | ||
_smutex.unlock(); | ||
|
||
return NSAPI_ERROR_DEVICE_ERROR; | ||
return ret; | ||
} | ||
|
||
void ESP8266::_oob_packet_hdlr() | ||
|
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.
Instead of using the goto statement, the ifs above could be transformed into an if - else if - else if structure.
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.
Duly noted, but I'll keep the original for now.
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 kind of like the
goto END
type of handling where we have multiple cases which all should lead to shared error handling.Its like
try { ... } catch { ... } finally { ... }
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.
In a previous life, I worked with
do { ... } while (false)
. I've always had mixed feelings about it.