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