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); }
/***************************************************************************** Function: uint32_t TCPPeekSMGR(TCPSOCKET * pSocket, HSMGR pSMGR, uint8_t * pbRead, uint16_t cbRead, IPSTATUS * pStatus) Description: Reads bytes out of the receive buffer but does not move the unread pointer, peek or receive will return the same data. Parameters: pSocket: The socket to read the bytes from pSMGR: pointer to an open stream pbRead: A buffer to receive the data cbRead: 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 ***************************************************************************/ static uint32_t TCPPeekSMGR(TCPSOCKET * pSocket, HSMGR pSMGR, uint16_t index, uint8_t * pbRead, uint16_t cbRead, IPSTATUS * pStatus) { int32_t cb = 0; IPSTATUS status = ipsSuccess; if(pSocket == NULL) { status = ipsSocketNULL; } else if(pbRead == NULL || cbRead == 0) { status = ipsBufferNotDefined; } else if(pSocket->s.portRemote == portListen || pSocket->s.portRemote == portInvalid) { status = ipsSocketNotResolved; } else if(pSMGR == NULL) { status = ipsNoSMGRGiven; } else { cb = SMGRRead((HSMGR) pSMGR, index, pbRead, min((SMGRcbStream(pSMGR) - index), cbRead)); } AssignStatusSafely(pStatus, status); return(cb); }
static uint32_t UDPPeekSMGR(UDPSOCKET * pSocket, HSMGR pSMGR, uint16_t index, uint8_t * pbRead, uint16_t cbRead, IPSTATUS * pStatus) { uint32_t cb = 0; if(pSocket == NULL) { AssignStatusSafely(pStatus, ipsSocketNULL); return(0); } else if(pbRead == NULL || cbRead == 0) { AssignStatusSafely(pStatus, ipsBufferNotDefined); return(0); } else if(pSocket->s.portRemote == portListen || pSocket->s.portRemote == portInvalid) { AssignStatusSafely(pStatus, ipsSocketNotResolved); return(0); } cb = min((pSocket->cbNextDataGram - index), cbRead); if(cb > 0 && SMGRRead((HSMGR) pSMGR, (sizeof(uint16_t) + index), pbRead, cb) == cb) { return(cb); } return(0); }
void UDPClose(HSOCKET hSocket) { UDPSOCKET * pSocket = (UDPSOCKET *) hSocket; UDPSOCKET * pSocketCur = NULL; // loop thru all listening sockets looking for this one while((pSocketCur = FFNext(&g_ffptListeningUDPSockets, pSocketCur)) != NULL) { // see if we found it if(pSocket == pSocketCur) { SMGR * pSMGR = alloca(pSocket->cbRxSMGR); // remove it from the listening list FFRemove(&g_ffptListeningUDPSockets, pSocket); if(pSMGR != NULL && (SMGRRead((HSMGR) &pSocket->smgrRxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR)) { // free the datastream SMGRFree((HSMGR) pSMGR); // don't need to write back because these pages are all getting freed as well } // free what is in the socket as well // this is why we don't have to write back SMGRFree((HSMGR) &pSocket->smgrRxBuff); // clear the socket IPSReleaseSocket((TCPSOCKET *) pSocket); return; } } return; }
uint32_t UDPPeekIdx(HSOCKET hSocket, uint32_t index, uint8_t * pbRead, uint16_t cbRead, IPSTATUS * pStatus) { 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)) { // because we are only READing, no need to update the stream tables return(UDPPeekSMGR(pSocket, (HSMGR) pSMGR, index, pbRead, cbRead, pStatus)); } } return(0); }
/***************************************************************************** Function: uint32_t TCPPeek(SOCKET * pSocket, void * pv, uint32_t cb, IPSTATUS * pStatus) Description: Reads bytes out of the receive buffer but does not move the unread pointer, peek or receive will return the same data. Parameters: hSocket: The socket to read the bytes from index: Number of bytes in to start the peek pbRead: A buffer to receive the data cbRead: 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 TCPPeekIdx(HSOCKET hSocket, uint32_t index, void * pbRead, uint32_t cbRead, IPSTATUS * pStatus) { TCPSOCKET * pSocket = (TCPSOCKET *) hSocket; IPSTATUS status = ipsSocketNULL; if(pSocket != NULL && pSocket->cbRxSMGR > 0) { SMGR * pSMGR = (SMGR*)alloca(pSocket->cbRxSMGR); if(SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, pSocket->cbRxSMGR) == pSocket->cbRxSMGR) { // because we are only READing, no need to update the stream tables return(TCPPeekSMGR(pSocket, (HSMGR) pSMGR, (uint16_t) index, (u8*)pbRead, cbRead, pStatus)); } status = ipsFailedToReadStreamBuffer; } AssignStatusSafely(pStatus, status); return(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); } } }
/***************************************************************************** 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); }
/***************************************************************************** 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); }
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); }
/***************************************************************************** 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); } } }
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); }
void TCPResetSocket(TCPSOCKET * pSocket) { if(pSocket == NULL || pSocket->smgrRxTxBuff.pPMGR == NULL) { return; } // fixup the seq nbr generator to make sure we don't reissue seqnbr less than before in time TCPFixupSeqNumber(pSocket->s.pLLAdp, pSocket->sndISS + pSocket->sndNXT); // clean up the socket if we were not listening if(pSocket->tcpState != tcpSynReceivedWhileListening) { uint16_t cb = pSocket->cbRxSMGR + pSocket->cbTxSMGR; SMGR * pSMGR = (SMGR*)alloca(cb); // remove it from the listening list FFRemove(&g_ffptActiveTCPSockets, pSocket); // this works // pSocket->sndISS = 0; // pSocket->tcpState = tcpUnassigned; // pSocket->fSocketOpen = false; // if this does not pass, we will have a memory leak // the alloca should always work. // this frees the Rx and Tx socket buffers if(SMGRRead((HSMGR) &pSocket->smgrRxTxBuff, 0, pSMGR, cb) == cb) { SMGRFree((HSMGR) pSMGR); SMGRFree((HSMGR) (((uint8_t *) pSMGR) + pSocket->cbRxSMGR)); } // free the pointer to the RxTx streams. SMGRFree((HSMGR) &pSocket->smgrRxTxBuff); // release it back to the global pool if we got it from there IPSReleaseSocket(pSocket); // clean the socket // I am assuming this will not break us anywhere. memset(pSocket, 0, sizeof(TCPSOCKET)); return; } // if we were listening, go back to listening // restore the socket to the listening state pSocket->s.portRemote = portListen; memset(&pSocket->s.ipRemote, 0, sizeof(IPv4or6)); memset(&pSocket->s.macRemote, 0, sizeof(MACADDR)); pSocket->tcpState = tcpListen; pSocket->sndISS = 0; // initalize the socket info pSocket->sndISS = TCPGetSeqNumber(pSocket->s.pLLAdp); pSocket->sndNXT = 0; pSocket->sndUNA = 0; pSocket->sndEND = 0; pSocket->sndWND = 0; pSocket->sndPSH = 0; // pSocket->sndWL2 = 0; pSocket->sndUP = 0; pSocket->sndRTTComplete = 0; pSocket->rcvIRS = 0; // pSocket->rcvUNR = 0; pSocket->rcvNXT = 0; pSocket->rcvUP = 0; // pSocket->rcvSeqAhead = 0; pSocket->fGotFin = false; pSocket->fSocketOpen = false; // Jacobson rule pSocket->RTTsa = RTTsaINIT; pSocket->RTTsv = RTTsvINIT; pSocket->tRTO_SET = RTO(pSocket); pSocket->tRTOCur = pSocket->tRTO_SET; }