void TCPServer::periodicTask(void) { FFLL * pffllServer = NULL; // look at all of the server objects while((pffllServer = (FFLL *) FFNext(&_ffptPeriodTask, pffllServer)) != NULL) { FFLL * pffllSocket = NULL; TCPServer& tcpServer = *((TCPServer *) (pffllServer->_this)); // for syntax sake if(ILIsIPSetup(tcpServer._pDEIPcK->_pLLAdp, NULL)) { while((pffllSocket = (FFLL *) FFNext(&tcpServer._ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake // start listening on available sockets if(tcpSocket._classState == ipsNotInitialized && tcpSocket._socket.tcpState < tcpInvalid) { // get this listening if(TCPOpenWithSocket(tcpSocket._pDEIPcK->_pLLAdp, &tcpSocket._socket, tcpSocket._hPMGR, &IPListen, portListen, tcpServer._listeningPort, NULL) == &tcpSocket._socket) { if(tcpSocket._socket.tcpState == tcpListen) { tcpSocket._classState = ipsListening; } } } } } } }
uint16_t GetEphemeralPort(FFPT * pFFPT, uint16_t * pNextEphemeralPort) { uint16_t foundEphemeralPort = (*pNextEphemeralPort)++; SOCKET * pSocket = NULL; // make sure this is within range if(foundEphemeralPort > portEphemeralLast) { foundEphemeralPort = portEphemeralFirst; } // check that this port is not in use while((pSocket = (SOCKET*)FFNext(pFFPT, pSocket)) != NULL) { uint16_t portLocal = pSocket->portLocal; // this port is in use, try another one, start over if(foundEphemeralPort == portLocal) { foundEphemeralPort = (*pNextEphemeralPort)++; if(foundEphemeralPort > portEphemeralLast) { foundEphemeralPort = portEphemeralFirst; } // re-search the in use ports to make sure this is okay pSocket = NULL; } } // it is not possible to have as many sockets as ephemeral ports // so we won't loop forever, we will come out of the while loop return(foundEphemeralPort); }
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; }
void TCPPeriodicTasks(void) { TCPSOCKET * pSocketCur = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, NULL); // look at all of the active sockets // remember the TCPStateMachine may remove a socket when // closed and that could clear the socket and thus the next pointer // in the list and FFNext will just have a NULL as the next pointer // after TCPStateMachine runs, so we need to get the next pointer // before we run the state machine while(pSocketCur != NULL) { TCPSOCKET * pSocketNext = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, pSocketCur); TCPStateMachine(NULL, pSocketCur, NULL); pSocketCur = pSocketNext; } }
void DNSPeriodicTasks(void) { const LLADP * pLLAdp = NULL; // walk all of the adpators and process each DHCP State while((pLLAdp = (LLADP*)FFNext(&ffptAdaptors, pLLAdp)) != NULL) { DNSStateMachine(pLLAdp); } }
void UDPCloseAllSockets(void) { UDPSOCKET * pSocket = NULL; // go until you empty the list. while((pSocket = FFNext(&g_ffptListeningUDPSockets, NULL)) != NULL) { UDPClose(pSocket); } }
void TCPAbortAllSockets(void) { TCPSOCKET * pSocket = NULL; // look at all of the TCP sockets //we have to clean out the list, each time we remove // the first entry, the next point will get cleared because the socket // is set to zero, so the next is set to zero in the socket // so just iterate on the first entry until the list is empty while((pSocket = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, NULL)) != NULL) { TCPAbort(pSocket); } }
/*** bool TCPServer::getAvailableClientsRemoteEndPoint(IPEndPoint *pRemoteEP, int index) ** bool TCPServer::getAvailableClientsRemoteEndPoint(IPEndPoint *pRemoteEP, MAC * pRemoteMAC, int index) ** ** Synopsis: ** Returns endpoint information about a TCPSocket waiting to be accepted. ** ** Parameters: ** pRemoteEP A pointer to an IPEndPoint to receive the remote endpoint information for the client ** waiting to be accepted. This may be NULL if you don't want the info ** ** pRemoteMAC A pointer to a MAC to receive the remote MAC address of the client waiting to be accepted. ** This will be the MAC address as known by ARP and will only have MAC address of machines ** on your local area network. If the IP is not local, the MAC will most probably be the MAC ** of your router. This may be NULL if you don't want the info ** ** index This is a zero based index and must be less than what AvailableClients returns. It ** selects the Client within the server list that you want remote endpoint information on. ** ** Return Values: ** true The local endpoint was returned. ** false An error occured, most likely your index was out of range ** ** Errors: ** None ** ** Notes: ** ** This allows you to determine if you want to accept this endpoint before removing it from ** the server. It allows you to accept other clients first and out of order. ** ** This call should be made immediately after AvailableClients and immediately before ** AcceptClient so that the servers pending list does not change due to another connection. ** */ bool TCPServer::getAvailableClientsRemoteEndPoint(IPEndPoint& epRemote, int index) { FFLL * pffllSocket = NULL; int c = 0; while((pffllSocket = (FFLL *) FFNext(&_ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake if(TCPIsEstablished(&tcpSocket._socket, NULL) && c == index) { return(tcpSocket.getRemoteEndPoint(epRemote)); } } return(false); }
// We can get errors, you passed me a NULL, or an opened TCPSocket, or index out of range. TCPSocket * TCPServer::acceptClient(int index) { FFLL * pffllSocket = NULL; int c = 0; while((pffllSocket = (FFLL *) FFNext(&_ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake if(TCPIsEstablished(&tcpSocket._socket, NULL) && c == index) { FFRemove(&_ffptSockets, pffllSocket); tcpSocket._classState = ipsInUseW; return(&tcpSocket); } } return(NULL); }
bool TCPIsInUse(const LLADP * pLLAdp, uint32_t portPair, const void * pIPvXDest) { TCPSOCKET * pSocket = NULL; bool fListenIP = (memcmp(pIPvXDest, &IPListen, ILIPSize(pLLAdp)) == 0); while((pSocket = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, pSocket)) != NULL) { // check to see if this port pair is in active use along with the remote IP if( portPair == pSocket->s.portPair && (memcmp(pIPvXDest, (void *) &pSocket->s.ipRemote, ILIPSize(pLLAdp)) == 0) ) { // if this totally in use and a duplicate should not be put on the stack // however let there be mult listens but check that what we are listining on is the listing IP, not some specific target IP we are waiting for. if(pSocket->tcpState > tcpListen || (pSocket->tcpState == tcpListen && !fListenIP)) { return(true); } } } return(false); }
/*** int TCPServer::availableClients(void) ** ** Synopsis: ** Checks to see how many pending clients are availabe to be accepted. ** ** Parameters: ** None ** ** Return Values: ** The number of waiting TCPSockets to be accepted. ** ** Errors: ** None ** ** Notes: ** ** This is the workhorse of the TCPServer Class ** It will update pending clients if a connection is detected ** It will attempt to start listening if a socket comes avalialbe for listening ** It will clean up disconnected clients */ int TCPServer::availableClients(int& cListening, int& cWaiting, IPSTATUS * pStatus) { int cAvailable = 0; cWaiting = 0; cListening = 0; FFLL * pffllSocket = NULL; if(_pDEIPcK == NULL) { AssignStatusSafely(pStatus, ipsNotInitialized); return(0); } if(ILIsIPNetworkReady(_pDEIPcK->_pLLAdp, pStatus)) { while((pffllSocket = (FFLL *) FFNext(&_ffptSockets, pffllSocket)) != NULL) { TCPSocket& tcpSocket = *((TCPSocket *) (pffllSocket->_this)); // for syntax sake if(TCPIsEstablished(&tcpSocket._socket, NULL)) { cAvailable++; } else if(TCPIsConnected(&tcpSocket._socket, NULL)) { cWaiting++; } else if(tcpSocket._socket.tcpState == tcpListen) { cListening++; } } } return(cAvailable); }
// only called for incoming packets void TCPProcess(IPSTACK * pIpStack) { TCPSOCKET * pSocketCur = NULL; TCPSOCKET * pSocketListen = NULL; TCPSOCKET * pSocketExact = NULL; // see if this is directed to my IP if( !( // this is not my IP address // my IPv4 address (!ILIsIPv6(pIpStack->pLLAdp) && pIpStack->pLLAdp->ipMy.ipv4.u32 == pIpStack->pIPv4Hdr->ipDest.u32) || // my IPv6 addresss (memcmp(&pIpStack->pLLAdp->ipMy.ipv6, &pIpStack->pIPv6Hdr->ipDest, sizeof(IPv6)) == 0) )) { // just get out if it is not for me return; } // look at all of the sockets while((pSocketCur = (TCPSOCKET*)FFNext(&g_ffptActiveTCPSockets, pSocketCur)) != NULL) { if( pSocketCur->tcpState > tcpListen && pIpStack->pTCPHdr->portPair == pSocketCur->s.portPair && // matches the remote IP ((!ILIsIPv6(pIpStack->pLLAdp) && pSocketCur->s.ipRemote.ipv4.u32 == pIpStack->pIPv4Hdr->ipSrc.u32) || (memcmp(&pSocketCur->s.ipRemote.ipv6, &pIpStack->pIPv4Hdr->ipSrc, sizeof(IPv6)) == 0)) ) { pSocketExact = pSocketCur; break; } else if(pSocketCur->tcpState == tcpListen && pSocketCur->s.portLocal == pIpStack->pTCPHdr->portDest && pIpStack->pTCPHdr->fSyn) { pSocketListen = pSocketCur; } } // see if we did not find an exact match // but we are listening if(pSocketExact == NULL) { pSocketExact = pSocketListen; } // a match to an active socket if(pSocketExact != NULL) { IPSUpdateARPEntry(pIpStack); memcpy(&pSocketExact->s.macRemote, &pIpStack->pFrameII->macSrc, sizeof(MACADDR)); TCPStateMachine(pIpStack, pSocketExact, NULL); } // to no socket at all, this will cause a RST to be sent. else { TCPStateMachine(pIpStack, NULL, NULL); } }
void UDPProcess(IPSTACK * pIpStack) { UDPSOCKET * pSocketCur = NULL; UDPSOCKET * pSocketListen = NULL; UDPSOCKET * pSocketAnyRemoteIP = NULL; UDPSOCKET * pSocketExact = NULL; bool fBroadcast = false; bool fMyIP = ILIsIPv6(pIpStack->pLLAdp) ? ILIsMyIP(pIpStack->pLLAdp, &pIpStack->pIPv6Hdr->ipDest, &fBroadcast) : ILIsMyIP(pIpStack->pLLAdp, &pIpStack->pIPv4Hdr->ipDest, &fBroadcast); // see if this is directed to my IP if( !fMyIP ) { return; } // look at all listening sockets to see if the ports and remote IP match while((pSocketCur = FFNext(&g_ffptListeningUDPSockets, pSocketCur)) != NULL) { // make sure we have consistant IPs if(ILIsIPv6(pSocketCur->s.pLLAdp) == ILIsIPv6(pIpStack->pLLAdp)) { // listening socket, only check local port, remote port/IP will be set if( pSocketCur->s.portRemote == portListen && pSocketCur->s.portLocal == pIpStack->pUDPHdr->portDest ) { pSocketListen = pSocketCur; } // all connected sockets else if(pIpStack->pUDPHdr->portPair == pSocketCur->s.portPair) { // this is an IPv4 address if(!ILIsIPv6(pIpStack->pLLAdp)) { // exact match if(pSocketCur->s.ipRemote.ipv4.u32 == pIpStack->pIPv4Hdr->ipSrc.u32) { pSocketExact = pSocketCur; break; } // this is only supported for DHCP IPv4 else if(pSocketCur->s.ipRemote.ipv4.u32 == UDPAnyRemoteIPv4.u32) { pSocketAnyRemoteIP = pSocketCur; } } // else an IPv6 address else { // exact match if(memcmp(&pSocketCur->s.ipRemote.ipv6, &pIpStack->pIPv6Hdr->ipSrc, sizeof(IPv6)) == 0) { pSocketExact = pSocketCur; break; } } } } } // a match to an active socket if(pSocketExact == NULL) { if(pSocketAnyRemoteIP != NULL) { pSocketExact = pSocketAnyRemoteIP; } else if(pSocketListen != NULL) { pSocketExact = pSocketListen; pSocketExact->s.portRemote = pIpStack->pUDPHdr->portSrc; if(ILIsIPv6(pSocketExact->s.pLLAdp)) { memcpy(&pSocketExact->s.ipRemote.ipv6, &pIpStack->pIPv6Hdr->ipSrc, sizeof(IPv6)); } else { pSocketExact->s.ipRemote.ipv4.u32 = pIpStack->pIPv4Hdr->ipSrc.u32; } } } // no match to anything, get out. if(pSocketExact == NULL) { return; } // update our ARP table IPSUpdateARPEntry(pIpStack); memcpy(&pSocketExact->s.macRemote, &pIpStack->pFrameII->macSrc, sizeof(MACADDR)); // Receive the UDP input data UDPProcessRx(pIpStack, pSocketExact); }