Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

tcp/tcpsend.c

Committer:
andrewboyson
Date:
2018-10-29
Revision:
74:c3756bfa960e
Child:
75:603b10404183

File content as of revision 74:c3756bfa960e:

#include <stdint.h>
#include <stdbool.h>

#include    "log.h"
#include    "net.h"
#include "action.h"
#include    "tcp.h"
#include "tcphdr.h"
#include    "tcb.h"
#include    "ip4.h"
#include   "dhcp.h"
#include   "http.h"
#include    "led.h"
#include "tcpsend.h"



static int sendData(void* pPacket, struct tcb* pTcb)
{
    int dataLength = 0;
    char* pData = (char*)pPacket + TcpHdrSizeGet();
    switch (pTcb->locPort)
    {
        case 80:
            HttpSendReply(&dataLength, pData, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo);
            break;
        default:
            break;
    }    
    
    pTcb->lastSendTime = TcbElapsed;
    
    return dataLength;
}

int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb, int sendType)
{
    int dataLength = 0;
    TcpHdrMakeEmpty();
    int locMss = *pSize - TcpHdrSizeGet();
    switch (pTcb->state)
    {
        case TCB_SYN_RECEIVED:
            if (pTcb->bytesSentToRem == 0)
            {
                TcpHdrMssSet(locMss);
                TcpHdrSYN = true;
            }
            break;
            
        case TCB_ESTABLISHED:
            if (!pTcb->sentFin)
            {
                if (pTcb->bytesSentToRem - pTcb->bytesAckdByRem < pTcb->window)
                {
                    if (pTcb->todo)
                    {
                        dataLength = sendData(pPacket, pTcb);
                        if (dataLength < pTcb->remMss)
                        {
                            TcpHdrFIN     = true;
                            pTcb->sentFin = true;
                        }
                    }
                    else
                    {
                        if (pTcb->rcvdFin)
                        {
                            TcpHdrFIN     = true;
                            pTcb->sentFin = true;
                        }
                    }
                }
            }
            break;
    }

    //See if have need to acknowledge received bytes
    bool rcvdSeqHasAdvanced = pTcb->bytesRcvdFromRem > pTcb->bytesAckdToRem;
    
    //Record the number of bytes acknowledged to the remote
    pTcb->bytesAckdToRem = pTcb->bytesRcvdFromRem;
    
    //Specify the start of the data being sent and acknowledge the data received
    TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn;  //Set up the acknowledgement field ready to send
    TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn;  //Set up the start of the message before adding the bytes sent

    //Record the number of bytes sent
    uint32_t bytesToSend = 0;
    if (TcpHdrSYN) bytesToSend += 1;            //Add one to acknowledge the SYN
                   bytesToSend += dataLength;   //Add the number of bytes received
    if (TcpHdrFIN) bytesToSend += 1;            //Add one to acknowledge the FIN

    pTcb->bytesSentToRem += bytesToSend;
    
    if (rcvdSeqHasAdvanced || bytesToSend || sendType == TCP_RESEND_ACK || sendType == TCP_SEND_RESET)
    {
        //Set the acknowledge flag
        TcpHdrACK = true;
        TcpHdrRST = sendType == TCP_SEND_RESET;
        
        //Swap the ports for the reply
        TcpHdrSrcPort = pTcb->locPort;
        TcpHdrDstPort = pTcb->remPort;
                
        //Specify the receive window size to not throttle
        TcpHdrWindow = 4000;
        
        //Write the header
        TcpHdrWriteToPacket(pPacket);
        
        //Calculate the size of the reply
        *pSize = TcpHdrSizeGet() + dataLength;
            
        return ActionMakeFromDestAndTrace(UNICAST, TcpDoTrace && NetTraceStack);
    }
    else
    {
        return DO_NOTHING;
    }
}
int TcpPollForPacketToSend(int* pSize, void* pPacket, int ipType, int* pRemArIndex)
{
    struct tcb* pTcb = TcbGetNext(); //This loops around the TCBs
    if (pTcb->ipType != ipType) return DO_NOTHING;
    *pRemArIndex = pTcb->remArIndex;
    int action = TcpSend(pSize, pPacket, pTcb, TCP_SEND_NORMAL);
    return action;
}