BaseType_t xProcessReceivedUDPPacket()

in FreeRTOS_UDP_IP.c [300:477]


BaseType_t xProcessReceivedUDPPacket( NetworkBufferDescriptor_t * pxNetworkBuffer,
                                      uint16_t usPort,
                                      BaseType_t * pxIsWaitingForARPResolution )
{
    BaseType_t xReturn = pdPASS;
    FreeRTOS_Socket_t * pxSocket;

    configASSERT( pxNetworkBuffer != NULL );
    configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL );

    /* Map the ethernet buffer to the UDPPacket_t struct for easy access to the fields. */
    const UDPPacket_t * pxUDPPacket = ipCAST_CONST_PTR_TO_CONST_TYPE_PTR( UDPPacket_t, pxNetworkBuffer->pucEthernetBuffer );

    /* Caller must check for minimum packet size. */
    pxSocket = pxUDPSocketLookup( usPort );

    *pxIsWaitingForARPResolution = pdFALSE;

    do
    {
        if( pxSocket != NULL )
        {
            if( xCheckRequiresARPResolution( pxNetworkBuffer ) == pdTRUE )
            {
                /* Mark this packet as waiting for ARP resolution. */
                *pxIsWaitingForARPResolution = pdTRUE;

                /* Return a fail to show that the frame will not be processed right now. */
                xReturn = pdFAIL;
                break;
            }
            else
            {
                /* Update the age of this cache entry since a packet was received. */
                vARPRefreshCacheEntryAge( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
            }

            #if ( ipconfigUSE_CALLBACKS == 1 )
                {
                    /* Did the owner of this socket register a reception handler ? */
                    if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xUDP.pxHandleReceive ) )
                    {
                        struct freertos_sockaddr xSourceAddress, destinationAddress;
                        void * pcData = &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
                        FOnUDPReceive_t xHandler = ( FOnUDPReceive_t ) pxSocket->u.xUDP.pxHandleReceive;
                        xSourceAddress.sin_port = pxNetworkBuffer->usPort;
                        xSourceAddress.sin_addr = pxNetworkBuffer->ulIPAddress;
                        destinationAddress.sin_port = usPort;
                        destinationAddress.sin_addr = pxUDPPacket->xIPHeader.ulDestinationIPAddress;

                        /* The value of 'xDataLength' was proven to be at least the size of a UDP packet in prvProcessIPPacket(). */
                        if( xHandler( ( Socket_t ) pxSocket,
                                      ( void * ) pcData,
                                      ( size_t ) ( pxNetworkBuffer->xDataLength - ipUDP_PAYLOAD_OFFSET_IPv4 ),
                                      &( xSourceAddress ),
                                      &( destinationAddress ) ) != 0 )
                        {
                            xReturn = pdFAIL; /* xHandler has consumed the data, do not add it to .xWaitingPacketsList'. */
                        }
                    }
                }
            #endif /* ipconfigUSE_CALLBACKS */

            #if ( ipconfigUDP_MAX_RX_PACKETS > 0U )
                {
                    if( xReturn == pdPASS )
                    {
                        if( listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ) >= pxSocket->u.xUDP.uxMaxPackets )
                        {
                            FreeRTOS_debug_printf( ( "xProcessReceivedUDPPacket: buffer full %ld >= %ld port %u\n",
                                                     listCURRENT_LIST_LENGTH( &( pxSocket->u.xUDP.xWaitingPacketsList ) ),
                                                     pxSocket->u.xUDP.uxMaxPackets, pxSocket->usLocalPort ) );
                            xReturn = pdFAIL; /* we did not consume or release the buffer */
                        }
                    }
                }
            #endif /* if ( ipconfigUDP_MAX_RX_PACKETS > 0U ) */

            #if ( ipconfigUSE_CALLBACKS == 1 ) || ( ipconfigUDP_MAX_RX_PACKETS > 0U )
                if( xReturn == pdPASS ) /*lint !e774: Boolean within 'if' always evaluates to True, depending on configuration. [MISRA 2012 Rule 14.3, required. */
            #else
                /* xReturn is still pdPASS. */
            #endif
            {
                vTaskSuspendAll();
                {
                    taskENTER_CRITICAL();
                    {
                        /* Add the network packet to the list of packets to be
                         * processed by the socket. */
                        vListInsertEnd( &( pxSocket->u.xUDP.xWaitingPacketsList ), &( pxNetworkBuffer->xBufferListItem ) );
                    }
                    taskEXIT_CRITICAL();
                }
                ( void ) xTaskResumeAll();

                /* Set the socket's receive event */
                if( pxSocket->xEventGroup != NULL )
                {
                    ( void ) xEventGroupSetBits( pxSocket->xEventGroup, ( EventBits_t ) eSOCKET_RECEIVE );
                }

                #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
                    {
                        if( ( pxSocket->pxSocketSet != NULL ) && ( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_READ ) ) != 0U ) )
                        {
                            ( void ) xEventGroupSetBits( pxSocket->pxSocketSet->xSelectGroup, ( EventBits_t ) eSELECT_READ );
                        }
                    }
                #endif

                #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
                    {
                        if( pxSocket->pxUserSemaphore != NULL )
                        {
                            ( void ) xSemaphoreGive( pxSocket->pxUserSemaphore );
                        }
                    }
                #endif

                #if ( ipconfigUSE_DHCP == 1 )
                    {
                        if( xIsDHCPSocket( pxSocket ) != 0 )
                        {
                            ( void ) xSendDHCPEvent();
                        }
                    }
                #endif
            }
        }
        else
        {
            /* There is no socket listening to the target port, but still it might
             * be for this node. */

            #if ( ipconfigUSE_DNS == 1 ) && ( ipconfigDNS_USE_CALLBACKS == 1 )

                /* A DNS reply, check for the source port.  Although the DNS client
                 * does open a UDP socket to send a messages, this socket will be
                 * closed after a short timeout.  Messages that come late (after the
                 * socket is closed) will be treated here. */
                if( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usSourcePort ) == ( uint16_t ) ipDNS_PORT )
                {
                    vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
                    xReturn = ( BaseType_t ) ulDNSHandlePacket( pxNetworkBuffer );
                }
                else
            #endif

            #if ( ipconfigUSE_LLMNR == 1 )
                /* A LLMNR request, check for the destination port. */
                if( ( usPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) ||
                    ( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) )
                {
                    vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
                    xReturn = ( BaseType_t ) ulDNSHandlePacket( pxNetworkBuffer );
                }
                else
            #endif /* ipconfigUSE_LLMNR */

            #if ( ipconfigUSE_NBNS == 1 )
                /* a NetBIOS request, check for the destination port */
                if( ( usPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) ||
                    ( pxUDPPacket->xUDPHeader.usSourcePort == FreeRTOS_ntohs( ipNBNS_PORT ) ) )
                {
                    vARPRefreshCacheEntry( &( pxUDPPacket->xEthernetHeader.xSourceAddress ), pxUDPPacket->xIPHeader.ulSourceIPAddress );
                    xReturn = ( BaseType_t ) ulNBNSHandlePacket( pxNetworkBuffer );
                }
                else
            #endif /* ipconfigUSE_NBNS */
            {
                xReturn = pdFAIL;
            }
        }
    } while( ipFALSE_BOOL );

    return xReturn;
}