Skip to content

Commit 561cd70

Browse files
committed
Fixing (maybe) a bug involving multiple received UDP packets.
http://code.google.com/p/arduino/issues/detail?id=669
1 parent 6ab18ea commit 561cd70

File tree

2 files changed

+55
-19
lines changed

2 files changed

+55
-19
lines changed

libraries/Ethernet/EthernetUdp.cpp

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
6263
int 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

117118
int 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()
140147
int 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

152162
int 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

166195
int 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

176207
void 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
}

libraries/Ethernet/EthernetUdp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class EthernetUDP : public UDP {
4848
IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed
4949
uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed
5050
uint16_t _offset; // offset into the packet being sent
51+
uint16_t _remaining; // remaining bytes of incoming packet yet to be processed
5152

5253
public:
5354
EthernetUDP(); // Constructor

0 commit comments

Comments
 (0)