Line No. | Rev | Author | Line |
---|---|---|---|
1 | 32 | kaklik | /********************************************************************* |
2 | * |
||
3 | * User Datagram Protocol (UDP) Communications Layer |
||
4 | * Module for Microchip TCP/IP Stack |
||
5 | * -Provides unreliable, minimum latency transport of application |
||
6 | * datagram (packet) oriented data |
||
7 | * -Reference: RFC 768 |
||
8 | * |
||
9 | ********************************************************************* |
||
10 | * FileName: UDP.c |
||
11 | * Dependencies: IP, Ethernet (ENC28J60.c or ETH97J60.c) |
||
12 | * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32 |
||
13 | * Compiler: Microchip C32 v1.05 or higher |
||
14 | * Microchip C30 v3.12 or higher |
||
15 | * Microchip C18 v3.30 or higher |
||
16 | * HI-TECH PICC-18 PRO 9.63PL2 or higher |
||
17 | * Company: Microchip Technology, Inc. |
||
18 | * |
||
19 | * Software License Agreement |
||
20 | * |
||
21 | * Copyright (C) 2002-2009 Microchip Technology Inc. All rights |
||
22 | * reserved. |
||
23 | * |
||
24 | * Microchip licenses to you the right to use, modify, copy, and |
||
25 | * distribute: |
||
26 | * (i) the Software when embedded on a Microchip microcontroller or |
||
27 | * digital signal controller product ("Device") which is |
||
28 | * integrated into Licensee's product; or |
||
29 | * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h, |
||
30 | * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device |
||
31 | * used in conjunction with a Microchip ethernet controller for |
||
32 | * the sole purpose of interfacing with the ethernet controller. |
||
33 | * |
||
34 | * You should refer to the license agreement accompanying this |
||
35 | * Software for additional information regarding your rights and |
||
36 | * obligations. |
||
37 | * |
||
38 | * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT |
||
39 | * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT |
||
40 | * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A |
||
41 | * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
42 | * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR |
||
43 | * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF |
||
44 | * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS |
||
45 | * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE |
||
46 | * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER |
||
47 | * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT |
||
48 | * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. |
||
49 | * |
||
50 | * |
||
51 | * Author Date Comment |
||
52 | *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
53 | * Nilesh Rajbharti 3/19/01 Original (Rev 1.0) |
||
54 | * Nilesh Rajbharti 2/26/03 Fixed UDPGet and UDPProcess bugs |
||
55 | * as discovered and fixed by John Owen |
||
56 | * of Powerwave. |
||
57 | * 1. UDPGet would return FALSE on last good byte |
||
58 | * 2. UDPProcess was incorrectly calculating length. |
||
59 | * Nilesh Rajbharti 5/19/03 Added bFirstRead flag similar to TCP |
||
60 | * to detect very first UDPGet and |
||
61 | * reset MAC Rx pointer to begining of |
||
62 | * UDP data area. This would ensure that |
||
63 | * if UDP socket has pending Rx data and |
||
64 | * another module resets MAC Rx pointer, |
||
65 | * next UDP socket Get would get correct |
||
66 | * data. |
||
67 | * Robert Sloan (RSS) 5/29/03 Improved FindMatchingSocket() |
||
68 | * Nilesh Rajbharti 12/2/03 Added UDPChecksum logic in UDPProcess() |
||
69 | * Nilesh Rajbharti 12/5/03 Modified UDPProcess() and FindMatchingSocket() |
||
70 | * to include localIP as new parameter. |
||
71 | * This corrects pseudo header checksum |
||
72 | * logic in UDPProcess(). |
||
73 | * It also corrects broadcast packet |
||
74 | * matching correct in FindMatchingSocket(). |
||
75 | * Howard Schlunder 1/16/06 Fixed an imporbable RX checksum bug |
||
76 | * when using a Microchip Ethernet controller) |
||
77 | * Howard Schlunder 6/02/06 Fixed a bug where all RXed UDP packets |
||
78 | * without a checksum (0x0000) were thrown |
||
79 | * away. No checksum is legal in UDP. |
||
80 | * Howard Schlunder 8/10/06 Fixed a bug where UDP sockets would |
||
81 | * unintentionally keep the remote MAC |
||
82 | * address cached, even after calling |
||
83 | * UDPInit(), UDPClose(), or reseting |
||
84 | * the part without clearing all the |
||
85 | * PIC memory. |
||
86 | ********************************************************************/ |
||
87 | #define __UDP_C |
||
88 | |||
89 | #include "TCPIP Stack/TCPIP.h" |
||
90 | |||
91 | #if defined(STACK_USE_UDP) |
||
92 | |||
93 | /**************************************************************************** |
||
94 | Section: |
||
95 | Configuration Parameters |
||
96 | ***************************************************************************/ |
||
97 | |||
98 | // First port number for randomized local port number selection |
||
99 | #define LOCAL_UDP_PORT_START_NUMBER (4096u) |
||
100 | |||
101 | // Last port number for randomized local port number selection |
||
102 | #define LOCAL_UDP_PORT_END_NUMBER (8192u) |
||
103 | |||
104 | /**************************************************************************** |
||
105 | Section: |
||
106 | UDP Global Variables |
||
107 | ***************************************************************************/ |
||
108 | |||
109 | // Stores an array of information pertaining to each UDP socket |
||
110 | UDP_SOCKET_INFO UDPSocketInfo[MAX_UDP_SOCKETS]; |
||
111 | |||
112 | // Indicates which UDP socket is currently active |
||
113 | UDP_SOCKET activeUDPSocket; |
||
114 | |||
115 | WORD UDPTxCount; // Number of bytes written to this UDP segment |
||
116 | WORD UDPRxCount; // Number of bytes read from this UDP segment |
||
117 | static UDP_SOCKET LastPutSocket = INVALID_UDP_SOCKET; // Indicates the last socket to which data was written |
||
118 | static WORD wPutOffset; // Offset from beginning of payload where data is to be written. |
||
119 | static WORD wGetOffset; // Offset from beginning of payload from where data is to be read. |
||
120 | |||
121 | // Stores various flags for the UDP module |
||
122 | static struct |
||
123 | { |
||
124 | unsigned char bFirstRead : 1; // No data has been read from this segment yet |
||
125 | unsigned char bWasDiscarded : 1; // The data in this segment has been discarded |
||
126 | } Flags; |
||
127 | |||
128 | // Indicates which socket has currently received data for this loop |
||
129 | static UDP_SOCKET SocketWithRxData = INVALID_UDP_SOCKET; |
||
130 | |||
131 | /**************************************************************************** |
||
132 | Section: |
||
133 | Function Prototypes |
||
134 | ***************************************************************************/ |
||
135 | |||
136 | static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode, |
||
137 | IP_ADDR *localIP); |
||
138 | |||
139 | /**************************************************************************** |
||
140 | Section: |
||
141 | Connection Management Functions |
||
142 | ***************************************************************************/ |
||
143 | |||
144 | /***************************************************************************** |
||
145 | Function: |
||
146 | void UDPInit(void) |
||
147 | |||
148 | Summary: |
||
149 | Initializes the UDP module. |
||
150 | |||
151 | Description: |
||
152 | Initializes the UDP module. This function initializes all the UDP |
||
153 | sockets to the closed state. |
||
154 | |||
155 | Precondition: |
||
156 | None |
||
157 | |||
158 | Parameters: |
||
159 | None |
||
160 | |||
161 | Returns: |
||
162 | None |
||
163 | |||
164 | Remarks: |
||
165 | This function is called only one during lifetime of the application. |
||
166 | ***************************************************************************/ |
||
167 | void UDPInit(void) |
||
168 | { |
||
169 | UDP_SOCKET s; |
||
170 | |||
171 | for ( s = 0; s < MAX_UDP_SOCKETS; s++ ) |
||
172 | { |
||
173 | UDPClose(s); |
||
174 | } |
||
175 | Flags.bWasDiscarded = 1; |
||
176 | } |
||
177 | |||
178 | |||
179 | /***************************************************************************** |
||
180 | Function: |
||
181 | void UDPTask(void) |
||
182 | |||
183 | Summary: |
||
184 | Performs state management and housekeeping for UDP. |
||
185 | |||
186 | Description: |
||
187 | Performs state management and housekeeping for UDP. This is an internal |
||
188 | function meant to be called by StackTask() (not a user API). |
||
189 | |||
190 | Precondition: |
||
191 | None |
||
192 | |||
193 | Parameters: |
||
194 | None |
||
195 | |||
196 | Return Values: |
||
197 | None |
||
198 | |||
199 | Remarks: |
||
200 | UDPTask() is called once per StackTask() iteration to ensure that calls |
||
201 | to UDPIsPutReady() always update the Ethernet Write pointer location |
||
202 | between StackTask() iterations. |
||
203 | ***************************************************************************/ |
||
204 | void UDPTask(void) |
||
205 | { |
||
206 | LastPutSocket = INVALID_UDP_SOCKET; |
||
207 | } |
||
208 | |||
209 | |||
210 | /***************************************************************************** |
||
211 | Function: |
||
212 | UDP_SOCKET UDPOpen(UDP_PORT localPort, NODE_INFO* remoteNode, |
||
213 | UDP_PORT remotePort) |
||
214 | |||
215 | Summary: |
||
216 | Creates a UDP socket handle for transmiting or receiving UDP packets. |
||
217 | |||
218 | Description: |
||
219 | Creates a UDP socket handle for transmiting or receiving UDP packets. |
||
220 | Call this function to obtain a handle required by other UDP function. |
||
221 | |||
222 | Precondition: |
||
223 | UDPInit() must have been previously called. |
||
224 | |||
225 | Parameters: |
||
226 | localPort - UDP port number to listen on. If 0, stack will dynamically |
||
227 | assign a unique port number to use. |
||
228 | remoteNode - Pointer to remote node info (MAC and IP address) for this |
||
229 | connection. If this is a server socket (receives the first packet) |
||
230 | or the destination is the broadcast address, then this parameter |
||
231 | should be NULL. |
||
232 | remotePort - For client sockets, the remote port number. |
||
233 | |||
234 | Return Values: |
||
235 | Success - |
||
236 | A UDP socket handle that can be used for subsequent UDP API calls. |
||
237 | Failure - |
||
238 | INVALID_UDP_SOCKET. This function fails when no more UDP socket |
||
239 | handles are available. Increase MAX_UDP_SOCKETS to make more sockets |
||
240 | available. |
||
241 | |||
242 | Remarks: |
||
243 | When finished using the UDP socket handle, call the UDPClose() function |
||
244 | to free the socket and delete the handle. |
||
245 | ***************************************************************************/ |
||
246 | UDP_SOCKET UDPOpen(UDP_PORT localPort, |
||
247 | NODE_INFO *remoteNode, |
||
248 | UDP_PORT remotePort) |
||
249 | { |
||
250 | UDP_SOCKET s; |
||
251 | UDP_SOCKET_INFO *p; |
||
252 | |||
253 | // Local temp port numbers. |
||
254 | static WORD NextPort __attribute__((persistent)); |
||
255 | |||
256 | |||
257 | p = UDPSocketInfo; |
||
258 | for ( s = 0; s < MAX_UDP_SOCKETS; s++ ) |
||
259 | { |
||
260 | if(p->localPort == INVALID_UDP_PORT) |
||
261 | { |
||
262 | p->localPort = localPort; |
||
263 | |||
264 | if(localPort == 0x0000u) |
||
265 | { |
||
266 | if(NextPort > LOCAL_UDP_PORT_END_NUMBER || NextPort < LOCAL_UDP_PORT_START_NUMBER) |
||
267 | NextPort = LOCAL_UDP_PORT_START_NUMBER; |
||
268 | |||
269 | p->localPort = NextPort++; |
||
270 | } |
||
271 | |||
272 | // If remoteNode is supplied, remember it. |
||
273 | if(remoteNode) |
||
274 | { |
||
275 | memcpy((void*)&p->remoteNode, |
||
276 | (const void*)remoteNode, |
||
277 | sizeof(p->remoteNode)); |
||
278 | } |
||
279 | else |
||
280 | { |
||
281 | // else Set broadcast address |
||
282 | memset((void*)&p->remoteNode, 0xFF, sizeof(p->remoteNode)); |
||
283 | } |
||
284 | |||
285 | p->remotePort = remotePort; |
||
286 | |||
287 | // Mark this socket as active. |
||
288 | // Once an active socket is set, subsequent operation can be |
||
289 | // done without explicitely supply socket identifier. |
||
290 | activeUDPSocket = s; |
||
291 | return s; |
||
292 | } |
||
293 | p++; |
||
294 | } |
||
295 | |||
296 | return (UDP_SOCKET)INVALID_UDP_SOCKET; |
||
297 | } |
||
298 | |||
299 | |||
300 | |||
301 | |||
302 | /***************************************************************************** |
||
303 | Function: |
||
304 | void UDPClose(UDP_SOCKET s) |
||
305 | |||
306 | Summary: |
||
307 | Closes a UDP socket and frees the handle. |
||
308 | |||
309 | Description: |
||
310 | Closes a UDP socket and frees the handle. Call this function to release |
||
311 | a socket and return it to the pool for use by future communications. |
||
312 | |||
313 | Precondition: |
||
314 | UDPInit() must have been previously called. |
||
315 | |||
316 | Parameters: |
||
317 | s - The socket handle to be released. If an illegal handle value is |
||
318 | provided, the function safely does nothing. |
||
319 | |||
320 | Returns: |
||
321 | None |
||
322 | |||
323 | Remarks: |
||
324 | This function does not affect the previously designated active socket. |
||
325 | ***************************************************************************/ |
||
326 | void UDPClose(UDP_SOCKET s) |
||
327 | { |
||
328 | if(s >= MAX_UDP_SOCKETS) |
||
329 | return; |
||
330 | |||
331 | UDPSocketInfo[s].localPort = INVALID_UDP_PORT; |
||
332 | UDPSocketInfo[s].remoteNode.IPAddr.Val = 0x00000000; |
||
333 | } |
||
334 | |||
335 | |||
336 | /***************************************************************************** |
||
337 | Function: |
||
338 | void UDPSetTxBuffer(WORD wOffset) |
||
339 | |||
340 | Summary: |
||
341 | Moves the pointer within the TX buffer. |
||
342 | |||
343 | Description: |
||
344 | This function allows the write location within the TX buffer to be |
||
345 | specified. Future calls to UDPPut, UDPPutArray, UDPPutString, etc will |
||
346 | write data from the indicated location. |
||
347 | |||
348 | Precondition: |
||
349 | UDPInit() must have been previously called and a socket is currently |
||
350 | active. |
||
351 | |||
352 | Parameters: |
||
353 | wOffset - Offset from beginning of UDP packet data payload to place the |
||
354 | write pointer. |
||
355 | |||
356 | Returns: |
||
357 | None |
||
358 | ***************************************************************************/ |
||
359 | void UDPSetTxBuffer(WORD wOffset) |
||
360 | { |
||
361 | IPSetTxBuffer(wOffset+sizeof(UDP_HEADER)); |
||
362 | wPutOffset = wOffset; |
||
363 | } |
||
364 | |||
365 | |||
366 | /***************************************************************************** |
||
367 | Function: |
||
368 | void UDPSetRxBuffer(WORD wOffset) |
||
369 | |||
370 | Summary: |
||
371 | Moves the pointer within the RX buffer. |
||
372 | |||
373 | Description: |
||
374 | This function allows the read location within the RX buffer to be |
||
375 | specified. Future calls to UDPGet and UDPGetArray will read data from |
||
376 | the indicated location forward. |
||
377 | |||
378 | Precondition: |
||
379 | UDPInit() must have been previously called and a socket is currently |
||
380 | active. |
||
381 | |||
382 | Parameters: |
||
383 | wOffset - Offset from beginning of UDP packet data payload to place the |
||
384 | read pointer. |
||
385 | |||
386 | Returns: |
||
387 | None |
||
388 | ***************************************************************************/ |
||
389 | void UDPSetRxBuffer(WORD wOffset) |
||
390 | { |
||
391 | IPSetRxBuffer(wOffset+sizeof(UDP_HEADER)); |
||
392 | wGetOffset = wOffset; |
||
393 | } |
||
394 | |||
395 | |||
396 | |||
397 | /**************************************************************************** |
||
398 | Section: |
||
399 | Transmit Functions |
||
400 | ***************************************************************************/ |
||
401 | |||
402 | /***************************************************************************** |
||
403 | Function: |
||
404 | WORD UDPIsPutReady(UDP_SOCKET s) |
||
405 | |||
406 | Summary: |
||
407 | Determines how many bytes can be written to the UDP socket. |
||
408 | |||
409 | Description: |
||
410 | This function determines if bytes can be written to the specified UDP |
||
411 | socket. It also prepares the UDP module for writing by setting the |
||
412 | indicated socket as the currently active connection. |
||
413 | |||
414 | Precondition: |
||
415 | UDPInit() must have been previously called. |
||
416 | |||
417 | Parameters: |
||
418 | s - The socket to be made active |
||
419 | |||
420 | Returns: |
||
421 | The number of bytes that can be written to this socket. |
||
422 | ***************************************************************************/ |
||
423 | WORD UDPIsPutReady(UDP_SOCKET s) |
||
424 | { |
||
425 | if(!MACIsTxReady()) |
||
426 | return 0; |
||
427 | |||
428 | if(LastPutSocket != s) |
||
429 | { |
||
430 | LastPutSocket = s; |
||
431 | UDPTxCount = 0; |
||
432 | UDPSetTxBuffer(0); |
||
433 | } |
||
434 | |||
435 | activeUDPSocket = s; |
||
436 | |||
437 | return MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) - UDPTxCount; |
||
438 | } |
||
439 | |||
440 | /***************************************************************************** |
||
441 | Function: |
||
442 | BOOL UDPPut(BYTE v) |
||
443 | |||
444 | Summary: |
||
445 | Writes a byte to the currently active socket. |
||
446 | |||
447 | Description: |
||
448 | This function writes a single byte to the currently active UDP socket, |
||
449 | while incrementing the buffer length. UDPIsPutReady should be used |
||
450 | before calling this function to specify the currently active socket. |
||
451 | |||
452 | Precondition: |
||
453 | UDPIsPutReady() was previously called to specify the current socket. |
||
454 | |||
455 | Parameters: |
||
456 | v - The byte to be loaded into the transmit buffer. |
||
457 | |||
458 | Return Values: |
||
459 | TRUE - The byte was successfully written to the socket. |
||
460 | FALSE - The transmit buffer is already full and so the write failed. |
||
461 | ***************************************************************************/ |
||
462 | BOOL UDPPut(BYTE v) |
||
463 | { |
||
464 | // See if we are out of transmit space. |
||
465 | if(wPutOffset >= (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER))) |
||
466 | { |
||
467 | return FALSE; |
||
468 | } |
||
469 | |||
470 | // Load application data byte |
||
471 | MACPut(v); |
||
472 | wPutOffset++; |
||
473 | if(wPutOffset > UDPTxCount) |
||
474 | UDPTxCount = wPutOffset; |
||
475 | |||
476 | return TRUE; |
||
477 | } |
||
478 | |||
479 | /***************************************************************************** |
||
480 | Function: |
||
481 | WORD UDPPutArray(BYTE *cData, WORD wDataLen) |
||
482 | |||
483 | Summary: |
||
484 | Writes an array of bytes to the currently active socket. |
||
485 | |||
486 | Description: |
||
487 | This function writes an array of bytes to the currently active UDP socket, |
||
488 | while incrementing the buffer length. UDPIsPutReady should be used |
||
489 | before calling this function to specify the currently active socket. |
||
490 | |||
491 | Precondition: |
||
492 | UDPIsPutReady() was previously called to specify the current socket. |
||
493 | |||
494 | Parameters: |
||
495 | cData - The array to write to the socket. |
||
496 | wDateLen - Number of bytes from cData to be written. |
||
497 | |||
498 | Returns: |
||
499 | The number of bytes successfully placed in the UDP transmit buffer. If |
||
500 | this value is less than wDataLen, then the buffer became full and the |
||
501 | input was truncated. |
||
502 | ***************************************************************************/ |
||
503 | WORD UDPPutArray(BYTE *cData, WORD wDataLen) |
||
504 | { |
||
505 | WORD wTemp; |
||
506 | |||
507 | wTemp = (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)) - wPutOffset; |
||
508 | if(wTemp < wDataLen) |
||
509 | wDataLen = wTemp; |
||
510 | |||
511 | wPutOffset += wDataLen; |
||
512 | if(wPutOffset > UDPTxCount) |
||
513 | UDPTxCount = wPutOffset; |
||
514 | |||
515 | // Load application data bytes |
||
516 | MACPutArray(cData, wDataLen); |
||
517 | |||
518 | return wDataLen; |
||
519 | } |
||
520 | |||
521 | /***************************************************************************** |
||
522 | Function: |
||
523 | WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen) |
||
524 | |||
525 | Summary: |
||
526 | Writes an array of bytes from ROM to the currently active socket. |
||
527 | |||
528 | Description: |
||
529 | This function writes an array of bytes from ROM to the currently active |
||
530 | UDP socket, while incrementing the buffer length. UDPIsPutReady should |
||
531 | be used before calling this function to specify the currently active |
||
532 | socket. |
||
533 | |||
534 | Precondition: |
||
535 | UDPIsPutReady() was previously called to specify the current socket. |
||
536 | |||
537 | Parameters: |
||
538 | cData - The array to write to the socket. |
||
539 | wDateLen - Number of bytes from cData to be written. |
||
540 | |||
541 | Returns: |
||
542 | The number of bytes successfully placed in the UDP transmit buffer. If |
||
543 | this value is less than wDataLen, then the buffer became full and the |
||
544 | input was truncated. |
||
545 | |||
546 | Remarks: |
||
547 | This function is aliased to UDPPutArray on non-PIC18 platforms. |
||
548 | ***************************************************************************/ |
||
549 | #if defined(__18CXX) |
||
550 | WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen) |
||
551 | { |
||
552 | WORD wTemp; |
||
553 | |||
554 | wTemp = (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)) - wPutOffset; |
||
555 | if(wTemp < wDataLen) |
||
556 | wDataLen = wTemp; |
||
557 | |||
558 | wPutOffset += wDataLen; |
||
559 | if(wPutOffset > UDPTxCount) |
||
560 | UDPTxCount = wPutOffset; |
||
561 | |||
562 | // Load application data bytes |
||
563 | MACPutROMArray(cData, wDataLen); |
||
564 | |||
565 | return wDataLen; |
||
566 | } |
||
567 | #endif |
||
568 | |||
569 | /***************************************************************************** |
||
570 | Function: |
||
571 | BYTE* UDPPutString(BYTE *strData) |
||
572 | |||
573 | Summary: |
||
574 | Writes null-terminated string to the currently active socket. |
||
575 | |||
576 | Description: |
||
577 | This function writes a null-terminated string to the currently active |
||
578 | UDP socket, while incrementing the buffer length. UDPIsPutReady should |
||
579 | be used before calling this function to specify the currently active |
||
580 | socket. |
||
581 | |||
582 | Precondition: |
||
583 | UDPIsPutReady() was previously called to specify the current socket. |
||
584 | |||
585 | Parameters: |
||
586 | cData - Pointer to the string to be written to the socket. |
||
587 | |||
588 | Returns: |
||
589 | A pointer to the byte following the last byte written. Note that this |
||
590 | is different than the UDPPutArray functions. If this pointer does not |
||
591 | dereference to a NULL byte, then the buffer became full and the input |
||
592 | data was truncated. |
||
593 | ***************************************************************************/ |
||
594 | BYTE* UDPPutString(BYTE *strData) |
||
595 | { |
||
596 | return strData + UDPPutArray(strData, strlen((char*)strData)); |
||
597 | } |
||
598 | |||
599 | /***************************************************************************** |
||
600 | Function: |
||
601 | BYTE* UDPPutString(BYTE *strData) |
||
602 | |||
603 | Summary: |
||
604 | Writes null-terminated string from ROM to the currently active socket. |
||
605 | |||
606 | Description: |
||
607 | This function writes a null-terminated string from ROM to the currently |
||
608 | active UDP socket, while incrementing the buffer length. UDPIsPutReady |
||
609 | should be used before calling this function to specify the currently |
||
610 | active socket. |
||
611 | |||
612 | Precondition: |
||
613 | UDPIsPutReady() was previously called to specify the current socket. |
||
614 | |||
615 | Parameters: |
||
616 | cData - Pointer to the string to be written to the socket. |
||
617 | |||
618 | Returns: |
||
619 | A pointer to the byte following the last byte written. Note that this |
||
620 | is different than the UDPPutArray functions. If this pointer does not |
||
621 | dereference to a NULL byte, then the buffer became full and the input |
||
622 | data was truncated. |
||
623 | |||
624 | Remarks: |
||
625 | This function is aliased to UDPPutString on non-PIC18 platforms. |
||
626 | ***************************************************************************/ |
||
627 | #if defined(__18CXX) |
||
628 | ROM BYTE* UDPPutROMString(ROM BYTE *strData) |
||
629 | { |
||
630 | return strData + UDPPutROMArray(strData, strlenpgm((ROM char*)strData)); |
||
631 | } |
||
632 | #endif |
||
633 | |||
634 | /***************************************************************************** |
||
635 | Function: |
||
636 | void UDPFlush(void) |
||
637 | |||
638 | Summary: |
||
639 | Transmits all pending data in a UDP socket. |
||
640 | |||
641 | Description: |
||
642 | This function builds a UDP packet with the pending TX data and marks it |
||
643 | for transmission over the network interface. Since UDP is a frame-based |
||
644 | protocol, this function must be called before returning to the main |
||
645 | stack loop whenever any data is written. |
||
646 | |||
647 | Precondition: |
||
648 | UDPIsPutReady() was previously called to specify the current socket, and |
||
649 | data has been written to the socket using the UDPPut family of functions. |
||
650 | |||
651 | Parameters: |
||
652 | None |
||
653 | |||
654 | Returns: |
||
655 | None |
||
656 | |||
657 | Remarks: |
||
658 | Note that unlike TCPFlush, UDPFlush must be called before returning to |
||
659 | the main stack loop. There is no auto transmit for UDP segments. |
||
660 | ***************************************************************************/ |
||
661 | void UDPFlush(void) |
||
662 | { |
||
663 | UDP_HEADER h; |
||
664 | UDP_SOCKET_INFO *p; |
||
665 | WORD wUDPLength; |
||
666 | |||
667 | p = &UDPSocketInfo[activeUDPSocket]; |
||
668 | |||
669 | wUDPLength = UDPTxCount + sizeof(UDP_HEADER); |
||
670 | |||
671 | // Generate the correct UDP header |
||
672 | h.SourcePort = swaps(p->localPort); |
||
673 | h.DestinationPort = swaps(p->remotePort); |
||
674 | h.Length = swaps(wUDPLength); |
||
675 | h.Checksum = 0x0000; |
||
676 | |||
677 | // Calculate IP pseudoheader checksum if we are going to enable |
||
678 | // the checksum field |
||
679 | #if defined(UDP_USE_TX_CHECKSUM) |
||
680 | { |
||
681 | PSEUDO_HEADER pseudoHeader; |
||
682 | |||
683 | pseudoHeader.SourceAddress = AppConfig.MyIPAddr; |
||
684 | pseudoHeader.DestAddress = p->remoteNode.IPAddr; |
||
685 | pseudoHeader.Zero = 0x0; |
||
686 | pseudoHeader.Protocol = IP_PROT_UDP; |
||
687 | pseudoHeader.Length = wUDPLength; |
||
688 | SwapPseudoHeader(pseudoHeader); |
||
689 | h.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader)); |
||
690 | } |
||
691 | #endif |
||
692 | |||
693 | // Position the hardware write pointer where we will need to |
||
694 | // begin writing the IP header |
||
695 | MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER)); |
||
696 | |||
697 | // Write IP header to packet |
||
698 | IPPutHeader(&p->remoteNode, IP_PROT_UDP, wUDPLength); |
||
699 | |||
700 | // Write UDP header to packet |
||
701 | MACPutArray((BYTE*)&h, sizeof(h)); |
||
702 | |||
703 | // Calculate the final UDP checksum and write it in, if enabled |
||
704 | #if defined(UDP_USE_TX_CHECKSUM) |
||
705 | { |
||
706 | PTR_BASE wReadPtrSave; |
||
707 | WORD wChecksum; |
||
708 | |||
709 | wReadPtrSave = MACSetReadPtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER)); |
||
710 | wChecksum = CalcIPBufferChecksum(wUDPLength); |
||
711 | if(wChecksum == 0x0000u) |
||
712 | wChecksum = 0xFFFF; |
||
713 | MACSetReadPtr(wReadPtrSave); |
||
714 | MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + 6); // 6 is the offset to the Checksum field in UDP_HEADER |
||
715 | MACPutArray((BYTE*)&wChecksum, sizeof(wChecksum)); |
||
716 | } |
||
717 | #endif |
||
718 | |||
719 | // Transmit the packet |
||
720 | MACFlush(); |
||
721 | |||
722 | // Reset packet size counter for the next TX operation |
||
723 | UDPTxCount = 0; |
||
724 | LastPutSocket = INVALID_UDP_SOCKET; |
||
725 | } |
||
726 | |||
727 | |||
728 | |||
729 | /**************************************************************************** |
||
730 | Section: |
||
731 | Receive Functions |
||
732 | ***************************************************************************/ |
||
733 | |||
734 | /***************************************************************************** |
||
735 | Function: |
||
736 | WORD UDPIsGetReady(UDP_SOCKET s) |
||
737 | |||
738 | Summary: |
||
739 | Determines how many bytes can be read from the UDP socket. |
||
740 | |||
741 | Description: |
||
742 | This function determines if bytes can be read from the specified UDP |
||
743 | socket. It also prepares the UDP module for reading by setting the |
||
744 | indicated socket as the currently active connection. |
||
745 | |||
746 | Precondition: |
||
747 | UDPInit() must have been previously called. |
||
748 | |||
749 | Parameters: |
||
750 | s - The socket to be made active (which has already been opened or is |
||
751 | listening) |
||
752 | |||
753 | Returns: |
||
754 | The number of bytes that can be read from this socket. |
||
755 | ***************************************************************************/ |
||
756 | WORD UDPIsGetReady(UDP_SOCKET s) |
||
757 | { |
||
758 | activeUDPSocket = s; |
||
759 | if(SocketWithRxData != s) |
||
760 | return 0; |
||
761 | |||
762 | // If this is the very first time we are accessing this packet, |
||
763 | // move the read point to the begining of the packet. |
||
764 | if(Flags.bFirstRead) |
||
765 | { |
||
766 | Flags.bFirstRead = 0; |
||
767 | UDPSetRxBuffer(0); |
||
768 | } |
||
769 | |||
770 | return UDPRxCount - wGetOffset; |
||
771 | } |
||
772 | |||
773 | /***************************************************************************** |
||
774 | Function: |
||
775 | BOOL UDPGet(BYTE *v) |
||
776 | |||
777 | Summary: |
||
778 | Reads a byte from the currently active socket. |
||
779 | |||
780 | Description: |
||
781 | This function reads a single byte from the currently active UDP socket, |
||
782 | while decrementing the remaining buffer length. UDPIsGetReady should be |
||
783 | used before calling this function to specify the currently active socket. |
||
784 | |||
785 | Precondition: |
||
786 | UDPIsGetReady() was previously called to specify the current socket. |
||
787 | |||
788 | Parameters: |
||
789 | v - The buffer to receive the data being read. |
||
790 | |||
791 | Return Values: |
||
792 | TRUE - A byte was successfully read |
||
793 | FALSE - No data remained in the read buffer |
||
794 | ***************************************************************************/ |
||
795 | BOOL UDPGet(BYTE *v) |
||
796 | { |
||
797 | // Make sure that there is data to return |
||
798 | if((wGetOffset >= UDPRxCount) || (SocketWithRxData != activeUDPSocket)) |
||
799 | return FALSE; |
||
800 | |||
801 | *v = MACGet(); |
||
802 | wGetOffset++; |
||
803 | |||
804 | return TRUE; |
||
805 | } |
||
806 | |||
807 | |||
808 | /***************************************************************************** |
||
809 | Function: |
||
810 | WORD UDPGetArray(BYTE *cData, WORD wDataLen) |
||
811 | |||
812 | Summary: |
||
813 | Reads an array of bytes from the currently active socket. |
||
814 | |||
815 | Description: |
||
816 | This function reads an array of bytes from the currently active UDP socket, |
||
817 | while decrementing the remaining bytes available. UDPIsGetReady should be |
||
818 | used before calling this function to specify the currently active socket. |
||
819 | |||
820 | Precondition: |
||
821 | UDPIsGetReady() was previously called to specify the current socket. |
||
822 | |||
823 | Parameters: |
||
824 | cData - The buffer to receive the bytes being read. |
||
825 | wDateLen - Number of bytes to be read from the socket. |
||
826 | |||
827 | Returns: |
||
828 | The number of bytes successfully read from the UDP buffer. If this |
||
829 | value is less than wDataLen, then the buffer was emptied and no more |
||
830 | data is available. |
||
831 | ***************************************************************************/ |
||
832 | WORD UDPGetArray(BYTE *cData, WORD wDataLen) |
||
833 | { |
||
834 | WORD wBytesAvailable; |
||
835 | |||
836 | // Make sure that there is data to return |
||
837 | if((wGetOffset >= UDPRxCount) || (SocketWithRxData != activeUDPSocket)) |
||
838 | return 0; |
||
839 | |||
840 | // Make sure we don't try to read more data than exists |
||
841 | wBytesAvailable = UDPRxCount - wGetOffset; |
||
842 | if(wBytesAvailable < wDataLen) |
||
843 | wDataLen = wBytesAvailable; |
||
844 | |||
845 | wDataLen = MACGetArray(cData, wDataLen); |
||
846 | wGetOffset += wDataLen; |
||
847 | |||
848 | return wDataLen; |
||
849 | } |
||
850 | |||
851 | /***************************************************************************** |
||
852 | Function: |
||
853 | void UDPDiscard(void) |
||
854 | |||
855 | Summary: |
||
856 | Discards any remaining RX data from a UDP socket. |
||
857 | |||
858 | Description: |
||
859 | This function discards any remaining received data in the currently |
||
860 | active UDP socket. |
||
861 | |||
862 | Precondition: |
||
863 | UDPIsGetReady() was previously called to select the currently active |
||
864 | socket. |
||
865 | |||
866 | Parameters: |
||
867 | None |
||
868 | |||
869 | Returns: |
||
870 | None |
||
871 | |||
872 | Remarks: |
||
873 | It is safe to call this function more than is necessary. If no data is |
||
874 | available, this function does nothing. |
||
875 | ***************************************************************************/ |
||
876 | void UDPDiscard(void) |
||
877 | { |
||
878 | if(!Flags.bWasDiscarded) |
||
879 | { |
||
880 | MACDiscardRx(); |
||
881 | UDPRxCount = 0; |
||
882 | SocketWithRxData = INVALID_UDP_SOCKET; |
||
883 | Flags.bWasDiscarded = 1; |
||
884 | } |
||
885 | } |
||
886 | |||
887 | |||
888 | |||
889 | /**************************************************************************** |
||
890 | Section: |
||
891 | Data Processing Functions |
||
892 | ***************************************************************************/ |
||
893 | |||
894 | /***************************************************************************** |
||
895 | Function: |
||
896 | BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len) |
||
897 | |||
898 | Summary: |
||
899 | Handles an incoming UDP segment. |
||
900 | |||
901 | Description: |
||
902 | This function handles an incoming UDP segment to determine if it is |
||
903 | acceptable and should be handed to one of the stack applications for |
||
904 | processing. |
||
905 | |||
906 | Precondition: |
||
907 | UDPInit() has been called an a UDP segment is ready in the MAC buffer. |
||
908 | |||
909 | Parameters: |
||
910 | remoteNode - The remote node that sent this segment. |
||
911 | localIP - The destination IP address for this segment. |
||
912 | len - Total length of the UDP segment. |
||
913 | |||
914 | Return Values: |
||
915 | TRUE - A valid packet is waiting and the stack applications should be |
||
916 | called to handle it. |
||
917 | FALSE - The packet was discarded. |
||
918 | ***************************************************************************/ |
||
919 | BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len) |
||
920 | { |
||
921 | UDP_HEADER h; |
||
922 | UDP_SOCKET s; |
||
923 | PSEUDO_HEADER pseudoHeader; |
||
924 | DWORD_VAL checksums; |
||
925 | |||
926 | UDPRxCount = 0; |
||
927 | |||
928 | // Retrieve UDP header. |
||
929 | MACGetArray((BYTE*)&h, sizeof(h)); |
||
930 | |||
931 | h.SourcePort = swaps(h.SourcePort); |
||
932 | h.DestinationPort = swaps(h.DestinationPort); |
||
933 | h.Length = swaps(h.Length) - sizeof(UDP_HEADER); |
||
934 | |||
935 | // See if we need to validate the checksum field (0x0000 is disabled) |
||
936 | if(h.Checksum) |
||
937 | { |
||
938 | // Calculate IP pseudoheader checksum. |
||
939 | pseudoHeader.SourceAddress = remoteNode->IPAddr; |
||
940 | pseudoHeader.DestAddress.Val = localIP->Val; |
||
941 | pseudoHeader.Zero = 0x0; |
||
942 | pseudoHeader.Protocol = IP_PROT_UDP; |
||
943 | pseudoHeader.Length = len; |
||
944 | |||
945 | SwapPseudoHeader(pseudoHeader); |
||
946 | |||
947 | checksums.w[0] = ~CalcIPChecksum((BYTE*)&pseudoHeader, |
||
948 | sizeof(pseudoHeader)); |
||
949 | |||
950 | |||
951 | // Now calculate UDP packet checksum in NIC RAM -- should match pseudoHeader |
||
952 | IPSetRxBuffer(0); |
||
953 | checksums.w[1] = CalcIPBufferChecksum(len); |
||
954 | |||
955 | if(checksums.w[0] != checksums.w[1]) |
||
956 | { |
||
957 | MACDiscardRx(); |
||
958 | return FALSE; |
||
959 | } |
||
960 | } |
||
961 | |||
962 | s = FindMatchingSocket(&h, remoteNode, localIP); |
||
963 | if(s == INVALID_UDP_SOCKET) |
||
964 | { |
||
965 | // If there is no matching socket, There is no one to handle |
||
966 | // this data. Discard it. |
||
967 | MACDiscardRx(); |
||
968 | return FALSE; |
||
969 | } |
||
970 | else |
||
971 | { |
||
972 | SocketWithRxData = s; |
||
973 | UDPRxCount = h.Length; |
||
974 | Flags.bFirstRead = 1; |
||
975 | Flags.bWasDiscarded = 0; |
||
976 | } |
||
977 | |||
978 | |||
979 | return TRUE; |
||
980 | } |
||
981 | |||
982 | /***************************************************************************** |
||
983 | Function: |
||
984 | static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode, |
||
985 | IP_ADDR *localIP) |
||
986 | |||
987 | Summary: |
||
988 | Matches an incoming UDP segment to a currently active socket. |
||
989 | |||
990 | Description: |
||
991 | This function attempts to match an incoming UDP segment to a currently |
||
992 | active socket for processing. |
||
993 | |||
994 | Precondition: |
||
995 | UDP segment header and IP header have both been retrieved. |
||
996 | |||
997 | Parameters: |
||
998 | h - The UDP header that was received. |
||
999 | remoteNode - IP and MAC of the remote node that sent this segment. |
||
1000 | localIP - IP address that this segment was destined for. |
||
1001 | |||
1002 | Returns: |
||
1003 | A UDP_SOCKET handle of a matching socket, or INVALID_UDP_SOCKET when no |
||
1004 | match could be made. |
||
1005 | ***************************************************************************/ |
||
1006 | static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, |
||
1007 | NODE_INFO *remoteNode, |
||
1008 | IP_ADDR *localIP) |
||
1009 | { |
||
1010 | UDP_SOCKET s; |
||
1011 | UDP_SOCKET partialMatch; |
||
1012 | UDP_SOCKET_INFO *p; |
||
1013 | |||
1014 | partialMatch = INVALID_UDP_SOCKET; |
||
1015 | |||
1016 | p = UDPSocketInfo; |
||
1017 | for ( s = 0; s < MAX_UDP_SOCKETS; s++ ) |
||
1018 | { |
||
1019 | // This packet is said to be matching with current socket: |
||
1020 | // 1. If its destination port matches with our local port and |
||
1021 | // 2. Packet source IP address matches with socket remote IP address. |
||
1022 | // OR this socket had transmitted packet with destination address as broadcast (subnet or limited broadcast). |
||
1023 | if ( p->localPort == h->DestinationPort ) |
||
1024 | { |
||
1025 | if(p->remotePort == h->SourcePort) |
||
1026 | { |
||
1027 | if( (p->remoteNode.IPAddr.Val == remoteNode->IPAddr.Val) || |
||
1028 | (localIP->Val == 0xFFFFFFFFul) || |
||
1029 | (localIP->Val == (AppConfig.MyIPAddr.Val | (~AppConfig.MyMask.Val)))) |
||
1030 | { |
||
1031 | return s; |
||
1032 | } |
||
1033 | #ifdef STACK_USE_ZEROCONF_MDNS_SD |
||
1034 | /* Multicast Support in UDP Layer for mDNS. |
||
1035 | * mDNS- Multicast DNS for Zeroconf protocol. |
||
1036 | * Multicast address used by mDNS: 224.0.0.251 : 5353 |
||
1037 | * second check with self MAC-address is to |
||
1038 | * suppress Loop-Back packets */ |
||
1039 | else if (localIP->Val == 0xFB0000E0ul) |
||
1040 | { |
||
1041 | if(remoteNode->IPAddr.Val!= AppConfig.MyIPAddr.Val) |
||
1042 | return s; |
||
1043 | else |
||
1044 | return INVALID_UDP_SOCKET; |
||
1045 | } |
||
1046 | #endif |
||
1047 | } |
||
1048 | |||
1049 | partialMatch = s; |
||
1050 | } |
||
1051 | p++; |
||
1052 | } |
||
1053 | |||
1054 | if ( partialMatch != INVALID_UDP_SOCKET ) |
||
1055 | { |
||
1056 | p = &UDPSocketInfo[partialMatch]; |
||
1057 | |||
1058 | memcpy((void*)&p->remoteNode, |
||
1059 | (const void*)remoteNode, sizeof(p->remoteNode) ); |
||
1060 | |||
1061 | p->remotePort = h->SourcePort; |
||
1062 | } |
||
1063 | return partialMatch; |
||
1064 | } |
||
1065 | |||
1066 | |||
1067 | #endif //#if defined(STACK_USE_UDP) |
Powered by WebSVN v2.8.3