UDP.c

Go to the documentation of this file.
00001 
00002 
00003 
00028 /*********************************************************************
00029  * Software License Agreement
00030  *
00031  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights 
00032  * reserved.
00033  *
00034  * Microchip licenses to you the right to use, modify, copy, and 
00035  * distribute: 
00036  * (i)  the Software when embedded on a Microchip microcontroller or 
00037  *      digital signal controller product ("Device") which is 
00038  *      integrated into Licensee's product; or
00039  * (ii) ONLY the Software driver source files ENC28J60.c and 
00040  *      ENC28J60.h ported to a non-Microchip device used in 
00041  *      conjunction with a Microchip ethernet controller for the 
00042  *      sole purpose of interfacing with the ethernet controller. 
00043  *
00044  * You should refer to the license agreement accompanying this 
00045  * Software for additional information regarding your rights and 
00046  * obligations.
00047  *
00048  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 
00049  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 
00050  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
00051  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 
00052  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 
00053  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 
00054  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 
00055  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 
00056  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 
00057  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 
00058  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00059  *
00060  *
00061  * Author               Date    Comment
00062  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00063  * Nilesh Rajbharti     3/19/01  Original        (Rev 1.0)
00064  * Nilesh Rajbharti     2/26/03  Fixed UDPGet and UDPProcess bugs
00065  *                               as discovered and fixed by John Owen
00066  *                               of Powerwave.
00067  *                               1. UDPGet would return FALSE on last good byte
00068  *                               2. UDPProcess was incorrectly calculating length.
00069  * Nilesh Rajbharti     5/19/03  Added bFirstRead flag similar to TCP
00070  *                               to detect very first UDPGet and
00071  *                               reset MAC Rx pointer to begining of
00072  *                               UDP data area.  This would ensure that
00073  *                               if UDP socket has pending Rx data and
00074  *                               another module resets MAC Rx pointer,
00075  *                               next UDP socket Get would get correct
00076  *                               data.
00077  * Robert Sloan (RSS)    5/29/03 Improved FindMatchingSocket()
00078  * Nilesh Rajbharti     12/2/03  Added UDPChecksum logic in UDPProcess()
00079  * Nilesh Rajbharti     12/5/03  Modified UDPProcess() and FindMatchingSocket()
00080  *                               to include localIP as new parameter.
00081  *                               This corrects pseudo header checksum
00082  *                               logic in UDPProcess().
00083  *                               It also corrects broadcast packet
00084  *                               matching correct in FindMatchingSocket().
00085  * Howard Schlunder     1/16/06  Fixed an imporbable RX checksum bug 
00086  *                               when using a Microchip Ethernet controller)
00087  * Howard Schlunder     6/02/06  Fixed a bug where all RXed UDP packets 
00088  *                               without a checksum (0x0000) were thrown
00089  *                               away.  No checksum is legal in UDP.
00090  * Howard Schlunder     8/10/06  Fixed a bug where UDP sockets would 
00091  *                               unintentionally keep the remote MAC 
00092  *                               address cached, even after calling 
00093  *                               UDPInit(), UDPClose(), or reseting 
00094  *                               the part without clearing all the 
00095  *                               PIC memory.
00096  ********************************************************************/
00097 #define __UDP_C
00098 
00099 #include "TCPIP.h"
00100 #include "mdns.h"
00101 
00102 
00103 /****************************************************************************
00104   Section:
00105     Configuration Parameters
00106   ***************************************************************************/
00107 
00108 // First port number for randomized local port number selection
00109 #define LOCAL_UDP_PORT_START_NUMBER (4096u)
00110 
00111 // Last port number for randomized local port number selection
00112 #define LOCAL_UDP_PORT_END_NUMBER   (8192u)
00113 
00114 /****************************************************************************
00115   Section:
00116     UDP Global Variables
00117   ***************************************************************************/
00118 
00119 // Stores an array of information pertaining to each UDP socket
00120 UDP_SOCKET_INFO     UDPSocketInfo[MAX_UDP_SOCKETS];
00121 
00122 // Indicates which UDP socket is currently active
00123 UDP_SOCKET          activeUDPSocket;
00124 
00125 WORD UDPTxCount;    // Number of bytes written to this UDP segment
00126 WORD UDPRxCount;    // Number of bytes read from this UDP segment
00127 static UDP_SOCKET   LastPutSocket = INVALID_UDP_SOCKET; // Indicates the last socket to which data was written
00128 static WORD wPutOffset;     // Offset from beginning of payload where data is to be written.
00129 static WORD wGetOffset;     // Offset from beginning of payload from where data is to be read.
00130 
00131 // Stores various flags for the UDP module
00132 static struct
00133 {
00134     unsigned char bFirstRead : 1;       // No data has been read from this segment yet
00135     unsigned char bWasDiscarded : 1;    // The data in this segment has been discarded
00136 } Flags;
00137 
00138 // Indicates which socket has currently received data for this loop
00139 static UDP_SOCKET SocketWithRxData = INVALID_UDP_SOCKET;
00140 
00141 /****************************************************************************
00142   Section:
00143     Function Prototypes
00144   ***************************************************************************/
00145 
00146 static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode,
00147                                     IP_ADDR *localIP);
00148 
00149 /****************************************************************************
00150   Section:
00151     Connection Management Functions
00152   ***************************************************************************/
00153 
00154 /*****************************************************************************
00155   Function:
00156     void UDPInit(void)
00157 
00158   Summary:
00159     Initializes the UDP module.
00160 
00161   Description:
00162     Initializes the UDP module.  This function initializes all the UDP 
00163     sockets to the closed state.
00164 
00165   Precondition:
00166     None
00167 
00168   Parameters:
00169     None
00170 
00171   Returns:
00172     None
00173     
00174   Remarks:
00175     This function is called only one during lifetime of the application.
00176   ***************************************************************************/
00177 void UDPInit(void)
00178 {
00179     UDP_SOCKET s;
00180 
00181     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
00182     {
00183         UDPClose(s);
00184     }
00185     Flags.bWasDiscarded = 1;
00186 }
00187 
00188 
00189 /*****************************************************************************
00190   Function:
00191     void UDPTask(void)
00192 
00193   Summary:
00194     Performs state management and housekeeping for UDP.
00195     
00196   Description:
00197     Performs state management and housekeeping for UDP.  This is an internal
00198     function meant to be called by StackTask() (not a user API).
00199 
00200   Precondition:
00201     None
00202 
00203   Parameters:
00204     None
00205 
00206   Return Values:
00207     None
00208     
00209   Remarks:
00210     UDPTask() is called once per StackTask() iteration to ensure that calls 
00211     to UDPIsPutReady() always update the Ethernet Write pointer location 
00212     between StackTask() iterations.
00213   ***************************************************************************/
00214 void UDPTask(void)
00215 {
00216     LastPutSocket = INVALID_UDP_SOCKET;
00217 }
00218 
00219 
00220 /*****************************************************************************
00221   Function:
00222     UDP_SOCKET UDPOpen(UDP_PORT localPort, NODE_INFO* remoteNode, 
00223                         UDP_PORT remotePort)
00224 
00225   Summary:
00226     Creates a UDP socket handle for transmiting or receiving UDP packets.
00227     
00228   Description:
00229     Creates a UDP socket handle for transmiting or receiving UDP packets.  
00230     Call this function to obtain a handle required by other UDP function.
00231 
00232   Precondition:
00233     UDPInit() must have been previously called.
00234 
00235   Parameters:
00236     localPort - UDP port number to listen on.  If 0, stack will dynamically 
00237         assign a unique port number to use.
00238     remoteNode - Pointer to remote node info (MAC and IP address) for this
00239         connection.  If this is a server socket (receives the first packet) 
00240         or the destination is the broadcast address, then this parameter
00241         should be NULL.
00242     remotePort - For client sockets, the remote port number.
00243 
00244   Return Values:
00245     Success -
00246         A UDP socket handle that can be used for subsequent UDP API calls.
00247     Failure -
00248         INVALID_UDP_SOCKET.  This function fails when no more UDP socket 
00249         handles are available.  Increase MAX_UDP_SOCKETS to make more sockets 
00250         available.
00251     
00252   Remarks:
00253     When finished using the UDP socket handle, call the UDPClose() function 
00254     to free the socket and delete the handle.
00255   ***************************************************************************/
00256 UDP_SOCKET UDPOpen(UDP_PORT localPort,
00257                    NODE_INFO *remoteNode,
00258                    UDP_PORT remotePort)
00259 {
00260     UDP_SOCKET s;
00261     UDP_SOCKET_INFO *p;
00262 
00263     // Local temp port numbers.
00264     static WORD NextPort __attribute__((persistent));
00265 
00266 
00267     p = UDPSocketInfo;
00268     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
00269     {
00270         if(p->localPort == INVALID_UDP_PORT)
00271         {
00272             p->localPort = localPort;   
00273 
00274             if(localPort == 0x0000u)
00275             {
00276                 if(NextPort > LOCAL_UDP_PORT_END_NUMBER || NextPort < LOCAL_UDP_PORT_START_NUMBER)
00277                     NextPort = LOCAL_UDP_PORT_START_NUMBER;
00278     
00279                 p->localPort    = NextPort++;
00280             }
00281 
00282             // If remoteNode is supplied, remember it.
00283             if(remoteNode)
00284             {
00285                 memcpy((void*)&p->remoteNode,
00286                         (const void*)remoteNode,
00287                         sizeof(p->remoteNode));
00288             }
00289             else
00290             {
00291                 // else Set broadcast address
00292                 memset((void*)&p->remoteNode, 0xFF, sizeof(p->remoteNode));
00293             }
00294 
00295             p->remotePort   = remotePort;
00296 
00297             // Mark this socket as active.
00298             // Once an active socket is set, subsequent operation can be
00299             // done without explicitely supply socket identifier.
00300             activeUDPSocket = s;
00301             return s;
00302         }
00303         p++;
00304     }
00305 
00306     return (UDP_SOCKET)INVALID_UDP_SOCKET;
00307 }
00308 
00309 
00310 
00311 
00312 /*****************************************************************************
00313   Function:
00314     void UDPClose(UDP_SOCKET s)
00315 
00316   Summary:
00317     Closes a UDP socket and frees the handle.
00318     
00319   Description:
00320     Closes a UDP socket and frees the handle.  Call this function to release
00321     a socket and return it to the pool for use by future communications.
00322 
00323   Precondition:
00324     UDPInit() must have been previously called.
00325 
00326   Parameters:
00327     s - The socket handle to be released.
00328 
00329   Returns:
00330     None
00331     
00332   Remarks:
00333     This function does not affect the previously designated active socket.
00334   ***************************************************************************/
00335 void UDPClose(UDP_SOCKET s)
00336 {
00337     if(s == INVALID_UDP_SOCKET)
00338         return;
00339 
00340     UDPSocketInfo[s].localPort = INVALID_UDP_PORT;
00341     UDPSocketInfo[s].remoteNode.IPAddr.Val = 0x00000000;
00342 }
00343 
00344 
00345 /*****************************************************************************
00346   Function:
00347     void UDPSetTxBuffer(WORD wOffset)
00348 
00349   Summary:
00350     Moves the pointer within the TX buffer.
00351     
00352   Description:
00353     This function allows the write location within the TX buffer to be 
00354     specified.  Future calls to UDPPut, UDPPutArray, UDPPutString, etc will
00355     write data from the indicated location.
00356 
00357   Precondition:
00358     UDPInit() must have been previously called and a socket is currently 
00359     active.
00360 
00361   Parameters:
00362     wOffset - Offset from beginning of UDP packet data payload to place the
00363         write pointer.
00364 
00365   Returns:
00366     None
00367   ***************************************************************************/
00368 void UDPSetTxBuffer(WORD wOffset)
00369 {
00370     IPSetTxBuffer(wOffset+sizeof(UDP_HEADER));
00371     wPutOffset = wOffset;
00372 }
00373 
00374 
00375 /*****************************************************************************
00376   Function:
00377     void UDPSetRxBuffer(WORD wOffset)
00378 
00379   Summary:
00380     Moves the pointer within the RX buffer.
00381     
00382   Description:
00383     This function allows the read location within the RX buffer to be 
00384     specified.  Future calls to UDPGet and UDPGetArray will read data from
00385     the indicated location forward.
00386 
00387   Precondition:
00388     UDPInit() must have been previously called and a socket is currently 
00389     active.
00390 
00391   Parameters:
00392     wOffset - Offset from beginning of UDP packet data payload to place the
00393         read pointer.
00394 
00395   Returns:
00396     None
00397   ***************************************************************************/
00398 void UDPSetRxBuffer(WORD wOffset)
00399 {
00400     IPSetRxBuffer(wOffset+sizeof(UDP_HEADER));
00401     wGetOffset = wOffset;
00402 }
00403 
00404 
00405 
00406 /****************************************************************************
00407   Section:
00408     Transmit Functions
00409   ***************************************************************************/
00410   
00411 /*****************************************************************************
00412   Function:
00413     WORD UDPIsPutReady(UDP_SOCKET s)
00414 
00415   Summary:
00416     Determines how many bytes can be written to the UDP socket.
00417     
00418   Description:
00419     This function determines if bytes can be written to the specified UDP
00420     socket.  It also prepares the UDP module for writing by setting the 
00421     indicated socket as the currently active connection.
00422 
00423   Precondition:
00424     UDPInit() must have been previously called.
00425 
00426   Parameters:
00427     s - The socket to be made active
00428 
00429   Returns:
00430     The number of bytes that can be written to this socket.
00431   ***************************************************************************/
00432 WORD UDPIsPutReady(UDP_SOCKET s)
00433 {
00434     if(!MACIsTxReady())
00435         return 0;
00436 
00437     if(LastPutSocket != s)
00438     {
00439         LastPutSocket = s;
00440         UDPTxCount = 0;
00441         UDPSetTxBuffer(0);
00442     }
00443 
00444     activeUDPSocket = s;
00445 
00446     return MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) - UDPTxCount;
00447 }
00448 
00449 /*****************************************************************************
00450   Function:
00451     BOOL UDPPut(BYTE v)
00452 
00453   Summary:
00454     Writes a byte to the currently active socket.
00455     
00456   Description:
00457     This function writes a single byte to the currently active UDP socket, 
00458     while incrementing the buffer length.  UDPIsPutReady should be used 
00459     before calling this function to specify the currently active socket.
00460 
00461   Precondition:
00462     UDPIsPutReady() was previously called to specify the current socket.
00463 
00464   Parameters:
00465     v - The byte to be loaded into the transmit buffer.
00466 
00467   Return Values:
00468     TRUE - The byte was successfully written to the socket.
00469     FALSE - The transmit buffer is already full and so the write failed.
00470   ***************************************************************************/
00471 BOOL UDPPut(BYTE v)
00472 {
00473     // See if we are out of transmit space.
00474     if(wPutOffset >= (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)))
00475     {
00476         return FALSE;
00477     }
00478 
00479     // Load application data byte
00480     MACPut(v);
00481     wPutOffset++;
00482     if(wPutOffset > UDPTxCount)
00483         UDPTxCount = wPutOffset;
00484 
00485     return TRUE;
00486 }
00487 
00488 /*****************************************************************************
00489   Function:
00490     WORD UDPPutArray(BYTE *cData, WORD wDataLen)
00491 
00492   Summary:
00493     Writes an array of bytes to the currently active socket.
00494     
00495   Description:
00496     This function writes an array of bytes to the currently active UDP socket, 
00497     while incrementing the buffer length.  UDPIsPutReady should be used 
00498     before calling this function to specify the currently active socket.
00499 
00500   Precondition:
00501     UDPIsPutReady() was previously called to specify the current socket.
00502 
00503   Parameters:
00504     cData - The array to write to the socket.
00505     wDateLen - Number of bytes from cData to be written.
00506     
00507   Returns:
00508     The number of bytes successfully placed in the UDP transmit buffer.  If
00509     this value is less than wDataLen, then the buffer became full and the
00510     input was truncated.
00511   ***************************************************************************/
00512 WORD UDPPutArray(BYTE *cData, WORD wDataLen)
00513 {
00514     WORD wTemp;
00515 
00516     wTemp = (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)) - wPutOffset;
00517     if(wTemp < wDataLen)
00518         wDataLen = wTemp;
00519 
00520     wPutOffset += wDataLen;
00521     if(wPutOffset > UDPTxCount)
00522         UDPTxCount = wPutOffset;
00523 
00524     // Load application data bytes
00525     MACPutArray(cData, wDataLen);
00526 
00527     return wDataLen;
00528 }
00529 
00530 /*****************************************************************************
00531   Function:
00532     WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen)
00533 
00534   Summary:
00535     Writes an array of bytes from ROM to the currently active socket.
00536     
00537   Description:
00538     This function writes an array of bytes from ROM to the currently active 
00539     UDP socket, while incrementing the buffer length.  UDPIsPutReady should 
00540     be used before calling this function to specify the currently active 
00541     socket.
00542 
00543   Precondition:
00544     UDPIsPutReady() was previously called to specify the current socket.
00545 
00546   Parameters:
00547     cData - The array to write to the socket.
00548     wDateLen - Number of bytes from cData to be written.
00549     
00550   Returns:
00551     The number of bytes successfully placed in the UDP transmit buffer.  If
00552     this value is less than wDataLen, then the buffer became full and the
00553     input was truncated.
00554     
00555   Remarks:
00556     This function is aliased to UDPPutArray on non-PIC18 platforms.
00557   ***************************************************************************/
00558 #if defined(__18CXX)
00559 WORD UDPPutROMArray(ROM BYTE *cData, WORD wDataLen)
00560 {
00561     WORD wTemp;
00562 
00563     wTemp = (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)) - wPutOffset;
00564     if(wTemp < wDataLen)
00565         wDataLen = wTemp;
00566 
00567     wPutOffset += wDataLen;
00568     if(wPutOffset > UDPTxCount)
00569         UDPTxCount = wPutOffset;
00570 
00571     // Load application data bytes
00572     MACPutROMArray(cData, wDataLen);
00573 
00574     return wDataLen;
00575 }
00576 #endif
00577 
00578 /*****************************************************************************
00579   Function:
00580     BYTE* UDPPutString(BYTE *strData)
00581 
00582   Summary:
00583     Writes null-terminated string to the currently active socket.
00584     
00585   Description:
00586     This function writes a null-terminated string to the currently active 
00587     UDP socket, while incrementing the buffer length.  UDPIsPutReady should 
00588     be used before calling this function to specify the currently active
00589     socket.
00590 
00591   Precondition:
00592     UDPIsPutReady() was previously called to specify the current socket.
00593 
00594   Parameters:
00595     cData - Pointer to the string to be written to the socket.
00596     
00597   Returns:
00598     A pointer to the byte following the last byte written.  Note that this
00599     is different than the UDPPutArray functions.  If this pointer does not
00600     dereference to a NULL byte, then the buffer became full and the input
00601     data was truncated.
00602   ***************************************************************************/
00603 BYTE* UDPPutString(BYTE *strData)
00604 {
00605     return strData + UDPPutArray(strData, strlen((char*)strData));
00606 }
00607 
00608 /*****************************************************************************
00609   Function:
00610     BYTE* UDPPutString(BYTE *strData)
00611 
00612   Summary:
00613     Writes null-terminated string from ROM to the currently active socket.
00614     
00615   Description:
00616     This function writes a null-terminated string from ROM to the currently
00617     active UDP socket, while incrementing the buffer length.  UDPIsPutReady
00618     should be used before calling this function to specify the currently
00619     active socket.
00620 
00621   Precondition:
00622     UDPIsPutReady() was previously called to specify the current socket.
00623 
00624   Parameters:
00625     cData - Pointer to the string to be written to the socket.
00626     
00627   Returns:
00628     A pointer to the byte following the last byte written.  Note that this
00629     is different than the UDPPutArray functions.  If this pointer does not
00630     dereference to a NULL byte, then the buffer became full and the input
00631     data was truncated.
00632   
00633   Remarks:
00634     This function is aliased to UDPPutString on non-PIC18 platforms.
00635   ***************************************************************************/
00636 #if defined(__18CXX)
00637 ROM BYTE* UDPPutROMString(ROM BYTE *strData)
00638 {
00639     return strData + UDPPutROMArray(strData, strlenpgm((ROM char*)strData));
00640 }
00641 #endif
00642 
00643 /*****************************************************************************
00644   Function:
00645     void UDPFlush(void)
00646 
00647   Summary:
00648     Transmits all pending data in a UDP socket.
00649     
00650   Description:
00651     This function builds a UDP packet with the pending TX data and marks it 
00652     for transmission over the network interface.  Since UDP is a frame-based
00653     protocol, this function must be called before returning to the main
00654     stack loop whenever any data is written.
00655 
00656   Precondition:
00657     UDPIsPutReady() was previously called to specify the current socket, and
00658     data has been written to the socket using the UDPPut family of functions.
00659 
00660   Parameters:
00661     None
00662     
00663   Returns:
00664     None
00665 
00666   Remarks:
00667     Note that unlike TCPFlush, UDPFlush must be called before returning to 
00668     the main stack loop.  There is no auto transmit for UDP segments.
00669   ***************************************************************************/
00670 void UDPFlush(void)
00671 {
00672     UDP_HEADER      h;
00673     UDP_SOCKET_INFO *p;
00674     WORD            wReadPtrSave;
00675     WORD            wChecksum;
00676     WORD            wUDPLength;
00677 
00678     p = &UDPSocketInfo[activeUDPSocket];
00679 
00680     wUDPLength = UDPTxCount + sizeof(UDP_HEADER);
00681 
00682     // Generate the correct UDP header
00683     h.SourcePort        = swaps(p->localPort);
00684     h.DestinationPort   = swaps(p->remotePort);
00685     h.Length            = swaps(wUDPLength);
00686     h.Checksum          = 0x0000;
00687     
00688     // Calculate IP pseudoheader checksum if we are going to enable 
00689     // the checksum field
00690     #if defined(UDP_USE_TX_CHECKSUM)
00691     {
00692         PSEUDO_HEADER   pseudoHeader;
00693         
00694         // MODIFIX: Use the eWicht structure sIPConfig.
00695         pseudoHeader.SourceAddress  = sIPConfig.MyIPAddr;
00696         pseudoHeader.DestAddress    = p->remoteNode.IPAddr;
00697         pseudoHeader.Zero           = 0x0;
00698         pseudoHeader.Protocol       = IP_PROT_UDP;
00699         pseudoHeader.Length         = wUDPLength;
00700         SwapPseudoHeader(pseudoHeader);
00701         h.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader, sizeof(pseudoHeader));
00702     }
00703     #endif
00704 
00705     // Position the hardware write pointer where we will need to 
00706     // begin writing the IP header
00707     MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
00708     
00709     // Write IP header to packet
00710     IPPutHeader(&p->remoteNode, IP_PROT_UDP, wUDPLength);
00711 
00712     // Write UDP header to packet
00713     MACPutArray((BYTE*)&h, sizeof(h));
00714     
00715     // Calculate the final UDP checksum and write it in, if enabled
00716     #if defined(UDP_USE_TX_CHECKSUM)
00717     {
00718         wReadPtrSave = MACSetReadPtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER));
00719         wChecksum = CalcIPBufferChecksum(wUDPLength);
00720         MACSetReadPtr(wReadPtrSave);
00721         MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + 6);    // 6 is the offset to the Checksum field in UDP_HEADER
00722         MACPutArray((BYTE*)&wChecksum, sizeof(wChecksum));
00723     }
00724     #endif
00725     
00726     // Transmit the packet
00727     MACFlush();
00728 
00729     // Reset packet size counter for the next TX operation
00730     UDPTxCount = 0;
00731     LastPutSocket = INVALID_UDP_SOCKET;
00732 }
00733 
00734 
00735 
00736 /****************************************************************************
00737   Section:
00738     Receive Functions
00739   ***************************************************************************/
00740 
00741 /*****************************************************************************
00742   Function:
00743     WORD UDPIsGetReady(UDP_SOCKET s)
00744 
00745   Summary:
00746     Determines how many bytes can be read from the UDP socket.
00747     
00748   Description:
00749     This function determines if bytes can be read from the specified UDP
00750     socket.  It also prepares the UDP module for reading by setting the 
00751     indicated socket as the currently active connection.
00752 
00753   Precondition:
00754     UDPInit() must have been previously called.
00755 
00756   Parameters:
00757     s - The socket to be made active (which has already been opened or is
00758         listening)
00759 
00760   Returns:
00761     The number of bytes that can be read from this socket.
00762   ***************************************************************************/
00763 WORD UDPIsGetReady(UDP_SOCKET s)
00764 {
00765     activeUDPSocket = s;
00766     if(SocketWithRxData != s)
00767         return 0;
00768 
00769     // If this is the very first time we are accessing this packet, 
00770     // move the read point to the begining of the packet.
00771     if(Flags.bFirstRead)
00772     {
00773         Flags.bFirstRead = 0;
00774         UDPSetRxBuffer(0);
00775     }
00776 
00777     return UDPRxCount;
00778 }
00779 
00780 /*****************************************************************************
00781   Function:
00782     BOOL UDPGet(BYTE *v)
00783 
00784   Summary:
00785     Reads a byte from the currently active socket.
00786     
00787   Description:
00788     This function reads a single byte from the currently active UDP socket, 
00789     while decrementing the remaining buffer length.  UDPIsGetReady should be 
00790     used before calling this function to specify the currently active socket.
00791 
00792   Precondition:
00793     UDPIsGetReady() was previously called to specify the current socket.
00794 
00795   Parameters:
00796     v - The buffer to receive the data being read.
00797 
00798   Return Values:
00799     TRUE - A byte was successfully read
00800     FALSE - No data remained in the read buffer
00801   ***************************************************************************/
00802 BOOL UDPGet(BYTE *v)
00803 {
00804     // Make sure that there is data to return
00805     if((wGetOffset >= UDPRxCount) || (SocketWithRxData != activeUDPSocket))
00806         return FALSE;
00807 
00808     *v = MACGet();
00809     wGetOffset++;
00810 
00811     return TRUE;
00812 }
00813 
00814 
00815 /*****************************************************************************
00816   Function:
00817     WORD UDPGetArray(BYTE *cData, WORD wDataLen)
00818 
00819   Summary:
00820     Reads an array of bytes from the currently active socket.
00821     
00822   Description:
00823     This function reads an array from bytes to the currently active UDP socket, 
00824     while decrementing the remaining buffer length.  UDPIsGetReady should be 
00825     used before calling this function to specify the currently active socket.
00826 
00827   Precondition:
00828     UDPIsPutReady() was previously called to specify the current socket.
00829 
00830   Parameters:
00831     cData - The buffer to receive the bytes being read.
00832     wDateLen - Number of bytes to be read from the socket.
00833     
00834   Returns:
00835     The number of bytes successfully read from the UDP buffer.  If this
00836     value is less than wDataLen, then the buffer was emptied and no more 
00837     data is available.
00838   ***************************************************************************/
00839 WORD UDPGetArray(BYTE *cData, WORD wDataLen)
00840 {
00841     WORD wBytesAvailable;
00842     
00843     // Make sure that there is data to return
00844     if((wGetOffset >= UDPRxCount) || (SocketWithRxData != activeUDPSocket))
00845         return 0;
00846 
00847     // Make sure we don't try to read more data than exists
00848     wBytesAvailable = UDPRxCount - wGetOffset;
00849     if(wBytesAvailable < wDataLen)
00850         wDataLen = wBytesAvailable;
00851 
00852     wDataLen = MACGetArray(cData, wDataLen);
00853     wGetOffset += wDataLen;
00854 
00855     return wDataLen;
00856 }
00857 
00858 /*****************************************************************************
00859   Function:
00860     void UDPDiscard(void)
00861 
00862   Summary:
00863     Discards any remaining RX data from a UDP socket.
00864     
00865   Description:
00866     This function discards any remaining received data in the currently 
00867     active UDP socket.
00868 
00869   Precondition:
00870     UDPIsGetReady() was previously called to select the currently active
00871     socket.
00872 
00873   Parameters:
00874     None
00875     
00876   Returns:
00877     None
00878 
00879   Remarks:
00880     It is safe to call this function more than is necessary.  If no data is
00881     available, this function does nothing.
00882   ***************************************************************************/
00883 void UDPDiscard(void)
00884 {
00885     if(!Flags.bWasDiscarded)
00886     {
00887         MACDiscardRx();
00888         UDPRxCount = 0;
00889         Flags.bWasDiscarded = 1;
00890     }
00891 }
00892 
00893 
00894 
00895 /****************************************************************************
00896   Section:
00897     Data Processing Functions
00898   ***************************************************************************/
00899 
00900 /*****************************************************************************
00901   Function:
00902     BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
00903 
00904   Summary:
00905     Handles an incoming UDP segment.
00906     
00907   Description:
00908     This function handles an incoming UDP segment to determine if it is 
00909     acceptable and should be handed to one of the stack applications for
00910     processing.
00911 
00912   Precondition:
00913     UDPInit() has been called an a UDP segment is ready in the MAC buffer.
00914 
00915   Parameters:
00916     remoteNode - The remote node that sent this segment.
00917     localIP - The destination IP address for this segment.
00918     len - Total length of the UDP segment.
00919     
00920   Return Values:
00921     TRUE - A valid packet is waiting and the stack applications should be
00922         called to handle it.
00923     FALSE - The packet was discarded.
00924   ***************************************************************************/
00925 
00926 BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
00927 {
00928     UDP_HEADER      h;
00929     UDP_SOCKET      s;
00930     PSEUDO_HEADER   pseudoHeader;
00931     DWORD_VAL       checksums;
00932 
00933     // MODIFIX: Check for valid IP addresses here, else return!
00934     // Valid IP addresses:
00935     // 1) Broadcast (255.255.255.255)
00936     // 2) Multicast (All in-between 224.0.0.0 and 239.255.255.255)
00937     // 3) Network-Broadcast (i.e for a 192.168.1/24 network this is 192.168.1.255)
00938     //      ->  not supported and therefore commented out.
00939     // 4) Unicast with matching IP address.
00940     if ((localIP->Val != 0xFFFFFFFFul) && 
00941         ((localIP->v[0] < 224) || (localIP->v[0] > 239)) &&
00942 //      (localIP->Val != (sIPConfig.MyIPAddr.Val | (~sIPConfig.MyMask.Val))) &&
00943         (localIP->Val != sIPConfig.MyIPAddr.Val))
00944     {
00945         return FALSE;
00946     }
00947 
00948 
00949     SocketWithRxData = INVALID_UDP_SOCKET;
00950     UDPRxCount = 0;
00951 
00952     // Retrieve UDP header.
00953     MACGetArray((BYTE*)&h, sizeof(h));
00954 
00955     h.SourcePort        = swaps(h.SourcePort);
00956     h.DestinationPort   = swaps(h.DestinationPort);
00957     h.Length            = swaps(h.Length) - sizeof(UDP_HEADER);
00958 
00959     // See if we need to validate the checksum field (0x0000 is disabled)
00960     if(h.Checksum)
00961     {
00962         // Calculate IP pseudoheader checksum.
00963         pseudoHeader.SourceAddress      = remoteNode->IPAddr;
00964         pseudoHeader.DestAddress.Val    = localIP->Val;
00965         pseudoHeader.Zero               = 0x0;
00966         pseudoHeader.Protocol           = IP_PROT_UDP;
00967         pseudoHeader.Length             = len;
00968 
00969         SwapPseudoHeader(pseudoHeader);
00970     
00971         checksums.w[0] = ~CalcIPChecksum((BYTE*)&pseudoHeader,
00972                                         sizeof(pseudoHeader));
00973     
00974     
00975         // Now calculate UDP packet checksum in NIC RAM -- should match pseudoHeader
00976         IPSetRxBuffer(0);
00977         checksums.w[1] = CalcIPBufferChecksum(len);
00978     
00979         if(checksums.w[0] != checksums.w[1])
00980         {
00981             MACDiscardRx();
00982             return FALSE;
00983         }
00984     }
00985 
00986     s = FindMatchingSocket(&h, remoteNode, localIP);
00987     if(s == INVALID_UDP_SOCKET)
00988     {
00989         // If there is no matching socket, There is no one to handle
00990         // this data.  Discard it.
00991         MACDiscardRx();
00992         return FALSE;
00993     }
00994     else
00995     {
00996         SocketWithRxData = s;
00997         UDPRxCount = h.Length;
00998         Flags.bFirstRead = 1;
00999         Flags.bWasDiscarded = 0;
01000     }
01001 
01002     // MODIFIX: Add this request for a quick processing of the MDNS frames. 
01003     // Especially the remote node and destination data is needed by MDNS 
01004     // responder for answering via MDNS unicasts.
01005     if(UDPSocketInfo[s].remotePort == MDNS_PORT)
01006     {
01007         MDNSProcessFrame(remoteNode, localIP);
01008         return FALSE;
01009     }
01010 
01011     return TRUE;
01012 }
01013 
01014 /*****************************************************************************
01015   Function:
01016     static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h, NODE_INFO *remoteNode,
01017                                             IP_ADDR *localIP)
01018 
01019   Summary:
01020     Matches an incoming UDP segment to a currently active socket.
01021     
01022   Description:
01023     This function attempts to match an incoming UDP segment to a currently
01024     active socket for processing.
01025 
01026   Precondition:
01027     UDP segment header and IP header have both been retrieved.
01028 
01029   Parameters:
01030     h - The UDP header that was received.
01031     remoteNode - IP and MAC of the remote node that sent this segment.
01032     localIP - IP address that this segment was destined for.
01033     
01034   Returns:
01035     A UDP_SOCKET handle of a matching socket, or INVALID_UDP_SOCKET when no
01036     match could be made.
01037   ***************************************************************************/
01038 static UDP_SOCKET FindMatchingSocket(UDP_HEADER *h,
01039                                      NODE_INFO *remoteNode,
01040                                      IP_ADDR *localIP)
01041 {
01042     UDP_SOCKET s;
01043     UDP_SOCKET partialMatch;
01044     UDP_SOCKET_INFO *p;
01045 
01046     partialMatch = INVALID_UDP_SOCKET;
01047 
01048     p = UDPSocketInfo;
01049     for ( s = 0; s < MAX_UDP_SOCKETS; s++ )
01050     {
01051         // This packet is said to be matching with current socket:
01052         // 1. If its destination port matches with our local port and
01053         // 2. Packet source IP address matches with socket remote IP address.
01054         //    OR this socket had transmitted packet with destination address as broadcast (subnet or limited broadcast).
01055         if ( p->localPort == h->DestinationPort )
01056         {
01057             if(p->remotePort == h->SourcePort)
01058             {
01059                 // MODIFIX: Special handling for MDNS frames:
01060                 if (p->remotePort == MDNS_PORT)
01061                 {
01062                     return s;
01063                 }
01064 
01065                 // MODIFIX: Removed the IP request, is done before.
01066                 if (p->remoteNode.IPAddr.Val == remoteNode->IPAddr.Val)
01067                 {
01068                     return s;
01069                 }
01070             }
01071 
01072             partialMatch = s;
01073         }
01074         p++;
01075     }
01076 
01077     if ( partialMatch != INVALID_UDP_SOCKET )
01078     {
01079         p = &UDPSocketInfo[partialMatch];
01080 
01081         memcpy((void*)&p->remoteNode,
01082                 (const void*)remoteNode, sizeof(p->remoteNode));
01083 
01084         p->remotePort = h->SourcePort;
01085     }
01086     return partialMatch;
01087 }
01088 
01089 
01092 
01093 // MODIFIX: Added the following function for retrieving the amount of already
01094 // put bytes.
01095 WORD UDPGetPutOffset(void)
01096 {
01097     return wPutOffset;
01098 }
01099 
01102 // MODIFIX: Added the following function for retrieving the amount of already
01103 // got bytes.
01104 
01105 WORD UDPGetGetOffset(void)
01106 {
01107     return wGetOffset;
01108 }
01109 

Generated on Sun Nov 27 20:02:39 2011 for eWicht by  doxygen 1.5.5