Пример #1
0
bool DEWFcK::wfConnect(SECURITY security, const char * szSsid, const byte * rgbKey, int iKey, IPSTATUS * pStatus)
{
    IPSTATUS status = ipsFailed;

    deIPInit();

    if(isWFInitialized(&status))
    {
        switch(_wfState)
        {
            case idle:
            case scanReady:
            case keygenReady:
            case connecting:
                if(_pNwWF->Connect(security, (const uint8_t *) szSsid, rgbKey, iKey, true, &status))
                {
                    _wfState = connected;
                }
                else if(IsIPStatusAnError(status))
                {
                    _wfState = idle;
                }
                break;

            default:
                status = ipsInvalidOperation;
                break;
        }
    }

    AssignStatusSafely(pStatus, status);
    return(_wfState == connected);
}
Пример #2
0
// 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);
}
Пример #3
0
/***    GCMD::ACTION ProcessClient(CLIENTINFO * pClientInfo)
 *
 *    Parameters:
 *          pClientInfo - a pointer to CLIENTINFO structure with the socket and local data used by the connection
 *              
 *    Return Values:
 *          GCMD::ACTION -  Generally GCMD::CONTINUE is returned to keep the server running
 *                          However if GCMD::RESTART is returned, the server is restarted
 *                          And if GCMD::TERMINATE is returned, the server is cleanly shutdown and loops forever doing nothing.
 *
 *    Description: 
 *    
 *      In the CLINTINFO structure there is an fInUse flag, and this is what tells the server
 *      that the CLINTINFO has an active connection. Only active connections are processed by the server
 *      so this function is only called with pClientInfo->fInUse == true. This function sets it false when the connection
 *      is closed or lost.
 *
 *      Having said that, there are a few cases when the connection will be dropped. For example if the other side
 *      unexpectedly drops the connection, or the network goes down.
 *
 *      When the connection is closed (state == STOPCLIENT) for whatever reason, the HTML rendering function will be called with 
 *      pClientInfo->htmlState == HTTPDISCONNECT. This is the only intential time the HTML Rendering function will
 *      be called with the connection closed. This is to allow the Rendering page to deinitialize any state.
 *      So if a file is open, or hardware is process, the rendering page function will have an opertunity to close
 *      resources. This is particularly useful if the connection is unexpectedly dropped, this will allow
 *      for cleanup. When the HTML rendering function is called with HTTPDISCONNECT, GCMD::DONE is expected to be returned.
 *      
 * ------------------------------------------------------------ */
GCMD::ACTION ProcessClient(CLIENTINFO * pClientInfo)
{   
    GCMD::ACTION    action = GCMD::CONTINUE;
    IPSTATUS        status = ipsSuccess;
    uint32_t        tCur = millis();

    // timeout occured, get out
    if(pClientInfo->clientState != START && (tCur - pClientInfo->tStartClient)  >= (secClientTO * 1000))
    {
        Serial.print("Timeout on client: 0x");
        Serial.println((uint32_t) pClientInfo, HEX);
        pClientInfo->nextClientState    =   EXIT;
 
        // if no data came in at all, then just close the connection
        if(pClientInfo->cbRead == 0)
        {
            pClientInfo->clientState        =   STOPCLIENT;
        }

        // if some data came in, then give the data to the default HTML page.
        else if(pClientInfo->ComposeHTMLPage == NULL)
        {
            pClientInfo->clientState        =   DEFAULTCMD;
        }
        else
        {
            pClientInfo->clientState        =   PROCESSHTML;
            pClientInfo->htmlState          =   HTTPTIMEOUT;
        }
    }

    // lost the connection, get out
    if(((CLIENTSTATE) pClientInfo->clientState < STOPCLIENT)  && !pClientInfo->pTCPClient->isEstablished())
    {
        Serial.println("Connection Lost");
        pClientInfo->clientState        = STOPCLIENT;
        pClientInfo->tStartClient       = tCur;
        pClientInfo->nextClientState    = EXIT;
    }

    switch((CLIENTSTATE) pClientInfo->clientState)
    {   
        case START:
            Serial.println("New Client detected");

            // we know for the most part, the CLIENTINFO is zero'ed 
            // so only set non-zero values
            pClientInfo->pbOut              =   pClientInfo->rgbOut;
            pClientInfo->htmlState          =   HTTPSTART;                  // forces the initialization state to be executed
            pClientInfo->tStartClient       =   tCur;
            pClientInfo->clientState        =   READINPUT;
            pClientInfo->nextClientState    =   WAITCMD;
            break;

        case READINPUT:
                // read in the HTTP URL, any additional data.
                if(pClientInfo->pTCPClient->available() >= 0 && pClientInfo->cbRead < sizeof(pClientInfo->rgbIn))
                {                        
                    pClientInfo->cbRead += pClientInfo->pTCPClient->readStream(&pClientInfo->rgbIn[pClientInfo->cbRead], sizeof(pClientInfo->rgbIn) - pClientInfo->cbRead);
                }
                pClientInfo->clientState = pClientInfo->nextClientState;
                break;

        case WAITCMD:
            // until we read something, match, or timeout, we keep reading and waiting.
            pClientInfo->clientState        =   READINPUT;
            pClientInfo->nextClientState    =   WAITCMD;

            // check the match strings, only if we have something to compare against
            if(pClientInfo->cbRead > 0)
            {
                bool fPartialMatch = false;

                // now look to see if HTML redering pages matches this URL
                for(uint32_t i = 0; i < CNTHTTPCMD; i++) 
                {
                    // does this entry have anything in it?
                    if(rgHttpCmd[i].cbMatch > 0)
                    {
                        uint32_t cbCmp = rgHttpCmd[i].cbMatch > pClientInfo->cbRead ? pClientInfo->cbRead : rgHttpCmd[i].cbMatch;

                        // see if we found a matching URL
                        if(memcmp(pClientInfo->rgbIn, rgHttpCmd[i].szMatchString, cbCmp) == 0)
                        {
                            // we either have a partial or full match
                            fPartialMatch = true;

                            // we have a full match; we know what dynamic page to call
                            if(cbCmp == rgHttpCmd[i].cbMatch)
                            {
                                pClientInfo->ComposeHTMLPage = rgHttpCmd[i].ComposeHTMLPage;
                                pClientInfo->clientState = DISPLAYTIME;
                                pClientInfo->tStartClient = tCur;

                                // fournd it, get out.
                                break;
                            }
                        }
                    }
                }


                // if we didn't find a perfect match, then lets see if we are done anyway
                if(pClientInfo->clientState == READINPUT)
                {
                    // only quit if we can't read anymore; our input buffer is full
                    // otherwise keep reading, we may get more bytes to give us a full match
                    if(!fPartialMatch || pClientInfo->cbRead == sizeof(pClientInfo->rgbIn) ||
                        (pClientInfo->cbRead >= 4 && 
                        pClientInfo->rgbIn[pClientInfo->cbRead-4] == '\r' && pClientInfo->rgbIn[pClientInfo->cbRead-3] == '\n' && 
                        pClientInfo->rgbIn[pClientInfo->cbRead-2] == '\r' && pClientInfo->rgbIn[pClientInfo->cbRead-1] == '\n'  ) )
                    {
                        pClientInfo->clientState = DEFAULTCMD;
                        pClientInfo->tStartClient = tCur;
                    }
                }
             }
            break;

        case DEFAULTCMD:
            Serial.println("Default page called");
            pClientInfo->ComposeHTMLPage = DefaultHTMLPage;        
            pClientInfo->tStartClient = tCur;
            pClientInfo->clientState = DISPLAYTIME;
            break;

        case DISPLAYTIME:
            {
#ifndef NOTIME

                unsigned int epochTime = 0;
                char szTemp[256];

                epochTime = deIPcK.secondsSinceEpoch();
                GetDayAndTime(epochTime, szTemp);
                Serial.println(szTemp);
#endif
                pClientInfo->clientState = PROCESSHTML;   
                pClientInfo->tStartClient = tCur;
            }
            break;

        case PROCESSHTML:

            // process the HTML page
            switch((action = pClientInfo->ComposeHTMLPage(pClientInfo)))
            {
                // just come back to this state
                case GCMD::CONTINUE:
                    pClientInfo->clientState = PROCESSHTML;
                    break;

                // TODO, read more from the input.
                case GCMD::READ:
                    pClientInfo->nextClientState    =   PROCESSHTML;
                    pClientInfo->clientState        =   READINPUT;
                    break;

                // we have data to write out
                case GCMD::WRITE:
                    pClientInfo->nextClientState    = PROCESSHTML;
                    pClientInfo->clientState        = WRITEBUFFER;
                    break;

                // Done processing the client, close the client and get out
                case GCMD::DONE:
                    pClientInfo->nextClientState    = EXIT;         // we are done!
                    pClientInfo->clientState        = STOPCLIENT;
                    break;

                case GCMD::RESTART:
                    pClientInfo->nextClientState    = RESTART;      // we want to terminate the server
                    pClientInfo->clientState        = STOPCLIENT;
                    break;

                case GCMD::TERMINATE:
                    pClientInfo->nextClientState    = TERMINATE;   // we want to terminate the server
                    pClientInfo->clientState        = STOPCLIENT;
                    break;
     
                case GCMD::REBOOT:
                    pClientInfo->nextClientState    = REBOOT;       // we want to reboot the server
                    pClientInfo->clientState        = STOPCLIENT;
                    break;
     
                case GCMD::GETLINE:
                    pClientInfo->clientState        = PARSENEXTLINE;
                    break;

                default:
                    Serial.print("Unsupported compose command detected: ");
                    Serial.println(action, DEC);
                    pClientInfo->nextClientState    = EXIT;     // we are done!
                    pClientInfo->clientState        = STOPCLIENT;
                    break;
            }

            pClientInfo->cbWritten          = 0;
            pClientInfo->tStartClient       = tCur;
            break;

        case PARSENEXTLINE:
            {
                uint32_t    i                   = 0;
                boolean     fFoundNewLine       = false;
                boolean     fNullTerminator     = false;
 
                // we are looking for either a /r/n or a /0.
                // if we find the /r/n first, than replace the /r/n with /0 and that is our first line
                // otherwise if we find the /0, go find the next /r/n
                for(i = 0; i < pClientInfo->cbRead; i++)
                {
                    if( (fFoundNewLine = pClientInfo->rgbIn[i] == '\n')  ||
                        (fNullTerminator = pClientInfo->rgbIn[i] == '\0')                                   )
                    {
                         break;
                    }
                }

                // found the line end, terminate it and return.
                if(fFoundNewLine)
                {
                    pClientInfo->rgbIn[i] = '\0';
                    if(i > 0 && pClientInfo->rgbIn[i-1] == '\r')
                    {
                        pClientInfo->rgbIn[i-1] = '\0';
                    }
                    pClientInfo->clientState = PROCESSHTML; 
                }

                else if(fNullTerminator)
                {
                    // go to beyond the \0
                    for( ; i < pClientInfo->cbRead && pClientInfo->rgbIn[i] == '\0'; i++);
 
                    if(i == pClientInfo->cbRead)
                    {
                        // nothing left in the buffer to read, so we can reset it.
                        pClientInfo->cbRead             = 0;
                        pClientInfo->clientState        = READINPUT;
                        pClientInfo->nextClientState    = PARSENEXTLINE;
                        if(pClientInfo->rgbOverflow[0] != '\0');
                        {
                            pClientInfo->rgbIn[0] = pClientInfo->rgbOverflow[0];
                            pClientInfo->rgbOverflow[0] = '\0';
                            pClientInfo->cbRead = 1;
                        }
                    }

                    // copy the end of the buffer to the front of the buffer
                    // memcpy should be a safe overlapping copy.
                    else
                    {
                        pClientInfo->cbRead -= i;
                        memcpy(pClientInfo->rgbIn, &pClientInfo->rgbIn[i], pClientInfo->cbRead);
                        // stay at this state to go find the end of line
                    }
                }

                // this is a hard condition, our input buffer is full, and it doesn't even contain a full line.
                else if(i == sizeof(pClientInfo->rgbIn))
                {
                    // save away the last byte and return it as a line, even though there is a line break.
                    pClientInfo->rgbOverflow[0] = pClientInfo->rgbIn[sizeof(pClientInfo->rgbIn)-1];
                    pClientInfo->rgbIn[sizeof(pClientInfo->rgbIn)-1] = '\0';
                    pClientInfo->clientState = PROCESSHTML; 
                }

                // we need to read more data.
                else
                {
                    pClientInfo->clientState        = READINPUT;
                    pClientInfo->nextClientState    = PARSENEXTLINE;
                }
            }

            break;

        case WRITEBUFFER:

            // see if we are done
            if(pClientInfo->cbWritten == pClientInfo->cbWrite)
            {
                pClientInfo->clientState        = pClientInfo->nextClientState;
                pClientInfo->nextClientState    = STOPCLIENT;
                break;
            }

            // otherwise we have data to write
            pClientInfo->cbWritten += pClientInfo->pTCPClient->writeStream(&pClientInfo->pbOut[pClientInfo->cbWritten], pClientInfo->cbWrite - pClientInfo->cbWritten, &status);

            // got an error, terminate the connection
            if(IsIPStatusAnError(status))
            {
                pClientInfo->clientState        = STOPCLIENT;
                pClientInfo->nextClientState    = EXIT;
            }

            // or we are done now after the write
            else if(pClientInfo->cbWritten == pClientInfo->cbWrite)
            {
                pClientInfo->clientState        = pClientInfo->nextClientState;
                pClientInfo->nextClientState    = STOPCLIENT;
            }

            pClientInfo->tStartClient = tCur;
            break;

         case STOPCLIENT:  
            Serial.print("Closing connection for client: 0x");
            Serial.println((uint32_t) pClientInfo, HEX);
            pClientInfo->pTCPClient->close();
            if(pClientInfo->ComposeHTMLPage != NULL)
            {
                pClientInfo->htmlState = HTTPDISCONNECT;
                pClientInfo->ComposeHTMLPage(pClientInfo);
            }
            pClientInfo->clientState = pClientInfo->nextClientState;
            pClientInfo->tStartClient = tCur;
            return(GCMD::ADDSOCKET);
            break;
                     
        case EXIT:
            break;

        case RESTART:
            Serial.println("Restart Commanded");
            return(GCMD::RESTART);
            break;

        case TERMINATE:
            Serial.println("Termination Commanded");
            return(GCMD::TERMINATE);
            break;

        case REBOOT:
            Serial.println("Reboot Commanded");
            return(GCMD::REBOOT);
            break;

        default:
            Serial.print("Unknown client state: ");
            Serial.println(pClientInfo->clientState, DEC);
            pClientInfo->clientState        = STOPCLIENT;
            pClientInfo->nextClientState    = EXIT;
            pClientInfo->tStartClient       = tCur;
            break;

    }

    return(GCMD::CONTINUE);
}
Пример #4
0
/*****************************************************************************
  Function:
	bool TCPIsConnected(SOCKET * pSocket, IPSTATUS * pStatus)

  Description:
        This is sort of like TCPIsEstablished except it is for any connected state. Think
        of being connected as being in the process of getting or closing a connection and being established.
        Established is a fully connected duplex condtion where both sides are ready to send and receive data.

  Parameters:
	pSocket:        The socket to see if it is in the established state
        pStatus:        A pointer to a status variable to recieve the status of the connection
                        This may be NULL if you don't care about the status

  Returns:
        true if the connection is in the process of connecting, half or full duplex
        connection, or in the process of closing but not yet closed.
        false if the conneciton is not in any kind of active condition.
  ***************************************************************************/
bool TCPIsConnected(HSOCKET hSocket, IPSTATUS * pStatus)
{
    TCPSOCKET * pSocket = (TCPSOCKET *) hSocket;
    IPSTATUS    status  = ipsUnknowTCPState;

    // check to see if we are even connected
    if(pSocket == NULL)
    {
        AssignStatusSafely(pStatus, ipsSocketNULL);
        return(false);
    }

    // Otherwise, what is our state?
    switch(pSocket->tcpState)
    {
        case tcpListen:
        case tcpSynSent:
        case tcpSynReceivedWhileListening:
        case tcpSynReceived:
        case tcpEstablished:
        case tcpFinWait1:
        case tcpFinWait2:
        case tcpCloseWait:
        case tcpClosing:
        case tcpLastAck:
            status = IPStatusFromTCPState(pSocket->tcpState);
            break;

        case tcpWaitUserClose:
            if(TCPAvailable(pSocket, NULL) > 0)
            {
                status = IPStatusFromTCPState(pSocket->tcpState);
            }
            else
            {
                status = IPErrorFromTCPState(pSocket->tcpState);
            }
            break;

        case tcpUnassigned:
        case tcpAllocated:
        case tcpInvalid:
        case tcpClosed:
            status = IPErrorFromTCPState(pSocket->tcpState);
            break;

        default:
            status = ipsUnknowTCPState;
            break;
    }

    AssignStatusSafely(pStatus, status);
    if(IsIPStatusAnError(status))
    {
        return(false);
    }
    else if(!ILIsIPNetworkReady(pSocket->s.pLLAdp, &status))
    {
        AssignStatusSafely(pStatus, status);
        return(false);
    }
    else if(pSocket->tcpState == tcpListen)
    {
        return(false);
    }

    return(true);
}
Пример #5
0
/*****************************************************************************
  Function:
	SOCKET * TCPOpen(const LLADP * pLLAdp, const SOCKETPOOL * pSocketPool, void * pIPvXDest, uint16_t portRemote, uint16_t portLocal, IPSTATUS * pStatus)

  Summary:
        Opens a Socket for both Client and Server. If portRemote == 0
        The socket is opened for listening.

  Description:

  Precondition:

  Parameters:
	pLLAdp -        The adaptor to use
        pSocket -       A pointer to the socket to use
        hPMGR -         A handle to the page manager to create the socket stream.
        pIPvXDest -     The Dest IP to connect to if a client, ignored for a server open and may be NULL
        portRemote -    The remote port to connect to if Client, MUST be 0 if this is a server open for listen
        portLocal -     Local port to use, one will be assigned if zero
        pStatus -       A pointer to a status variable to recieve the status of the open, This may be NULL

  Returns:
        The Socket if opened, NULL on failure
  ***************************************************************************/
HSOCKET TCPOpenWithSocket(const LLADP * pLLAdp, TCPSOCKET * pSocket, HPMGR hPMGR, const void * pIPvXDest, uint16_t portRemote, uint16_t portLocal, IPSTATUS * pStatus)
{
    IPSTATUS    status      = ipsSuccess;
    IPSTACK *   pIpStack    = NULL;
    uint32_t    cbOptions   = 0;

    // make sure pIPvXDest points to something
    if(portRemote == 0 || pIPvXDest == NULL)
    {
        pIPvXDest = &IPv6NONE;
    }

    if(pSocket == NULL)
    {
        AssignStatusSafely(pStatus, ipsNoSocketsAvailable);
        return(NULL);
    }

    else if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }

    // if this is a client open
    else if(    (pSocket = TCPInitSocket(pLLAdp, pSocket, hPMGR, pIPvXDest, portRemote, portLocal, &status)) != NULL  &&
                portRemote != portListen  &&
                (pIpStack = TCPCreateSyn(pSocket, &cbOptions, &status)) != NULL)
    {
        pSocket->tcpState               = tcpSynSent;
        pSocket->tLastAck               = SYSGetMilliSecond();

        // start the connection process
        TCPTransmit(pIpStack, pSocket, 1, cbOptions, false, SYSGetMilliSecond(), &status);
    }
    
    // else this is a server open / or an error getting the socket which we will abort below in the error check
    else if(pSocket != NULL)
    {
        pSocket->tcpState               = tcpListen;
    }

    // we got an error somewhere; clean up
    if(IsIPStatusAnError(status))
    {
        if(pSocket != NULL)
        {
            pSocket->tcpState = tcpUnassigned;
            TCPResetSocket(pSocket);
        }
        IPSRelease(pIpStack);
        pSocket = NULL;
        AssignStatusSafely(pStatus, status);
        return(NULL);
    }

    // put on the listening list.
    FFInPacket(&g_ffptActiveTCPSockets, pSocket);

    pSocket->fSocketOpen = true;
    AssignStatusSafely(pStatus, status);
    return((HSOCKET) pSocket);
 }
Пример #6
0
bool DNSInit(const LLADP * pLLAdp, void * rgbDNSMem, uint32_t cbDNSMem, HPMGR hPMGR, IPSTATUS * pStatus)
{
    IPSTATUS    status = ipsSuccess;
    DNSMEM *    pDNSMem = (DNSMEM *) rgbDNSMem;
    uint32_t    i = 0;

    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if(hPMGR == NULL)
    {
        status = ipsNoPMGRGiven;
    }
    else if(rgbDNSMem == NULL)
    {
        status = ipsDNSMemIsNULL;
    }
    else if(cbDNSMem < sizeof(DNSMEM))
    {
        status = ipsDNSNotEnoughMem;
    }
    else if(pLLAdp->pDNSMem != NULL)
    {
        status = ipsDNSAlreadyInitialized;
    }
    else if(ILIsIPv6(pLLAdp))
    {
        status = ipsIPv6NotSupported;
    }

    if(IsIPStatusAnError(status))
    {
        AssignStatusSafely(pStatus, status);
        return(false);
    }

    memset(pDNSMem, 0, cbDNSMem);
    if(&pDNSMem->socket != UDPOpenWithSocket(pLLAdp, &pDNSMem->socket, hPMGR, &IPv4BROADCAST, portDNSServer, portDynamicallyAssign, &status) ||
       IsIPStatusAnError(status))
    {
        UDPClose(&pDNSMem->socket);
        AssignStatusSafely(pStatus, status);
        return(false);
    }

    pDNSMem->dnsNSMax = (cbDNSMem - sizeof(DNSMEM)) / sizeof(IPv4or6);
    pDNSMem->cDhcpNS = 0;
    pDNSMem->iDNSCur = DNSiInvalid;
    pDNSMem->iDNSWorks = DNSiInvalid;
    pDNSMem->dnsState = dnsReady;
    pDNSMem->cTry = 0;
    ((LLADP *) pLLAdp)->pDNSMem = pDNSMem;

    // initialize them all to the Google NS
    // that way there is something in all of the slots
    // this will get over written if DHCP is used.
    for(i=0; i<pDNSMem->dnsNSMax; i++)
    {
        if((i % 2) == 0)
        {
            pDNSMem->dnsNS[i].ipv4.u32 = 0x04040808; // Google public DNS server
        }
        else
        {
            pDNSMem->dnsNS[i].ipv4.u32 = 0x08080808; // Google public DNS server
        }
    }

    AssignStatusSafely(pStatus, status);
    return(true);
}
Пример #7
0
// Notes on dnsNSMax and cDhcpNS. You would think that we should only cycle through cDhcpNS as this is the number
// DNS servers given to us by DHCP, however, sometimes DHCP does not give us good DNS servers and for the
// SNTP server to work, we need a good DNS server. So we continue to check the default, pre initialized google DNS
// servers after the DHCP DNS servers are checked first. If we get a lot of DNS servers from DHCP, then ultimately
// all of the pre installed google servers will be overwritten in the dnsNSMax list, but if we got a lot of DNS servers
// the assumption is that they are good ones. In particular, I found that Verizon did not give me very good DNS servers, they
// could not resolve the SNTP time servers.
static void DNSStateMachine(const LLADP * pLLAdp)
{
    IPSTATUS    status      = ipsSuccess;

    if(pLLAdp == NULL || pLLAdp->pDNSMem == NULL || !ILIsIPSetup(pLLAdp, NULL))
    {
        return;
    }

    switch(pLLAdp->pDNSMem->dnsState)
    {
        case dnsSend:
            if(pLLAdp->pDNSMem->dnsNSMax == 0)
            {
                pLLAdp->pDNSMem->dnsState = dnsReady;
                pLLAdp->pDNSMem->cTry = 0;
                break;
            }
            else if(pLLAdp->pDNSMem->cTry >= (pLLAdp->pDNSMem->dnsNSMax * DNSMINTRY))
            {
                if(pLLAdp->pDNSMem->iDNSCur == pLLAdp->pDNSMem->iDNSWorks)
                {
                    pLLAdp->pDNSMem->iDNSWorks = DNSiInvalid;
                }
                pLLAdp->pDNSMem->iDNSCur = DNSiInvalid;
                pLLAdp->pDNSMem->dnsState = dnsReady;
                pLLAdp->pDNSMem->cTry = 0;
                break;
            }
            else if(pLLAdp->pDNSMem->iDNSWorks < pLLAdp->pDNSMem->dnsNSMax)
            {
                pLLAdp->pDNSMem->iDNSCur = pLLAdp->pDNSMem->iDNSWorks;
            }
            else if(pLLAdp->pDNSMem->iDNSCur >= pLLAdp->pDNSMem->dnsNSMax)
            {
                pLLAdp->pDNSMem->iDNSCur = 0;
            }
            else
            {
                pLLAdp->pDNSMem->iDNSCur = (pLLAdp->pDNSMem->iDNSCur + 1) % pLLAdp->pDNSMem->dnsNSMax;
            }

            // set this up for an attempt to get the IP address
            memcpy(&pLLAdp->pDNSMem->socket.s.ipRemote, &pLLAdp->pDNSMem->dnsNS[pLLAdp->pDNSMem->iDNSCur], ILIPSize(pLLAdp));

            // fall thru on success

        case dnsReadySend:

            // clear the current IP address
            memset(&pLLAdp->pDNSMem->ip, 0, sizeof(IPv4or6));

            // just make this unique for this pass
            pLLAdp->pDNSMem->dnsDG.dnsHdr.ID++;

            // set my timers and counts
            pLLAdp->pDNSMem->cTry++;
            pLLAdp->pDNSMem->tTimeout = dnsWaitForRetry;
            pLLAdp->pDNSMem->tStart = SYSGetMilliSecond();

            // send out the DNS datagram
            UDPSend(&pLLAdp->pDNSMem->socket, (uint8_t *) &pLLAdp->pDNSMem->dnsDG, pLLAdp->pDNSMem->cbDNSDG, &status);

            // see if it went out.
            if(IsIPStatusAnError(status))
            {
                pLLAdp->pDNSMem->dnsState = dnsReady;
                pLLAdp->pDNSMem->cTry = 0;
            }
            else
            {
                pLLAdp->pDNSMem->dnsState = dnsWaiting;
            }
            break;

        case dnsWaiting:
            {
                uint16_t cbDG = UDPAvailable(&pLLAdp->pDNSMem->socket) ;
                IPSTATUS status;

                if(cbDG > sizeof(DNSHDR))
                {
                    // we need some space for the datagram
                    uint8_t     rgbDNSDG[DNSMAXUDPSIZE];
                    DNSDG *     pDNSDG  = (DNSDG *) rgbDNSDG;
                    uint8_t *   pEnd    = NULL;
                    uint8_t *   pCName  = NULL;
                    DNSRR *     pDNSRRA = NULL;

                    // read the DNS datagram
                    cbDG = UDPRead(&pLLAdp->pDNSMem->socket, rgbDNSDG, DNSMAXUDPSIZE, &status);

                    // There are some servers setting this and they should not! RFC 6195 2.1 and I need to ignore it
                    // Plus this is used internally to determine if we are in machine or network order. This is in network order right now.
                    pDNSDG->dnsHdr.Z = 0;

                    // now put in machine order.
                    cbDG = ExDNSDG(pDNSDG, cbDG);
                    pEnd = rgbDNSDG + cbDG;
                    
                    // if this is not a my response, keep waiting
                    // remember the ID is not exchanged, so network and machine order will have the same ID
                    if(!pDNSDG->dnsHdr.QR || pDNSDG->dnsHdr.ID != pLLAdp->pDNSMem->dnsDG.dnsHdr.ID)
                    {
                        break;
                    }

                    // ops and error occured, jump to finish with error
                    // go to the error state with no address found
                    if(pDNSDG->dnsHdr.RCODE != DNSRCODENoError)
                    {
                        // this is a failure case; go to the next DNS server
                        pLLAdp->pDNSMem->dnsState = dnsSend;
                        break;
                    }
                    
                    // get the canonical name for what we are looking for
                    // the first record is the question which has the name we used.
                    // we need to use the one in this datagram because we do memory range
                    // checking and if we use the QR we sent, it would be out of the memory range
                    pCName = DNSFindCName(pDNSDG, DNSRRAN, pDNSDG->rrRecords, pEnd);

                    // now find the A record
                    pDNSRRA = DNSFindRR(pDNSDG, NULL, DNSRRAN, DNSTYPEA, DNSCLASSIN, pCName, pEnd);

                    // if we got the A record we are done
                    if( pDNSRRA != NULL                                             &&
                        ((ILIsIPv6(pLLAdp)  &&  pDNSRRA->RDLENGTH == sizeof(IPv6))  ||
                         (!ILIsIPv6(pLLAdp) &&  pDNSRRA->RDLENGTH == sizeof(IPv4))  )   )
                    {
                        // copy in our result
                        memcpy(&pLLAdp->pDNSMem->ip, pDNSRRA->RDATA, pDNSRRA->RDLENGTH);

                        // say we are done
                        pLLAdp->pDNSMem->dnsState = dnsReady;
                        pLLAdp->pDNSMem->cTry = 0;

                        // We got an IP so we know this DNS server can work, remember that
                        if(pLLAdp->pDNSMem->iDNSCur < pLLAdp->pDNSMem->dnsNSMax)
                        {
                            pLLAdp->pDNSMem->iDNSWorks = pLLAdp->pDNSMem->iDNSCur;
                        }

                        // get out we found it and are done.
                        break;
                    }

                    // by default we will go to the next well know sever unless we pick up a better NS to go to
                    pLLAdp->pDNSMem->dnsState = dnsSend;

                    // we did not find anything, so update our DNS request to use the new CName
                    if(pCName != pDNSDG->rrRecords)
                    {
                        // make the new DNS packet with the CName instead of what we were using
                        uint16_t cbMax = DNSCreateIPv4QueryDN(pLLAdp, rgbDNSDG, pCName, pEnd, &pLLAdp->pDNSMem->dnsDG);
                        pLLAdp->pDNSMem->cbDNSDG = ExDNSDG(&pLLAdp->pDNSMem->dnsDG, cbMax);
                    }

                    // Didn't find an A record
                    // But maybe there is a name server we should try.
                    // If we asked for recursion and go it, no sense working the issue ourselves.
                    // likewise if there are now NS with IP addresses, no sense working the issue
                    if(!(pDNSDG->dnsHdr.RD && pDNSDG->dnsHdr.RA) && pDNSDG->dnsHdr.NSCOUNT > 0 && pDNSDG->dnsHdr.ARCOUNT > 0)
                    {
                        // this DNS server gave us something, so remember it
                        if(pLLAdp->pDNSMem->iDNSCur < pLLAdp->pDNSMem->dnsNSMax)
                        {
                            pLLAdp->pDNSMem->iDNSWorks = pLLAdp->pDNSMem->iDNSCur;
                        }

                        pDNSRRA = DNSFindNSARR(pDNSDG, pCName, pEnd, DNSTYPEA);

                        // if this looks like a good IP address to try, lets contact that name server
                        if(pDNSRRA != NULL && pDNSRRA->RDLENGTH == sizeof(IPv4))
                        {
                            // say were are not using one of our well known DNS servers
                            pLLAdp->pDNSMem->iDNSCur = DNSiInvalid;
                            
                            // Put the IP in our socket
                            memcpy(&pLLAdp->pDNSMem->socket.s.ipRemote, pDNSRRA->RDATA, pDNSRRA->RDLENGTH);
                            pLLAdp->pDNSMem->dnsState = dnsReadySend;
                        }
                    }

                    else if(pLLAdp->pDNSMem->iDNSWorks == pLLAdp->pDNSMem->iDNSCur)
                    {
                        pLLAdp->pDNSMem->iDNSWorks = DNSiInvalid;
                    }

                }
                else if((SYSGetMilliSecond() - pLLAdp->pDNSMem->tStart) >= pLLAdp->pDNSMem->tTimeout)
                {
                    pLLAdp->pDNSMem->dnsState = dnsWaitTry;
                }
            }
            break;

        case dnsWaitTry:

            if(pLLAdp->pDNSMem->iDNSWorks == pLLAdp->pDNSMem->iDNSCur)
            {
                pLLAdp->pDNSMem->iDNSWorks = DNSiInvalid;
            }
            
            if((pLLAdp->pDNSMem->cTry % DNSMINTRY) == 0)
            {
                pLLAdp->pDNSMem->dnsState = dnsSend;                
            }
            else
            {
                pLLAdp->pDNSMem->dnsState = dnsReadySend;
            }

            break;

        case dnsReady:
            pLLAdp->pDNSMem->cTry = 0;
            break;

        // noting to do here, either we have something in the DNS memory IP or not.
        case dnsRedirect:
        case dnsUninit:
        default:
            break;
    }
}
Пример #8
0
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);
}
Пример #9
0
bool UDPRawSend(const LLADP * pLLAdp, IPSTACK *   pIpStack, const void * pIPvXDest, uint16_t portDest, uint16_t portSrc, const uint8_t * pDatagram, uint32_t cbDatagram, bool fFreeDatagramImmediately, IPSTATUS * pStatus)
{   
    bool        fRet        = false;
    IPSTATUS    status      = ipsSuccess;

    if(pLLAdp == NULL)
    {
        status = ipsAdaptorMustBeSpecified;
    }
    else if(pIpStack == NULL)
    {
        status = ipsIpStackNULL;
    }
    else if(pIPvXDest == NULL)
    {
        status = ipsIPAddressIsNull;
    }
    else if(pDatagram == NULL)
    {
        status = ipsUDPNullDatagram;
    }
    
    // sometimes we want to keep the actual buffer we passed in the IpStack
    // because we will later want to reuse it and don't want it copied and freed
    // the downside is, we have to know that the send is complete somehow; typically
    // would do this if you don't reuse the buffer until we get a response from the
    // remote and thus know we must have sent the datagram already.
    // this is typically NOT the way we would use this, but DHCP Does this extensively
    else if(!fFreeDatagramImmediately)
    {
        pIpStack->pPayload = (void *) pDatagram;
    }
    else if(IPSGetPayloadFromAdaptor(pIpStack, cbDatagram) == cbDatagram)
    {
        // this is ugly to have to copy the data but somewhat required
        // the problem is, when we send we may need to wait while an APR is proformed and that
        // will require that the pDatagram be constant, however on return from this funciton
        // the application may immediately reuse the memory to construct the next datagram
        memcpy(pIpStack->pPayload, pDatagram, cbDatagram);
    }
    else
    {
        status = ispOutOfMemory;
    }

    if(IsIPStatusAnError(status))
    {
        AssignStatusSafely(pStatus, status);
        return(false);
    }

    pIpStack->pUDPHdr->portSrc         	= portSrc;
    pIpStack->pUDPHdr->portDest        	= portDest;
    pIpStack->pUDPHdr->cbHdrData       	+= cbDatagram;
    pIpStack->cbPayload               	= cbDatagram;

    if(ILIsIPv6(pLLAdp))
    {
        pIpStack->pIPv6Hdr->cbPayload	= pIpStack->cbPayload;
        memcpy(&pIpStack->pIPv6Hdr->ipDest, pIPvXDest, sizeof(IPv6));
    }
    else
    {
        pIpStack->pIPv4Hdr->cbTotal += pIpStack->cbPayload;
        memcpy(&pIpStack->pIPv4Hdr->ipDest, pIPvXDest, sizeof(IPv4));
    }

    fRet = ILSend(pIpStack, pStatus);

    return(fRet);
}
Пример #10
0
/***    void ProcessServer()
 *
 *    Parameters:
 *          None
 *              
 *    Return Values:
 *          None
 *
 *    Description: 
 *    
 *      This is the main server loop. It:
 *          1. Scans for WiFi connections
 *          2. Connects to a WiFi by SSID
 *          3. Optionally creates a server IP on the detected subnet and dynamically assigns DNS and subnets.
 *          4. Or uses the static IP you assign; then you must supply DNS and subnet
 *          5. Starts listening on the supplied server port.
 *          6. Accepts client connections
 *          7. Schedules the processing on client connections in a round robin yet fashion (cooperative execution).
 *          8. Automatically restart if the network goes down
 *      
 *      This illistrates how to write a state machine like loop
 *      so that the PeriodicTask is called everytime through the loop
 *      so the stack stay alive and responsive.
 *
 *      In the loop we listen for a request, verify it to a limited degree
 *      and then broadcast the Magic Packet to wake the request machine.
 *      
 * ------------------------------------------------------------ */
void ProcessServer(void)
{   
    uint32_t i               = 0;

  // see if we exceeded our timeout value.
  // then just be done and close the socket 
  // by default, a closed client is never connected
  // so it is safe to call isConnected() even if it is closed 
  if(stateTimeOut != NONE && TooMuchTime())
  {
	  xil_printf("Timeout occured\r\n");
    state = stateTimeOut;
    stateTimeOut = NONE;
    stateNext = RESTARTREST;
  }

  switch(state)
  {    

#if defined(USING_WIFI)

        case WIFISCAN:
            if(deIPcK.wfScan(&cNetworks, &status))
            {
            	xil_printf("Scan Done, %d Networks Found\r\n", cNetworks);
                state = PRINTAPINFO;
                RestartTimer();
                iNetwork = 0;
            }
            else if(IsIPStatusAnError(status))
            {
            	xil_printf("Scan Failed\r\n\n");
                state = WIFICONNECT;
                RestartTimer();
            }
            break;

        case PRINTAPINFO:
            if(iNetwork < cNetworks)
            {
                SCANINFO scanInfo;
                uint32_t j = 0;

// this is MRF24 specific code
// this will not run in all implemenations
#if MRFVERSION
                {
                    t_deviceInfo dvInfo;
                    WF_DeviceInfoGet(&dvInfo);

                    Serial.println("Device Info");
                    Serial.print("DeviceType: 0x");
                    Serial.print((int) dvInfo.deviceType, HEX);
                    Serial.print(" Rom Version: 0x");
                    Serial.print((int) dvInfo.romVersion, HEX);
                    Serial.print(" Patch Version: 0x");
                    Serial.println((int) dvInfo.patchVersion, HEX);
               }
#endif

                if(deIPcK.getScanInfo(iNetwork, &scanInfo))
                {
                	xil_printf("\r\nScan info for index: %d\r\n", iNetwork);

                	xil_printf("SSID: %s\r\n", scanInfo.ssid);

                    xil_printf("\r\nBSSID / MAC: ");
                    for(j=0; j<sizeof(scanInfo.bssid); j++)
                    {
                        if(scanInfo.bssid[j] < 16)
                        {
                        	xil_printf("0");
                        }
                        xil_printf("%X",scanInfo.bssid[j]);
                    }

                    xil_printf("\r\nChannel: %d\r\nSignal Strength: %d\r\n", scanInfo.channel, scanInfo.rssi);

                    if(scanInfo.bssType == DEWF_INFRASTRUCTURE)
                    {
                    	xil_printf("Infrastructure Network\r\n");
                    }
                    else if(scanInfo.bssType == DEWF_ADHOC)
                    {
                    	xil_printf("AdHoc Network\r\n");
                    }
                    else
                    {
                    	xil_printf("Unknown Network Type\r\n");
                    }

                    xil_printf("Beacon Period: %d\r\ndtimPeriod: %d\r\natimWindow: %d\r\n", scanInfo.beaconPeriod, scanInfo.dtimPeriod, scanInfo.atimWindow);


                    xil_printf("Security info: WPA2  WPA  Preamble  Privacy  Reserved  Reserved  Reserved  IE\r\n");
                    xil_printf("                %d    %d       %d        %d         %d         %d         %d      %d\r\n",(scanInfo.apConfig & 0b10000000) >> 7,(scanInfo.apConfig & 0b01000000) >> 6,(scanInfo.apConfig & 0b00100000) >> 5,(scanInfo.apConfig & 0b00010000) >> 4,(scanInfo.apConfig & 0b00001000) >> 3,(scanInfo.apConfig & 0b00000100) >> 2,(scanInfo.apConfig & 0b00000010) >> 1,(scanInfo.apConfig & 0b00000001));
//                      Serial.print((scanInfo.apConfig & 0b10000000) >> 7, DEC);
//                                       Serial.print("    ");
//                                       Serial.print((scanInfo.apConfig & 0b01000000) >> 6, DEC);
//                                            Serial.print("       ");
//                                            Serial.print((scanInfo.apConfig & 0b00100000) >> 5, DEC);
//                                                    Serial.print("        ");
//                                                    Serial.print((scanInfo.apConfig & 0b00010000) >> 4, DEC);
//                                                             Serial.print("         ");
//                                                             Serial.print((scanInfo.apConfig & 0b00001000) >> 3, DEC);
//                                                                       Serial.print("         ");
//                                                                        Serial.print((scanInfo.apConfig & 0b00000100) >> 2, DEC);
//                                                                                 Serial.print("         ");
//                                                                                 Serial.print((scanInfo.apConfig & 0b00000010) >> 1, DEC);
//                                                                                           Serial.print("      ");
//                                                                                           Serial.println((scanInfo.apConfig & 0b00000001), DEC);

                    xil_printf("Count of support bit rates: %d\r\n", scanInfo.cBasicRates);
                    xil_printf("Supported Rates: ");
                    for( j= 0; j< scanInfo.cBasicRates; j++)
                    {
                        uint32_t rate = (scanInfo.basicRateSet[j] & 0x7F) * 500;
                        xil_printf("\t%d kbps", rate);
                    }
                    xil_printf("\r\n");
                }
                else
                {