1818*/
1919
2020#include " WiFiClient.h"
21+ #include " WiFi.h"
2122#include < lwip/sockets.h>
2223#include < lwip/netdb.h>
2324#include < errno.h>
3031#undef write
3132#undef read
3233
34+ class WiFiClientRxBuffer {
35+ private:
36+ size_t _size;
37+ uint8_t *_buffer;
38+ size_t _pos;
39+ size_t _fill;
40+ int _fd;
41+ bool _failed;
42+
43+ size_t r_available ()
44+ {
45+ if (_fd < 0 ){
46+ return 0 ;
47+ }
48+ int count;
49+ int res = lwip_ioctl_r (_fd, FIONREAD, &count);
50+ if (res < 0 ) {
51+ _failed = true ;
52+ return 0 ;
53+ }
54+ return count;
55+ }
56+
57+ size_t fillBuffer ()
58+ {
59+ if (!_buffer){
60+ _buffer = (uint8_t *)malloc (_size);
61+ }
62+ if (_fill && _pos == _fill){
63+ _fill = 0 ;
64+ _pos = 0 ;
65+ }
66+ if (!_buffer || _size <= _fill || !r_available ()) {
67+ return 0 ;
68+ }
69+ int res = recv (_fd, _buffer + _fill, _size - _fill, MSG_DONTWAIT);
70+ if (res < 0 && errno != EWOULDBLOCK) {
71+ _failed = true ;
72+ return 0 ;
73+ }
74+ _fill += res;
75+ return res;
76+ }
77+
78+ public:
79+ WiFiClientRxBuffer (int fd, size_t size=1436 )
80+ :_size(size)
81+ ,_buffer(NULL )
82+ ,_pos(0 )
83+ ,_fill(0 )
84+ ,_fd(fd)
85+ ,_failed(false )
86+ {
87+ // _buffer = (uint8_t *)malloc(_size);
88+ }
89+
90+ ~WiFiClientRxBuffer ()
91+ {
92+ free (_buffer);
93+ }
94+
95+ bool failed (){
96+ return _failed;
97+ }
98+
99+ int read (uint8_t * dst, size_t len){
100+ if (!dst || !len || (_pos == _fill && !fillBuffer ())){
101+ return -1 ;
102+ }
103+ size_t a = _fill - _pos;
104+ if (len <= a || ((len - a) <= (_size - _fill) && fillBuffer () >= (len - a))){
105+ if (len == 1 ){
106+ *dst = _buffer[_pos];
107+ } else {
108+ memcpy (dst, _buffer + _pos, len);
109+ }
110+ _pos += len;
111+ return len;
112+ }
113+ size_t left = len;
114+ size_t toRead = a;
115+ uint8_t * buf = dst;
116+ memcpy (buf, _buffer + _pos, toRead);
117+ _pos += toRead;
118+ left -= toRead;
119+ buf += toRead;
120+ while (left){
121+ if (!fillBuffer ()){
122+ return len - left;
123+ }
124+ a = _fill - _pos;
125+ toRead = (a > left)?left:a;
126+ memcpy (buf, _buffer + _pos, toRead);
127+ _pos += toRead;
128+ left -= toRead;
129+ buf += toRead;
130+ }
131+ return len;
132+ }
133+
134+ int peek (){
135+ if (_pos == _fill && !fillBuffer ()){
136+ return -1 ;
137+ }
138+ return _buffer[_pos];
139+ }
140+
141+ size_t available (){
142+ return _fill - _pos + r_available ();
143+ }
144+ };
145+
33146class WiFiClientSocketHandle {
34147private:
35148 int sockfd;
@@ -57,6 +170,7 @@ WiFiClient::WiFiClient():_connected(false),next(NULL)
57170WiFiClient::WiFiClient (int fd):_connected(true ),next(NULL )
58171{
59172 clientSocketHandle.reset (new WiFiClientSocketHandle (fd));
173+ _rxBuffer.reset (new WiFiClientRxBuffer (fd));
60174}
61175
62176WiFiClient::~WiFiClient ()
@@ -68,13 +182,15 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
68182{
69183 stop ();
70184 clientSocketHandle = other.clientSocketHandle ;
185+ _rxBuffer = other._rxBuffer ;
71186 _connected = other._connected ;
72187 return *this ;
73188}
74189
75190void WiFiClient::stop ()
76191{
77192 clientSocketHandle = NULL ;
193+ _rxBuffer = NULL ;
78194 _connected = false ;
79195}
80196
@@ -99,18 +215,17 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
99215 return 0 ;
100216 }
101217 clientSocketHandle.reset (new WiFiClientSocketHandle (sockfd));
218+ _rxBuffer.reset (new WiFiClientRxBuffer (sockfd));
102219 _connected = true ;
103220 return 1 ;
104221}
105222
106223int WiFiClient::connect (const char *host, uint16_t port)
107224{
108- struct hostent *server;
109- server = gethostbyname (host);
110- if (server == NULL ) {
225+ IPAddress srv ((uint32_t )0 );
226+ if (!WiFiGenericClass::hostByName (host, srv)){
111227 return 0 ;
112228 }
113- IPAddress srv ((const uint8_t *)(server->h_addr ));
114229 return connect (srv, port);
115230}
116231
@@ -241,13 +356,29 @@ size_t WiFiClient::write_P(PGM_P buf, size_t size)
241356 return write (buf, size);
242357}
243358
244- int WiFiClient::read ( uint8_t *buf, size_t size )
359+ size_t WiFiClient::write (Stream &stream )
245360{
246- if (!available ()) {
247- return -1 ;
361+ uint8_t * buf = (uint8_t *)malloc (1360 );
362+ if (!buf){
363+ return 0 ;
248364 }
249- int res = recv (fd (), buf, size, MSG_DONTWAIT);
250- if (res < 0 && errno != EWOULDBLOCK) {
365+ size_t toRead = 0 , toWrite = 0 , written = 0 ;
366+ size_t available = stream.available ();
367+ while (available){
368+ toRead = (available > 1360 )?1360 :available;
369+ toWrite = stream.readBytes (buf, toRead);
370+ written += write (buf, toWrite);
371+ available = stream.available ();
372+ }
373+ free (buf);
374+ return written;
375+ }
376+
377+ int WiFiClient::read (uint8_t *buf, size_t size)
378+ {
379+ int res = -1 ;
380+ res = _rxBuffer->read (buf, size);
381+ if (_rxBuffer->failed ()) {
251382 log_e (" %d" , errno);
252383 stop ();
253384 }
@@ -256,31 +387,25 @@ int WiFiClient::read(uint8_t *buf, size_t size)
256387
257388int WiFiClient::peek ()
258389{
259- if (!available ()) {
260- return -1 ;
261- }
262- uint8_t data = 0 ;
263- int res = recv (fd (), &data, 1 , MSG_PEEK);
264- if (res < 0 && errno != EWOULDBLOCK) {
390+ int res = _rxBuffer->peek ();
391+ if (_rxBuffer->failed ()) {
265392 log_e (" %d" , errno);
266393 stop ();
267394 }
268- return data ;
395+ return res ;
269396}
270397
271398int WiFiClient::available ()
272399{
273400 if (!_connected) {
274401 return 0 ;
275402 }
276- int count;
277- int res = lwip_ioctl_r (fd (), FIONREAD, &count);
278- if (res < 0 ) {
403+ int res = _rxBuffer->available ();
404+ if (_rxBuffer->failed ()) {
279405 log_e (" %d" , errno);
280406 stop ();
281- return 0 ;
282407 }
283- return count ;
408+ return res ;
284409}
285410
286411// Though flushing means to send all pending data,
@@ -313,22 +438,9 @@ uint8_t WiFiClient::connected()
313438 if (_connected) {
314439 uint8_t dummy;
315440 int res = recv (fd (), &dummy, 0 , MSG_DONTWAIT);
316- if (res <= 0 ) {
317- switch (errno) {
318- case ENOTCONN:
319- case EPIPE:
320- case ECONNRESET:
321- case ECONNREFUSED:
322- case ECONNABORTED:
323- _connected = false ;
324- break ;
325- default :
326- _connected = true ;
327- break ;
328- }
329- }
330- else {
331- _connected = true ;
441+ if (res <= 0 && errno != EWOULDBLOCK) {
442+ _connected = false ;
443+ log_i (" Disconnected: RES: %d, ERR: %d" , res, errno);
332444 }
333445 }
334446 return _connected;
0 commit comments