/***************************************************************************** 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); }
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 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); }