| 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