@@ -52,15 +52,16 @@ uint8_t EthernetUDP::begin(uint16_t port) {
5252 return 0 ;
5353
5454 _port = port;
55+ _remaining = 0 ;
5556 socket (_sock, SnMR::UDP, _port, 0 );
5657
5758 return 1 ;
5859}
5960
60- /* Is data available in rx buffer? Returns 0 if no, number of available bytes if yes.
61- * returned value includes 8 byte UDP header! */
61+ /* return number of bytes available in the current packet,
62+ will return zero if parsePacket hasn't been called yet */
6263int EthernetUDP::available () {
63- return W5100. getRXReceivedSize (_sock) ;
64+ return _remaining ;
6465}
6566
6667/* Release any resources being used by this EthernetUDP instance */
@@ -116,20 +117,26 @@ size_t EthernetUDP::write(const uint8_t *buffer, size_t size)
116117
117118int EthernetUDP::parsePacket ()
118119{
119- if (available () > 0 )
120+ // discard any remaining bytes in the last packet
121+ flush ();
122+
123+ if (W5100.getRXReceivedSize (_sock) > 0 )
120124 {
121125 // HACK - hand-parse the UDP packet using TCP recv method
122126 uint8_t tmpBuf[8 ];
123- int ret =0 ;
127+ int ret =0 ;
124128 // read 8 header bytes and get IP and port from it
125129 ret = recv (_sock,tmpBuf,8 );
126130 if (ret > 0 )
127131 {
128132 _remoteIP = tmpBuf;
129133 _remotePort = tmpBuf[4 ];
130134 _remotePort = (_remotePort << 8 ) + tmpBuf[5 ];
135+ _remaining = tmpBuf[6 ];
136+ _remaining = (_remaining << 8 ) + tmpBuf[7 ];
137+
131138 // When we get here, any remaining bytes are the data
132- ret = available () ;
139+ ret = _remaining ;
133140 }
134141 return ret;
135142 }
@@ -140,42 +147,70 @@ int EthernetUDP::parsePacket()
140147int EthernetUDP::read ()
141148{
142149 uint8_t byte;
143- if (recv (_sock, &byte, 1 ) > 0 )
150+
151+ if ((_remaining > 0 ) && (recv (_sock, &byte, 1 ) > 0 ))
144152 {
145153 // We read things without any problems
154+ _remaining--;
146155 return byte;
147156 }
157+
148158 // If we get here, there's no data available
149159 return -1 ;
150160}
151161
152162int EthernetUDP::read (unsigned char * buffer, size_t len)
153163{
154- /* In the readPacket that copes with truncating packets, the buffer was
155- filled with this code. Not sure why it loops round reading out a byte
156- at a time.
157- int i;
158- for(i=0;i<(int)bufLen;i++) {
159- recv(_sock,tmpBuf,1);
160- buf[i]=tmpBuf[0];
164+
165+ if (_remaining > 0 )
166+ {
167+
168+ int got;
169+
170+ if (_remaining <= len)
171+ {
172+ // data should fit in the buffer
173+ got = recv (_sock, buffer, _remaining);
174+ }
175+ else
176+ {
177+ // too much data for the buffer,
178+ // grab as much as will fit
179+ got = recv (_sock, buffer, len);
180+ }
181+
182+ if (got > 0 )
183+ {
184+ _remaining -= got;
185+ return got;
186+ }
187+
161188 }
162- */
163- return recv (_sock, buffer, len);
189+
190+ // If we get here, there's no data available or recv failed
191+ return -1 ;
192+
164193}
165194
166195int EthernetUDP::peek ()
167196{
168197 uint8_t b;
169- // Unlike recv, peek doesn't check to see if there's any data available, so we must
170- if (!available ())
198+ // Unlike recv, peek doesn't check to see if there's any data available, so we must.
199+ // If the user hasn't called parsePacket yet then return nothing otherwise they
200+ // may get the UDP header
201+ if (!_remaining)
171202 return -1 ;
172203 ::peek (_sock, &b);
173204 return b;
174205}
175206
176207void EthernetUDP::flush ()
177208{
178- while (available ())
209+ // could this fail (loop endlessly) if _remaining > 0 and recv in read fails?
210+ // should only occur if recv fails after telling us the data is there, lets
211+ // hope the w5100 always behaves :)
212+
213+ while (_remaining)
179214 {
180215 read ();
181216 }
0 commit comments