예제 #1
0
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;
                        }
                    }
                }
            }
        }
    }
}
예제 #2
0
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);
}
예제 #3
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;
}
예제 #4
0
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;
    }
}
예제 #5
0
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);
    }
}
예제 #6
0
void UDPCloseAllSockets(void)
{
    UDPSOCKET * pSocket = NULL;

    // go until you empty the list.
    while((pSocket = FFNext(&g_ffptListeningUDPSockets, NULL)) != NULL)
    {
        UDPClose(pSocket);
    }
}
예제 #7
0
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);
    }
}
예제 #8
0
/***	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);
}
예제 #9
0
// 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);
}
예제 #10
0
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);
}
예제 #11
0
/***	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);
}
예제 #12
0
// 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);
    }
}
예제 #13
0
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);
}