Project Embedded Systems E-ict Denayer

Dependencies:   BSP_DISCO_F746NG F7_Ethernet LCD_DISCO_F746NG TS_DISCO_F746NG mbed-rtos mbed

ping.h

Committer:
Ayrton_L
Date:
2017-01-21
Revision:
0:16bcf70d262e
Child:
1:a2f7adf6db3d

File content as of revision 0:16bcf70d262e:

#ifndef _PING_H_
#define _PING_H_

#include "lwip/opt.h"
#include "lwip/mem.h"
#include "lwip/raw.h"
#include "lwip/icmp.h"
#include "lwip/netif.h"
#include "lwip/sys.h"
#include "lwip/timers.h"
#include "lwip/inet_chksum.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"

#ifndef PING_RCV_TIMEO                              //ping timeout... geen antwoord binnen deze tijd => timeout request
#define PING_RCV_TIMEO 1000
#endif

#ifndef PING_ID
#define PING_ID        0x2601                       //identifier om te matchen (antwoord matched hiermee. Linux => uniek, Windows => vast, maar wel verschillend per vesrie), subtiele hint 2601 voor beter resultaat? :)
#endif

#ifndef PING_DATA_SIZE                              //grootte payload: "random" data die ook gematched moet worden in het antwoord
#define PING_DATA_SIZE 32
#endif

#ifndef PING_DELAY                                  
#define PING_DELAY     500
#endif

#ifndef PING_RESULT
#define PING_RESULT(ping_ok)
#endif

static void v_PingOntvang( int32_t l_SocketReturn );
static void v_MaakPingRequest( struct icmp_echo_hdr *x_ICMPEchoHdr, uint16_t us_Lenght );
static err_t ux_Ping( int32_t l_SocketReturn, ip_addr_t *x_IPAddr );
static uint16_t us_PingSequenceNummer;

static void v_MaakPingRequest( struct icmp_echo_hdr *x_ICMPEchoHdr, uint16_t us_Lenght )
{
    int32_t ul_I;
    int32_t ul_DataLenght;
    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 );
}

static err_t ux_Ping( int32_t l_SocketReturn, ip_addr_t *x_IPAddr )                                 //pingske leggen
{
    int32_t l_Err;
    struct icmp_echo_hdr *x_ICMPEchoHdr;
    struct sockaddr_in x_VerzendAddr;
    int32_t l_PingGrootte;
    
    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 );
}

static void v_PingOntvang( int32_t l_SocketReturn )
{
    char c_Buffer[64];
    uint32_t ul_FromLen;
    uint32_t ul_RecvLen;
    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);
    
    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
}

void v_Ping( void )
{
    int32_t l_SocketReturn;                                                                //vooral om te kunnen debuggen binnen LWIP, sockets.c ... -1 on fail
    uint32_t ul_TimeOut;
    
    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 ) );

        while ( 1 ) 
        {
            ip_addr_t x_PingTarget = { 0x08080808 };                                              //Google DNS server, uptime 99.9% => vrij betrouwbaar om naar heen te pingen. Behalve in landen zoals DPRK
           
            if ( ux_Ping( l_SocketReturn, &x_PingTarget ) == ERR_OK ) 
            {
                v_PingOntvang( l_SocketReturn );
            } 
            sys_msleep( PING_DELAY );
        }
    }
}

#endif