1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-06 05:21:22 +03:00

WiFiClient: add support for connect timeout

This commit is contained in:
Ivan Grokhotkov 2017-05-18 17:24:57 +08:00 committed by Ivan Grokhotkov
parent 2aeac91c90
commit eebcc656ed
2 changed files with 65 additions and 53 deletions

View File

@ -88,7 +88,7 @@ WiFiClient& WiFiClient::operator=(const WiFiClient& other)
int WiFiClient::connect(const char* host, uint16_t port) int WiFiClient::connect(const char* host, uint16_t port)
{ {
IPAddress remote_addr; IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr)) if (WiFi.hostByName(host, remote_addr, _timeout))
{ {
return connect(remote_addr, port); return connect(remote_addr, port);
} }
@ -122,37 +122,19 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
pcb->local_port = _localPort++; pcb->local_port = _localPort++;
} }
tcp_arg(pcb, this); _client = new ClientContext(pcb, nullptr, nullptr);
tcp_err(pcb, &WiFiClient::_s_err);
tcp_connect(pcb, &addr, port, reinterpret_cast<tcp_connected_fn>(&WiFiClient::_s_connected));
esp_yield();
if (_client)
return 1;
// if tcp_error was called, pcb has already been destroyed.
// tcp_abort(pcb);
return 0;
}
int8_t WiFiClient::_connected(void* pcb, int8_t err)
{
(void) err;
tcp_pcb* tpcb = reinterpret_cast<tcp_pcb*>(pcb);
_client = new ClientContext(tpcb, 0, 0);
_client->ref(); _client->ref();
esp_schedule(); _client->setTimeout(_timeout);
return ERR_OK; int res = _client->connect(&addr, port);
} if (res == 0) {
_client->unref();
_client = nullptr;
return 0;
}
void WiFiClient::_err(int8_t err) return 1;
{
(void) err;
DEBUGV(":err %d\r\n", err);
esp_schedule();
} }
void WiFiClient::setNoDelay(bool nodelay) { void WiFiClient::setNoDelay(bool nodelay) {
if (!_client) if (!_client)
return; return;
@ -331,16 +313,6 @@ uint16_t WiFiClient::localPort()
return _client->getLocalPort(); return _client->getLocalPort();
} }
int8_t WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
{
return reinterpret_cast<WiFiClient*>(arg)->_connected(tpcb, err);
}
void WiFiClient::_s_err(void* arg, int8_t err)
{
reinterpret_cast<WiFiClient*>(arg)->_err(err);
}
void WiFiClient::stopAll() void WiFiClient::stopAll()
{ {
for (WiFiClient* it = _s_first; it; it = it->_next) { for (WiFiClient* it = _s_first; it; it = it->_next) {

View File

@ -124,7 +124,25 @@ public:
} }
} }
size_t availableForWrite () int connect(ip_addr_t* addr, uint16_t port)
{
err_t err = tcp_connect(_pcb, addr, port, reinterpret_cast<tcp_connected_fn>(&ClientContext::_s_connected));
if (err != ERR_OK) {
return 0;
}
_connect_pending = 1;
_op_start_time = millis();
// This delay will be interrupted by esp_schedule in the connect callback
delay(_timeout_ms);
_connect_pending = 0;
if (state() != ESTABLISHED) {
abort();
return 0;
}
return 1;
}
size_t availableForWrite()
{ {
return _pcb? tcp_sndbuf(_pcb): 0; return _pcb? tcp_sndbuf(_pcb): 0;
} }
@ -149,14 +167,14 @@ public:
return tcp_nagle_disabled(_pcb); return tcp_nagle_disabled(_pcb);
} }
void setNonBlocking(bool nonblocking) void setTimeout(int timeout_ms)
{ {
_noblock = nonblocking; _timeout_ms = timeout_ms;
} }
bool getNonBlocking() int getTimeout()
{ {
return _noblock; return _timeout_ms;
} }
uint32_t getRemoteAddress() uint32_t getRemoteAddress()
@ -315,9 +333,14 @@ public:
protected: protected:
void _cancel_write() bool _is_timeout()
{ {
if (_send_waiting) { return millis() - _op_start_time > _timeout_ms;
}
void _notify_error()
{
if (_connect_pending || _send_waiting) {
esp_schedule(); esp_schedule();
} }
} }
@ -328,10 +351,11 @@ protected:
assert(_send_waiting == 0); assert(_send_waiting == 0);
_datasource = ds; _datasource = ds;
_written = 0; _written = 0;
_op_start_time = millis();
do { do {
_write_some(); _write_some();
if (!_datasource->available() || _noblock || state() == CLOSED) { if (!_datasource->available() || _is_timeout() || state() == CLOSED) {
delete _datasource; delete _datasource;
_datasource = nullptr; _datasource = nullptr;
break; break;
@ -431,7 +455,7 @@ protected:
(void) err; (void) err;
if(pb == 0) { // connection closed if(pb == 0) { // connection closed
DEBUGV(":rcl\r\n"); DEBUGV(":rcl\r\n");
_cancel_write(); _notify_error();
abort(); abort();
return ERR_ABRT; return ERR_ABRT;
} }
@ -456,7 +480,16 @@ protected:
tcp_recv(_pcb, NULL); tcp_recv(_pcb, NULL);
tcp_err(_pcb, NULL); tcp_err(_pcb, NULL);
_pcb = NULL; _pcb = NULL;
_cancel_write(); _notify_error();
}
int8_t _connected(void* pcb, int8_t err)
{
(void) err;
assert(pcb == _pcb);
assert(_connect_pending);
esp_schedule();
return ERR_OK;
} }
err_t _poll(tcp_pcb*) err_t _poll(tcp_pcb*)
@ -485,6 +518,11 @@ protected:
return reinterpret_cast<ClientContext*>(arg)->_sent(tpcb, len); return reinterpret_cast<ClientContext*>(arg)->_sent(tpcb, len);
} }
static int8_t _s_connected(void* arg, void* pcb, int8_t err)
{
return reinterpret_cast<ClientContext*>(arg)->_connected(pcb, err);
}
private: private:
tcp_pcb* _pcb; tcp_pcb* _pcb;
@ -494,14 +532,16 @@ private:
discard_cb_t _discard_cb; discard_cb_t _discard_cb;
void* _discard_cb_arg; void* _discard_cb_arg;
int _refcnt;
ClientContext* _next;
DataSource* _datasource = nullptr; DataSource* _datasource = nullptr;
size_t _written = 0; size_t _written = 0;
size_t _write_chunk_size = 256; size_t _write_chunk_size = 256;
bool _noblock = false; uint32_t _timeout_ms = 5000;
int _send_waiting = 0; uint32_t _op_start_time = 0;
uint8_t _send_waiting = 0;
uint8_t _connect_pending = 0;
int8_t _refcnt;
ClientContext* _next;
}; };
#endif//CLIENTCONTEXT_H #endif//CLIENTCONTEXT_H