Project Embedded Systems E-ict Denayer

Dependencies:   BSP_DISCO_F746NG F7_Ethernet LCD_DISCO_F746NG TS_DISCO_F746NG mbed-rtos mbed

ping.cpp

Committer:
Ayrton_L
Date:
2017-08-17
Revision:
5:0518cef07365

File content as of revision 5:0518cef07365:

#include "ping.h"

void v_MaakPingRequest( struct icmp_echo_hdr *x_ICMPEchoHdr, uint16_t us_Lenght )
{
    int32_t ul_I = 0;
    int32_t ul_DataLenght = 0;
    ul_DataLenght = us_Lenght - sizeof( struct icmp_echo_hdr );

    ICMPH_TYPE_SET( x_ICMPEchoHdr, ICMP_ECHO );
    ICMPH_CODE_SET( x_ICMPEchoHdr, 0 );
    x_ICMPEchoHdr->chksum = 0;
    x_ICMPEchoHdr->id = PING_ID;
    x_ICMPEchoHdr->seqno = htons( ++us_PingSequenceNummer );                                   //byte order to netwerk byte order

    for( ul_I = 0; ul_I < ul_DataLenght; ul_I++ )                                             //beetje "random" data erin gooien
    {
        ( ( char* ) x_ICMPEchoHdr )[sizeof( struct icmp_echo_hdr ) + ul_I] = ( char )ul_I;
    }

    x_ICMPEchoHdr->chksum = inet_chksum( x_ICMPEchoHdr, us_Lenght );
}

/*-----------------------------------------------------------*/

err_t ux_Ping( int32_t l_SocketReturn, ip_addr_t *x_IPAddr )                                 //pind maken
{
    int32_t l_Err = 0;
    int32_t l_PingGrootte = 0;
    struct icmp_echo_hdr *x_ICMPEchoHdr;
    struct sockaddr_in x_VerzendAddr;
    
    /* NOTE
    Ik doe een malloc omdat:
Ik voor mijn fucntie om een ping request samen te stellen een pointer nodig heb, 
doordat een pointer geen grootte heeft en slechts enkel een geheugenplaats kan aanduiden 
gebruik ik dus malloc om deze pointer zijn geheugenplaats toe te wijzen waar nadien 
al mijn data van mijn ICMP-struct inkom*/

    l_PingGrootte = sizeof( struct icmp_echo_hdr ) + PING_DATA_SIZE;
    x_ICMPEchoHdr = ( struct icmp_echo_hdr * ) mem_malloc( ( mem_size_t ) l_PingGrootte );          //mallocske doen, is helaas niet toegelaten volgens mistra C :(
                                                                                                    //mem_size_t afhankelijk van hoe groot, uint16_t of uint32_t is van type size_t => malloc heeft verwacht size_t => unsigned type
    if( !x_ICMPEchoHdr )                                                                            //heeft ni veel nut dat functie verdergaat en error gooit als Echo failed
    {
        return ERR_MEM;                                                                             //Out Of memory errorke geven
    }

    v_MaakPingRequest( x_ICMPEchoHdr, ( uint16_t ) l_PingGrootte ); 

    x_VerzendAddr.sin_len = sizeof( x_VerzendAddr );
    x_VerzendAddr.sin_family = AF_INET;
    inet_addr_from_ipaddr( &x_VerzendAddr.sin_addr, x_IPAddr );
    l_Err = lwip_sendto( l_SocketReturn, x_ICMPEchoHdr, l_PingGrootte, 0, ( struct sockaddr* ) &x_VerzendAddr, sizeof( x_VerzendAddr ) );

    mem_free( x_ICMPEchoHdr );

    return ( l_Err ? ERR_OK : ERR_VAL );                                        //geen error = 0 => ERR_OK anders ERR_VAL   zelfs als if(l_Err =0) {return ERR_OK;} else {return ERR_VAL;}
}

/*-----------------------------------------------------------*/

void v_PingOntvang( int32_t l_SocketReturn )
{
    char c_Buffer[64];
    uint32_t ul_FromLen = 0;
    uint32_t ul_RecvLen = 0;
    struct sockaddr_in x_OntvangAdres;
    struct ip_hdr *px_IPHdr;
    struct icmp_echo_hdr *pux_Echo;
    ip_addr_t x_RecvAddr;
    
    ul_RecvLen = lwip_recvfrom( l_SocketReturn, c_Buffer, sizeof( c_Buffer ), 0, ( struct sockaddr* ) &x_OntvangAdres, ( socklen_t* ) &ul_FromLen);                 //word gebruikt om te kijken vanwaar de data komt, na oproep heeft deze dus een waarde
    
    while( ul_RecvLen > 0 ) 
    {
        if( ul_RecvLen >=  sizeof( struct ip_hdr ) + sizeof( struct icmp_echo_hdr ) );
        {        
            inet_addr_to_ipaddr(&x_RecvAddr, &x_OntvangAdres.sin_addr);
            
            px_IPHdr = ( struct ip_hdr * ) c_Buffer;
            pux_Echo = ( struct icmp_echo_hdr * ) ( c_Buffer + ( IPH_HL( px_IPHdr ) * 4));
            
            if( ( pux_Echo->id == PING_ID ) && ( pux_Echo->seqno == htons( us_PingSequenceNummer ) ) )                  //matchen van data, byte order naar netwerk byte order
            {
                PING_RESULT( ( ICMPH_TYPE( iecho ) == ICMP_ER ) );                                                      //ping resultaat processen
                return;
            } 
        }
        
        ul_RecvLen = lwip_recvfrom( l_SocketReturn, c_Buffer, sizeof( c_Buffer ), 0, ( struct sockaddr* ) &x_OntvangAdres, ( socklen_t* ) &ul_FromLen );
    }
    
    PING_RESULT( 0 );                                                                        //ping resultaat processen
}

/*-----------------------------------------------------------*/

uint32_t ul_Ping( ip_addr_t *x_PingTarget )
{
    int32_t l_SocketReturn = 0;                                                                //vooral om te kunnen debuggen binnen LWIP, sockets.c ... -1 on fail
    uint32_t ul_TimeOut = 0;
    
    l_SocketReturn = lwip_socket( AF_INET, SOCK_RAW, IP_PROTO_ICMP );
    ul_TimeOut = PING_RCV_TIMEO;

    if( l_SocketReturn  > -1 ) 
    {
        lwip_setsockopt( l_SocketReturn, SOL_SOCKET, SO_RCVTIMEO, &ul_TimeOut, sizeof( ul_TimeOut ) );
           
        if ( ux_Ping( l_SocketReturn, x_PingTarget ) == ERR_OK ) 
        {
            v_PingOntvang( l_SocketReturn );
        } 
        sys_msleep( PING_DELAY );
        return 0;
    }
    else
    {
        return 1;
    }
}