A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

ip4/udptcp4.cpp

Committer:
andrewboyson
Date:
2017-04-16
Revision:
10:f0854784e960
Child:
11:c051adb70c5a

File content as of revision 10:f0854784e960:

#include "mbed.h"
#include  "log.h"
#include  "net.h"
#include "dhcp.h"
#include  "ip4.h"
#include  "tcp.h"
#include  "udp.h"

#define DEBUG false

static uint16_t calculateChecksum(uint8_t pro, uint32_t srcIp, uint32_t dstIp, int size, void* pPacket)
{
    __packed struct pseudo
    {
        uint32_t src;
        uint32_t dst;
        uint8_t  zer;
        uint8_t  pro;
        uint16_t len;
    } pseudo;
    
    pseudo.src = srcIp;
    pseudo.dst = dstIp;
    pseudo.zer = 0;
    pseudo.pro = pro;
    pseudo.len = NetToHost16(size);

    return NetCheckSumTwo(sizeof(pseudo), &pseudo, size, pPacket);
}
static void destIpFromAction(int action, uint32_t* pDstIp)
{
    switch (action)
    {
        case UNICAST:
            break;
        case UNICAST_DNS:
            *pDstIp = DhcpDnsServer;
            break;
        case UNICAST_DHCP:
            *pDstIp = DhcpServer;
            break;
        case MULTICAST_NODE:
            *pDstIp = IP4_MULTICAST_ALL_HOSTS;
            break;
        case MULTICAST_ROUTER:
            *pDstIp = IP4_MULTICAST_ALL_ROUTERS;
            break;
        case MULTICAST_MDNS:
            *pDstIp = IP4_MULTICAST_DNS_ADDRESS;
            break;
        case MULTICAST_LLMNR:
            *pDstIp = IP4_MULTICAST_LLMNR_ADDRESS;
            break;
        case BROADCAST:
            *pDstIp = IP4_BROADCAST_ADDRESS;
            break;
        default:
            LogTimeF("UdpTcp4 destIpFromAction unknown action %d\r\n", action);
            return;
    }
}
static void finalisePacket(uint8_t pro, int action, void* pPacket, int size, uint32_t* pSrcIp, uint32_t* pDstIp)
{    
    if (!action) return;
    
    destIpFromAction(action, pDstIp);
    
    *pSrcIp = DhcpLocalIp;
    
    switch (pro)
    {
        case TCP: TcpMakeHeader(size, pPacket); break;
        case UDP: UdpMakeHeader(size, pPacket); break;
    }
    
    uint16_t checksum = calculateChecksum(pro, *pSrcIp, *pDstIp, size, pPacket);
    
    switch (pro)
    {
        case TCP: TcpAddChecksum(pPacket, checksum); break;
        case UDP: UdpAddChecksum(pPacket, checksum); break;
    }
    
    if (DEBUG) TcpLogHeader("IPv4 packet sent", pPacket, 0);
}

int Tcp4HandleReceivedPacket(uint32_t* pSrcIp, uint32_t* pDstIp, int* pSize, void * pPacket)
{   
    uint16_t calculatedChecksum = calculateChecksum(TCP, *pSrcIp, *pDstIp, *pSize, pPacket);
    if (DEBUG) TcpLogHeader("IPv4 packet received", pPacket, calculatedChecksum);
 
    TcpReadHeader(pPacket, *pSize);
        
    int action = TcpHandleReceivedPacket(pSize, pPacket);
    
    *pDstIp = *pSrcIp;
    
    finalisePacket(TCP, action, pPacket, *pSize, pSrcIp, pDstIp);
  
    return action;
}

int Udp4HandleReceivedPacket(uint32_t* pSrcIp, uint32_t* pDstIp, int* pSize, void * pPacket)
{   
    uint16_t calculatedChecksum = calculateChecksum(UDP, *pSrcIp, *pDstIp, *pSize, pPacket);
    if (DEBUG) UdpLogHeader("IPv4 packet received", pPacket, calculatedChecksum);
 
    UdpReadHeader(pPacket, *pSize);
    
    int action = UdpHandleReceivedPacket(pSize, pPacket);

    *pDstIp = *pSrcIp;
    
    finalisePacket(UDP, action, pPacket, *pSize, pSrcIp, pDstIp); //Note that the ports are reversed here
  
    return action;
}
int Udp4PollForPacketToSend(void* pPacket, int* pSize, uint32_t* pSrcIp, uint32_t* pDstIp)
{        
    int action = UdpPollForPacketToSend(IPV4, pSize, pPacket);
    
    finalisePacket(UDP, action, pPacket, *pSize, pSrcIp, pDstIp);
        
    return action;
}