18
18
*/
19
19
20
20
#include " WiFiClient.h"
21
+ #include " WiFi.h"
21
22
#include < lwip/sockets.h>
22
23
#include < lwip/netdb.h>
23
24
#include < errno.h>
30
31
#undef write
31
32
#undef read
32
33
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
+
33
146
class WiFiClientSocketHandle {
34
147
private:
35
148
int sockfd;
@@ -57,6 +170,7 @@ WiFiClient::WiFiClient():_connected(false),next(NULL)
57
170
WiFiClient::WiFiClient (int fd):_connected(true ),next(NULL )
58
171
{
59
172
clientSocketHandle.reset (new WiFiClientSocketHandle (fd));
173
+ _rxBuffer.reset (new WiFiClientRxBuffer (fd));
60
174
}
61
175
62
176
WiFiClient::~WiFiClient ()
@@ -68,13 +182,15 @@ WiFiClient & WiFiClient::operator=(const WiFiClient &other)
68
182
{
69
183
stop ();
70
184
clientSocketHandle = other.clientSocketHandle ;
185
+ _rxBuffer = other._rxBuffer ;
71
186
_connected = other._connected ;
72
187
return *this ;
73
188
}
74
189
75
190
void WiFiClient::stop ()
76
191
{
77
192
clientSocketHandle = NULL ;
193
+ _rxBuffer = NULL ;
78
194
_connected = false ;
79
195
}
80
196
@@ -99,18 +215,17 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
99
215
return 0 ;
100
216
}
101
217
clientSocketHandle.reset (new WiFiClientSocketHandle (sockfd));
218
+ _rxBuffer.reset (new WiFiClientRxBuffer (sockfd));
102
219
_connected = true ;
103
220
return 1 ;
104
221
}
105
222
106
223
int WiFiClient::connect (const char *host, uint16_t port)
107
224
{
108
- struct hostent *server;
109
- server = gethostbyname (host);
110
- if (server == NULL ) {
225
+ IPAddress srv ((uint32_t )0 );
226
+ if (!WiFiGenericClass::hostByName (host, srv)){
111
227
return 0 ;
112
228
}
113
- IPAddress srv ((const uint8_t *)(server->h_addr ));
114
229
return connect (srv, port);
115
230
}
116
231
@@ -241,13 +356,29 @@ size_t WiFiClient::write_P(PGM_P buf, size_t size)
241
356
return write (buf, size);
242
357
}
243
358
244
- int WiFiClient::read ( uint8_t *buf, size_t size )
359
+ size_t WiFiClient::write (Stream &stream )
245
360
{
246
- if (!available ()) {
247
- return -1 ;
361
+ uint8_t * buf = (uint8_t *)malloc (1360 );
362
+ if (!buf){
363
+ return 0 ;
248
364
}
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 ()) {
251
382
log_e (" %d" , errno);
252
383
stop ();
253
384
}
@@ -256,31 +387,25 @@ int WiFiClient::read(uint8_t *buf, size_t size)
256
387
257
388
int WiFiClient::peek ()
258
389
{
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 ()) {
265
392
log_e (" %d" , errno);
266
393
stop ();
267
394
}
268
- return data ;
395
+ return res ;
269
396
}
270
397
271
398
int WiFiClient::available ()
272
399
{
273
400
if (!_connected) {
274
401
return 0 ;
275
402
}
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 ()) {
279
405
log_e (" %d" , errno);
280
406
stop ();
281
- return 0 ;
282
407
}
283
- return count ;
408
+ return res ;
284
409
}
285
410
286
411
// Though flushing means to send all pending data,
@@ -313,22 +438,9 @@ uint8_t WiFiClient::connected()
313
438
if (_connected) {
314
439
uint8_t dummy;
315
440
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);
332
444
}
333
445
}
334
446
return _connected;
0 commit comments