3737#define FNTCP_SELECT_TIMEOUT_US (1000000 )
3838#define FNTCP_FLUSH_BUFFER_SIZE (1024 )
3939
40- class fnTcpClientRxBuffer
41- {
42- private:
43- size_t _size;
44- uint8_t *_buffer;
45- size_t _pos;
46- size_t _fill;
47- int _fd;
48- bool _failed;
49-
50- size_t r_available ()
51- {
52- if (_fd < 0 )
53- {
54- return 0 ;
55- }
56- #if defined(_WIN32)
57- unsigned long count;
58- int res = ioctlsocket (_fd, FIONREAD, &count);
59- if (res != 0 )
60- {
61- _failed = true ;
62- return 0 ;
63- }
64- #else
65- int count;
66- #ifdef ESP_PLATFORM
67- int res = lwip_ioctl (_fd, FIONREAD, &count);
68- #else
69- int res = ioctl (_fd, FIONREAD, &count);
70- #endif
71- if (res < 0 )
72- {
73- _failed = true ;
74- return 0 ;
75- }
76- #endif
77- return count;
78- }
79-
80- // Fill our buffer with data from the given socket descriptor
81- // Returns how much data was read
82- size_t fillBuffer ()
83- {
84- // Allocate space for the buffer if we haven't already
85- if (!_buffer)
86- {
87- _buffer = (uint8_t *)malloc (_size);
88- if (!_buffer)
89- {
90- Debug_printf (" Not enough memory to allocate buffer\r\n " );
91- _failed = true ;
92- return 0 ;
93- }
94- }
95-
96- if (_fill && _pos == _fill)
97- {
98- _fill = 0 ;
99- _pos = 0 ;
100- }
101-
102- if (!_buffer || _size <= _fill || !r_available ())
103- {
104- return 0 ;
105- }
106-
107- // Read the data
108- int res = recv (_fd, (char *)(_buffer + _fill), _size - _fill, MSG_DONTWAIT);
109- if (res < 0 )
110- {
111- int err = compat_getsockerr ();
112- #if defined(_WIN32)
113- if (err != WSAEWOULDBLOCK)
114- #else
115- if (err != EWOULDBLOCK)
116- #endif
117- {
118- _failed = true ;
119- }
120- return 0 ;
121- }
122- _fill += res;
123- return res;
124- }
125-
126- public:
127- fnTcpClientRxBuffer (int fd, size_t size = 1436 )
128- : _size(size), _buffer(NULL ), _pos(0 ), _fill(0 ), _fd(fd), _failed(false ) {}
129-
130- ~fnTcpClientRxBuffer () { free (_buffer); }
131-
132- bool failed () { return _failed; }
133-
134- // Read data and return how many bytes were read
135- int read (uint8_t *dst, size_t len)
136- {
137- // Fail if bad param or we're at the end of our buffer and couldn't get more data
138- if (!dst || !len || (_pos == _fill && !fillBuffer ()))
139- {
140- return -1 ;
141- }
142-
143- size_t a = _fill - _pos;
144- if (len <= a || ((len - a) <= (_size - _fill) && fillBuffer () >= (len - a)))
145- {
146- if (len == 1 )
147- {
148- *dst = _buffer[_pos];
149- }
150- else
151- {
152- memcpy (dst, _buffer + _pos, len);
153- }
154- _pos += len;
155- return len;
156- }
157-
158- size_t left = len;
159- size_t toRead = a;
160- uint8_t *buf = dst;
161- memcpy (buf, _buffer + _pos, toRead);
162- _pos += toRead;
163- left -= toRead;
164- buf += toRead;
165- while (left)
166- {
167- if (!fillBuffer ())
168- return len - left;
169-
170- a = _fill - _pos;
171- toRead = (a > left) ? left : a;
172- memcpy (buf, _buffer + _pos, toRead);
173- _pos += toRead;
174- left -= toRead;
175- buf += toRead;
176- }
177- return len;
178- }
179-
180- // Return value at current buffer position
181- int peek ()
182- {
183- // Return an error if we don't have any more data in our buffer and couldn't get more
184- if (_pos == _fill && !fillBuffer ())
185- return -1 ;
186-
187- return _buffer[_pos];
188- }
189-
190- size_t available ()
191- {
192- return _fill - _pos + r_available ();
193- }
194- };
195-
19640class fnTcpClientSocketHandle
19741{
19842private:
@@ -213,9 +57,10 @@ class fnTcpClientSocketHandle
21357
21458fnTcpClient::fnTcpClient (int fd)
21559{
60+ _fd = fd;
21661 _connected = true ;
217- _clientSocketHandle.reset (new fnTcpClientSocketHandle (fd ));
218- _rxBuffer.reset ( new fnTcpClientRxBuffer (fd) );
62+ _clientSocketHandle.reset (new fnTcpClientSocketHandle (_fd ));
63+ _rxBuffer.clear ( );
21964}
22065
22166fnTcpClient::~fnTcpClient ()
@@ -226,7 +71,6 @@ fnTcpClient::~fnTcpClient()
22671void fnTcpClient::stop ()
22772{
22873 _clientSocketHandle = nullptr ;
229- _rxBuffer = nullptr ;
23074 _connected = false ;
23175}
23276
@@ -357,7 +201,7 @@ int fnTcpClient::connect(in_addr_t ip, uint16_t port, int32_t timeout)
357201#endif
358202 // Create a socket handle and recieve buffer objects
359203 _clientSocketHandle.reset (new fnTcpClientSocketHandle (sockfd));
360- _rxBuffer.reset ( new fnTcpClientRxBuffer (sockfd) );
204+ _rxBuffer.clear ( );
361205 _connected = true ;
362206
363207 return 1 ;
@@ -529,14 +373,15 @@ size_t fnTcpClient::write(uint8_t data)
529373// Fill buffer with read data
530374int fnTcpClient::read (uint8_t *buf, size_t size)
531375{
532- int res = -1 ;
533- res = _rxBuffer->read (buf, size);
534- if (_rxBuffer->failed ())
376+ size_t rlen;
377+
378+ rlen = std::min (available (), size);
379+ if (rlen)
535380 {
536- Debug_printf ( " fail on fd %d, errno: %d, \" %s \"\r\n " , fd (), errno, strerror (errno) );
537- stop ( );
381+ memcpy (buf, _rxBuffer. data (), rlen );
382+ _rxBuffer. erase ( 0 , rlen );
538383 }
539- return res ;
384+ return rlen ;
540385}
541386
542387// Read one byte of data. Return read byte or negative value for error
@@ -571,28 +416,54 @@ int fnTcpClient::read_until(char terminator, char *buf, size_t size)
571416// Peek at next byte available for reading
572417int fnTcpClient::peek ()
573418{
574- int res = _rxBuffer->peek ();
575- if (_rxBuffer->failed ())
576- {
577- Debug_printf (" fail on fd %d, errno: %d, \" %s\"\r\n " , fd (), errno, strerror (errno));
578- stop ();
579- }
580- return res;
419+ if (_rxBuffer.size ())
420+ return _rxBuffer[0 ];
421+ return -1 ;
581422}
582423
583- // Return number of bytes available for reading
584- int fnTcpClient::available ()
424+ void fnTcpClient::updateFIFO ()
585425{
586- if (!_rxBuffer)
587- return 0 ;
426+ // check if socket is still connected
427+ if (!connected ())
428+ {
429+ // connection was closed or it has an error
430+ return ;
431+ }
432+
433+ #if defined(_WIN32)
434+ unsigned long count;
435+ int res = ioctlsocket (_fd, FIONREAD, &count);
436+ res = res != 0 ? -1 : count;
437+ #else
438+ int count;
439+ int res = ioctl (_fd, FIONREAD, &count);
440+ res = res < 0 ? -1 : count;
441+ #endif
588442
589- int res = _rxBuffer->available ();
590- if (_rxBuffer->failed ())
443+ if (res > 0 )
591444 {
592- Debug_printf (" fail on fd %d, errno: %d, \" %s\"\r\n " , fd (), errno, strerror (errno));
593- stop ();
445+ ssize_t result;
446+
447+ for (count = res; count; count -= result)
448+ {
449+ size_t old_len = _rxBuffer.size ();
450+ _rxBuffer.resize (old_len + count);
451+ result = recv (_fd, &_rxBuffer[old_len], count, 0 );
452+ if (result < 0 )
453+ result = 0 ;
454+ _rxBuffer.resize (old_len + result);
455+ }
456+
594457 }
595- return res;
458+
459+ return ;
460+ }
461+
462+ // Return number of bytes available for reading
463+ size_t fnTcpClient::available ()
464+ {
465+ updateFIFO ();
466+ return _rxBuffer.size ();
596467}
597468
598469// Send all pending data and clear receive buffer
0 commit comments