@@ -52,15 +52,16 @@ uint8_t EthernetUDP::begin(uint16_t port) {
52
52
return 0 ;
53
53
54
54
_port = port;
55
+ _remaining = 0 ;
55
56
socket (_sock, SnMR::UDP, _port, 0 );
56
57
57
58
return 1 ;
58
59
}
59
60
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 */
62
63
int EthernetUDP::available () {
63
- return W5100. getRXReceivedSize (_sock) ;
64
+ return _remaining ;
64
65
}
65
66
66
67
/* Release any resources being used by this EthernetUDP instance */
@@ -116,20 +117,26 @@ size_t EthernetUDP::write(const uint8_t *buffer, size_t size)
116
117
117
118
int EthernetUDP::parsePacket ()
118
119
{
119
- if (available () > 0 )
120
+ // discard any remaining bytes in the last packet
121
+ flush ();
122
+
123
+ if (W5100.getRXReceivedSize (_sock) > 0 )
120
124
{
121
125
// HACK - hand-parse the UDP packet using TCP recv method
122
126
uint8_t tmpBuf[8 ];
123
- int ret =0 ;
127
+ int ret =0 ;
124
128
// read 8 header bytes and get IP and port from it
125
129
ret = recv (_sock,tmpBuf,8 );
126
130
if (ret > 0 )
127
131
{
128
132
_remoteIP = tmpBuf;
129
133
_remotePort = tmpBuf[4 ];
130
134
_remotePort = (_remotePort << 8 ) + tmpBuf[5 ];
135
+ _remaining = tmpBuf[6 ];
136
+ _remaining = (_remaining << 8 ) + tmpBuf[7 ];
137
+
131
138
// When we get here, any remaining bytes are the data
132
- ret = available () ;
139
+ ret = _remaining ;
133
140
}
134
141
return ret;
135
142
}
@@ -140,42 +147,70 @@ int EthernetUDP::parsePacket()
140
147
int EthernetUDP::read ()
141
148
{
142
149
uint8_t byte;
143
- if (recv (_sock, &byte, 1 ) > 0 )
150
+
151
+ if ((_remaining > 0 ) && (recv (_sock, &byte, 1 ) > 0 ))
144
152
{
145
153
// We read things without any problems
154
+ _remaining--;
146
155
return byte;
147
156
}
157
+
148
158
// If we get here, there's no data available
149
159
return -1 ;
150
160
}
151
161
152
162
int EthernetUDP::read (unsigned char * buffer, size_t len)
153
163
{
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
+
161
188
}
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
+
164
193
}
165
194
166
195
int EthernetUDP::peek ()
167
196
{
168
197
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)
171
202
return -1 ;
172
203
::peek (_sock, &b);
173
204
return b;
174
205
}
175
206
176
207
void EthernetUDP::flush ()
177
208
{
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)
179
214
{
180
215
read ();
181
216
}
0 commit comments