Exemple #1
0
uint32_t UDPRead(HSOCKET hSocket, uint8_t * pbRead, uint16_t cbRead, IPSTATUS * pStatus)
{
    UDPSOCKET *     pSocket     = (UDPSOCKET *) hSocket;

    uint32_t cb = 0;

    if(pSocket != NULL)
    {
        SMGR *  pSMGR = alloca(pSocket->cbRxSMGR);

        if(pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR))
        {
            cb = UDPPeekSMGR(pSocket, (HSMGR) pSMGR, 0, pbRead, cbRead, pStatus);

            // if this is the whole datagram
            // note, the > part should never happen, cb should always
            // be cb <= pSocket->cbNextDataGram and this condition
            // should be cb == pSocket->cbNextDataGram; but should somehow
            // > happen, this will offer some correction
            if(cb >= pSocket->cbNextDataGram)
            {
                // move the begining to the next datagram
                SMGRMoveEnd((HSMGR) pSMGR, cb + sizeof(uint16_t), SMGRAtBegining);

                // read the next 2 bytes for the datagarm size if it exists
                if(SMGRRead((HSMGR) pSMGR, 0, &pSocket->cbNextDataGram, sizeof(uint16_t)) != sizeof(uint16_t))
                {
                    pSocket->cbNextDataGram = 0;
                }
            }

            // otherwise it is a partial datagram read
            else
            {
                // move the begining to after what we read, but leave room to
                // write the remaining datagram size
                SMGRMoveEnd((HSMGR) pSMGR, cb, SMGRAtBegining);

                // update the remaining datagram size
                pSocket->cbNextDataGram -= cb;
                SMGRWrite((HSMGR) pSMGR, 0, &pSocket->cbNextDataGram, sizeof(uint16_t));
            }

            // save away the table that is stored on the stack
            // this should not fail! It is a fixed size and already allocated
            SMGRWrite((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR);
        }
    }

    return(cb);
}
Exemple #2
0
/*****************************************************************************
  Function:
	uint32_t TCPSend(SOCKET *  pSocket, const void * pv, uint32_t cb, IPSTATUS * pStatus)

  Description:
         Stuff data into the socket to be sent on the next regularly scheduled send. Because of congestion
         control, this may take up to a fraction of a second to send. If you want it to go out immediately
         then call TCPFlush on the socket immediately after this call.

  Parameters:
	pSocket:        The socket to send the data on

        pv:             a pointer to a buffer of data to send

        cbReq:          The number of bytes to send.

        pStatus:        A pointer to a status variable to recieve the state of the send

  Returns:
        Number of bytes actually sent, could be less than requested if the socket is full.

  ***************************************************************************/
uint32_t TCPWrite(HSOCKET hSocket, const void * pv, uint32_t cbReq, IPSTATUS * pStatus)
{
    TCPSOCKET * pSocket = (TCPSOCKET *) hSocket;
    uint32_t    cb      = 0;

    if(pSocket == NULL)
    {
        AssignStatusSafely(pStatus, ipsSocketNULL);
        return(0);
    }

    // we can only write data if we are in the established state
    if(TCPIsEstablished(pSocket, pStatus))
    {
        SMGR *  pSMGR = (SMGR*)alloca(pSocket->cbTxSMGR);

        if(cbReq > 0 && pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, pSocket->cbRxSMGR, pSMGR, pSocket->cbTxSMGR) == pSocket->cbTxSMGR))
        {

            // This may seem like an odd place to do this, but I will update the sndUNA pointers here
            // I do this here instead of in the ACK processing because I do not want to take the time to open up the
            // stream in the ACK process, I just want to update the sndUNA pointer and move on. The downside of this is that
            // we may hold some pages longer than we need, but before I take MORE memory in the write, I will free those pages
            // which is why I will do that here before we WRITE our data below.
            TCPScaleSndIndexes(pSocket, pSMGR);

            // after we have scaled our pointers and potentially released some memory, we can
            // write as much data as we can to the stream
            cb  = SMGRWrite((HSMGR) pSMGR, SMGRcbStream(pSMGR), pv, cbReq);
            pSocket->sndEND += cb;

            // save away the table that is stored on the stack
            // this should not fail! It is a fixed size and already allocated
            SMGRWrite((HSMGR) &pSocket->smgrRxTxBuff, pSocket->cbRxSMGR, pSMGR, pSocket->cbTxSMGR);
        }
    }

    return(cb);
}
Exemple #3
0
uint32_t TCPAddRxDataToSocket(TCPSOCKET * pSocket, uint32_t seqNbr, uint8_t * pb, uint32_t cb)
{
    SMGR *      pSMGR = (SMGR*)alloca(pSocket->cbRxSMGR);
    uint32_t    rcvNXT = pSocket->rcvNXT + SEQBOUNDARY;

    // seqNbr is tricky, it has been normalized to rcvIRS
    // and may be very close to rcvUNR which is typically 0
    // so if seqNbr is < rcvNXT it could be less than rcvUNR, or an unsigned less than 0
    // or for an unsigned, very large; which would give us a false large seqNbr.
    // the MAX segment we can get is 64K, so as long as we scale this down so at least seqNbr + 64K < 2^^32, we can do a compare
    // and see if seqNbr < rcvNXT reliably. SEQBOUNDARY is 0x80000000 which is half way into the linear uint32_t range
    // scale seqNbr and rcvNXT and we can do a reliable < check.
    // Rip off data we have already received
    seqNbr += SEQBOUNDARY;
    if(seqNbr < rcvNXT)
    {
        pb += (rcvNXT - seqNbr);
        cb -= (rcvNXT - seqNbr);
    }

    // get our stream pointer
    if(cb > 0 && pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR))
    {
        // write as much data as we can to the stream
        cb  = SMGRWrite((HSMGR) pSMGR, SMGRcbStream(pSMGR), pb, cb);

        // add the bytes written to our rcvNXT pointer
        pSocket->rcvNXT += cb;

        // save away the table that is stored on the stack
        // this should not fail! It is a fixed size and already allocated
        SMGRWrite((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR);

        return(cb);
    }

    return(0);
}
Exemple #4
0
static uint32_t UDPProcessRx(IPSTACK * pIpStack, UDPSOCKET * pSocket)
{
    SMGR *      pSMGR = alloca(pSocket->cbRxSMGR);
    uint32_t    cbRet = 0;

    if(pIpStack->cbPayload > 0 && pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR))
    {
        uint32_t iEnd = SMGRcbStream(pSMGR);

        // put in the size prefex
        uint32_t cbWritten = SMGRWrite((HSMGR) pSMGR, iEnd, &pIpStack->cbPayload, sizeof(uint16_t));

        // put in the data
        cbWritten += SMGRWrite((HSMGR) pSMGR, iEnd + cbWritten, pIpStack->pPayload, pIpStack->cbPayload);

        // check to see that we wrote everything.
        if(cbWritten == (pIpStack->cbPayload + sizeof(uint16_t)))
        {
            if(pSocket->cbNextDataGram == 0)
            {
                pSocket->cbNextDataGram = pIpStack->cbPayload;
            }
            cbRet = pIpStack->cbPayload;
        }

        // we failed to save, so discard the datagram and put the stream back to where it was
        else
        {
            SMGRMoveEnd((HSMGR) pSMGR, iEnd, SMGRAtEnding);
        }

        // save away the table that is stored on the stack
        // this should not fail! It is a fixed size and already allocated
        SMGRWrite((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR);
    }

    return(cbRet);
}
Exemple #5
0
void UDPDiscard(HSOCKET hSocket)
{
    UDPSOCKET *     pSocket     = (UDPSOCKET *) hSocket;

    if(pSocket != NULL)
    {
        SMGR *  pSMGR = alloca(pSocket->cbRxSMGR);

        if(pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR))
        {
            uint32_t iEnd = SMGRcbStream(pSMGR);

            SMGRMoveEnd((HSMGR) pSMGR, iEnd, SMGRAtBegining);

            // save away the table that is stored on the stack
            // this should not fail! It is a fixed size and already allocated
            SMGRWrite((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR);
        }
    }
}
Exemple #6
0
/*****************************************************************************
  Function:
	uint32_t TCPRead(SOCKET *  pSocket, void * pv, uint32_t cb, IPSTATUS * pStatus)

  Description:
        Reads bytes out of the receive buffer. We call this receive instead of read because RFC 793 calls it receive.

  Parameters:
	pSocket:        The socket to read the bytes from
        pv:             A buffer to receive the data
        cb:             Max size of the buffer to receive the data
        pStatus:        A pointer to a status variable to recieve the state of the socket as a status

  Returns:
        Number of bytes read

  ***************************************************************************/
uint32_t TCPRead(HSOCKET hSocket, void * pbRead, uint32_t cbRead, IPSTATUS * pStatus)
{
    TCPSOCKET *     pSocket     = (TCPSOCKET *) hSocket;
    IPSTATUS        status      = ipsSocketNULL;
    uint32_t cb = 0;

    if(pSocket != NULL && pSocket->cbRxSMGR > 0)
    {
        SMGR *  pSMGR = (SMGR*)alloca(pSocket->cbRxSMGR);

        if(SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR)
        {
            cb = TCPPeekSMGR(pSocket, (HSMGR) pSMGR, 0, (u8*)pbRead, cbRead, &status);

            if(cb > 0)
            {
                // move the begining to after what we read
                SMGRMoveEnd((HSMGR) pSMGR, cb, SMGRAtBegining);

                // apply the read bytes to our base
                pSocket->rcvIRS += cb;

                // and now fix up to the base
                pSocket->rcvNXT -= cb;
                pSocket->rcvUP  -= cb;
//                pSocket->rcvSeqAhead -= cb;
            }

            // save away the table that is stored on the stack
            // this should not fail! It is a fixed size and already allocated
            SMGRWrite((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR);
        }
        else
        {
            status = ipsFailedToReadStreamBuffer;
        }
    }

    AssignStatusSafely(pStatus, status);
    return(cb);
}
Exemple #7
0
/*****************************************************************************
  Function:
	void TCPDiscard(SOCKET *  pSocket)

  Description:
        Discards all unread bytes in the sockets receive buffer.

  Parameters:
	hSocket:        The socket to clear the receive buffer from

  Returns:
        None

  ***************************************************************************/
void TCPDiscard(HSOCKET hSocket)
{
    TCPSOCKET *     pSocket     = (TCPSOCKET *) hSocket;

    if(pSocket != NULL && pSocket->cbRxSMGR > 0)
    {
        SMGR *  pSMGR = (SMGR*)alloca(pSocket->cbRxSMGR);

        if(SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR)
        {
            uint32_t iEnd = SMGRcbStream(pSMGR);

            // clear the stream by moving to the end
            SMGRMoveEnd((HSMGR) pSMGR, iEnd, SMGRAtBegining);

            // pretend like we read it
            // apply the read bytes to our base
            pSocket->rcvIRS += pSocket->rcvNXT;

            // and now fix up to the base
            pSocket->rcvNXT = 0;
            pSocket->rcvUP  = 0;
            
//            if(pSocket->rcvSeqAhead >= pSocket->rcvNXT)
//            {
//                pSocket->rcvSeqAhead -= pSocket->rcvNXT;
//            }
//            else
//            {
//                pSocket->rcvSeqAhead = 0;
//            }

            // save away the table that is stored on the stack
            // this should not fail! It is a fixed size and already allocated
            SMGRWrite((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR);
        }
    }
}
Exemple #8
0
// this will free the socket if it can't open it
TCPSOCKET * TCPInitSocket(const LLADP * pLLAdp, TCPSOCKET * pSocketOpen, HPMGR hPMGR, const void * pIPvXDest, uint16_t portRemote, uint16_t portLocal, IPSTATUS * pStatus)
{
    IPSTATUS    status          = ipsSuccess;
    SMGR *      pSMGR           = NULL;
    uint32_t    cb              = 0;
    uint32_t    cPages          = 0;

    if(pSocketOpen == NULL)
    {
        AssignStatusSafely(pStatus, ipsSocketNULL);
        return(NULL);
    }
    else if(hPMGR == NULL)
    {
        AssignStatusSafely(pStatus, ipsNoPMGRGiven);
    }

    // find a port
    if(portLocal == portDynamicallyAssign)
    {
        portLocal = GetEphemeralPort(&g_ffptActiveTCPSockets, &g_nextTCPEphemeralPort);
    }

    // get the sequence number
    // we have to get this BEFORE we memset the socket
    // as the timewait may be the socket we are clearing.
    // also, if we are listening, we can only assign the sequence number
    // when we now our remote port and IP as to not duplicate and to watch seq numbers.
    if(portRemote != portListen)
    {
        SKTPORTPAIR portPair;    // remote, local
        portPair.portRemote =   portRemote;
        portPair.portLocal  =   portLocal;

        // worry about the 2MSL timewait issue, get an appropriate sequence number
        if(TCPIsInUse(pLLAdp, portPair.portPair, pIPvXDest))
        {
            AssignStatusSafely(pStatus, ipsPortPairAndIPAlreadyActive);
            return(NULL);
        }
    }

    // build the stream manager to point to the page handler
    // first build the stream to the RxStream and TxStream
    // Rx is the 1st
    pSocketOpen->hPMGR = hPMGR;
    
    // calculate the size of the 2 embedded streams and how to partition the socket stream, stream
    // the Rx is the first indirect stream follwed by the Tx indirect stream in the socket stream
    cb                      = (1 << ((PMGR *) hPMGR)->pf2PerPage);
    cPages                  = ((PMGR *) hPMGR)->cPages;
    pSocketOpen->cbRxSMGR   = GetSMGRSize(min(((cTCPRXPages * cb) - sizeof(SMGR)), cPages));
    pSocketOpen->cbTxSMGR   = GetSMGRSize(min(((cTCPTXPages * cb) - sizeof(SMGR)), cPages));
    cb                      = pSocketOpen->cbRxSMGR + pSocketOpen->cbTxSMGR;

    if(SMGRInit(&pSocketOpen->smgrRxTxBuff, cbMAXTCPSreamRecord, hPMGR) != (HSMGR) &pSocketOpen->smgrRxTxBuff)
    {
        status = ispOutOfMemory;
    }
    else if((pSMGR = (SMGR*)alloca(cb)) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRInit(pSMGR, pSocketOpen->cbRxSMGR, hPMGR) == NULL || SMGRInit((SMGR *) (((uint8_t *) pSMGR) + pSocketOpen->cbRxSMGR), pSocketOpen->cbTxSMGR, hPMGR) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRWrite(&pSocketOpen->smgrRxTxBuff, 0, pSMGR, cb) != cb)
    {
        status = ispOutOfMemory;
    }

    AssignStatusSafely(pStatus, status);
    if(IsIPStatusAnError(status))
    {
        SMGRFree((HSMGR) pSMGR);
        SMGRFree((HSMGR) (((uint8_t *) pSMGR) + pSocketOpen->cbRxSMGR));
        SMGRFree((HSMGR) &pSocketOpen->smgrRxTxBuff);
        IPSReleaseSocket(pSocketOpen);
        return(NULL);
    }

    // make the socket
    pSocketOpen->tcpState       = tcpAllocated;
    pSocketOpen->s.portLocal    = portLocal;
    pSocketOpen->s.portRemote   = portRemote;
    pSocketOpen->s.pLLAdp       = pLLAdp;
    memcpy(&pSocketOpen->s.ipRemote, pIPvXDest, ILIPSize(pLLAdp));

    // get a new seq nbr
    pSocketOpen->sndISS = TCPGetSeqNumber(pLLAdp);

    // max I will allow to come in. RFC 1122 4.2.2.6
    pSocketOpen->cbLocalMSS     = min((PMGRMaxAlloc(hPMGR) >> 2), (uint16_t) (LLGetMTUR(pLLAdp) - 20));

    // Jacobson rule
    pSocketOpen->RTTsa          = RTTsaINIT;
    pSocketOpen->RTTsv          = RTTsvINIT;
    pSocketOpen->tRTO_SET       = RTO(pSocketOpen);
    pSocketOpen->tRTOCur        = pSocketOpen->tRTO_SET;

    return(pSocketOpen);
}
Exemple #9
0
HSOCKET UDPOpenWithSocket(const LLADP * pLLAdp, UDPSOCKET * pSocket, HPMGR hPMGR, const void * pIPvXDest, uint16_t portRemote, uint16_t portLocal, IPSTATUS * pStatus)
{
//    uint32_t    portPair    = 0;
    IPSTATUS    status      = ipsSuccess;
    SMGR *      pSMGR       = NULL;
    uint32_t    cb          = 0;

    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if(pSocket == NULL)
    {
        status = ipsSocketNULL;
    }
    else if(hPMGR == NULL)
    {
        status = ipsNoPMGRGiven;
    }
    else if(pIPvXDest == NULL)
    {
        status = ipsIPAddressIsNull;
    }
    // get the local port
    else if(portLocal == portDynamicallyAssign)
    {
        portLocal = GetEphemeralPort(&g_ffptListeningUDPSockets, &g_nextUDPEphemeralPort);
    }

    AssignStatusSafely(pStatus, status);
    if(IsIPStatusAnError(status))
    {
        return(NULL);
    }

    // build the stream manager to point to the page handler
    // first build the stream to the RxStream
    pSocket->hPMGR = hPMGR;
    if(SMGRInit(&pSocket->smgrRxBuff, cbMAXUDPSreamRecord, hPMGR) != (HSMGR) &pSocket->smgrRxBuff)
    {
        status = ispOutOfMemory;
    }
    else if((pSMGR = alloca((cb = GetSMGRSize(((PMGR *) hPMGR)->cPages)))) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRInit(pSMGR, cb, hPMGR) == NULL)
    {
        status = ispOutOfMemory;
    }
    else if(SMGRWrite(&pSocket->smgrRxBuff, 0, pSMGR, cb) != cb)
    {
        status = ispOutOfMemory;
    }

    AssignStatusSafely(pStatus, status);
    if(IsIPStatusAnError(status))
    {
        SMGRFree((HSMGR) pSMGR);
        SMGRFree((HSMGR) &pSocket->smgrRxBuff);
        return(NULL);
    }

    pSocket->s.pLLAdp         = pLLAdp;
    pSocket->s.portRemote     = portRemote;
    pSocket->s.portLocal      = portLocal;

    memcpy(&pSocket->s.ipRemote, pIPvXDest, ILIPSize(pLLAdp));

    pSocket->cbRxSMGR       = cb;

    // put on the listening list.
    FFInPacket(&g_ffptListeningUDPSockets, pSocket);

    // return the socket
    return(pSocket);
}