Beispiel #1
0
/***	void UdpServer::resumeListening(void)
**
**	Synopsis:   
**      Resumes listening on a UdpServer that did a StopListening
**
**	Parameters:
**      None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**
**      If StartListening was never called, this does nothing
**      If it is already listening, it does nothing
*/
void UdpServer::resumeListening(void)
{
    if(!_fStarted)
    {
        return;
    }

    // say we want to listen, may fail, but we will pick it up when we can.
    _fListening = true;

    // make sure we have room to to put our handle in
    if(_cPending >= _cPendingMax)
    {
        return;
    }

    // if we need to start listening on a socket
    if(_rghUDP[_cPending] >= INVALID_UDP_SOCKET)
    {
        // do not need to check to see if Ethernet is initialized because I can assign sockets before then
        _rghUDP[_cPending] = UDPOpen(_localPort, NULL, 0); 
    
        if(_rghUDP[_cPending] < INVALID_UDP_SOCKET)
        {
            // As for the iBuff, when we get data on the socket, the last entry 
            // will be where we put pending Client so just use this iBuff as the cache buffer
            ExchangeCacheBuffer(_rghUDP[_cPending], GetBufferLocation(_cPending), GetBufferSize());
        }
    }
}
Beispiel #2
0
bool UdpServer::acceptClient(UdpClient * pUdpClient, int index, DNETcK::STATUS * pStatus) 
{
    int cb = 0;

    // do not call AvailableClients here because that could shift the indexes around
    // and then we would not be returning the index that someone wants.
    if(pUdpClient == NULL)
    {
        if(pStatus != NULL) *pStatus = DNETcK::ClientPointerIsNULL;
        return(false);
    }
    else if(pUdpClient->_hUDP < INVALID_UDP_SOCKET)
    {
         if(pStatus != NULL) *pStatus = DNETcK::SocketAlreadyAssignedToClient;
        return(false);
    }
    else if(_cbCache < UdpClient::cbDatagramCacheMin)
    {
        if(pStatus != NULL) *pStatus = DNETcK::UDPCacheToSmall;
        return(false);
    }
    else if(index >= _cPending)
    {
        if(pStatus != NULL) *pStatus = DNETcK::IndexOutOfBounds;
        return(false);
    }

    // looks like we have a valid socket at our index
    // We are just making sure we have a properly initialized client
    pUdpClient->close();
    pUdpClient->construct(pUdpClient->_rgbCache, pUdpClient->_cbCache, pUdpClient->_msARPWait, pUdpClient->_cARPRetries);

    // set the hUDP and get ready to complete making the UdpClient
    pUdpClient->_hUDP = _rghUDP[index];
    pUdpClient->_classState = DNETcK::Finalizing;

    // about the only thing that can happen in finalize is that I can get an OutOfMemory error
    if(!pUdpClient->isEndPointResolved(DNETcK::msImmediate, pStatus))
    {
        // we do not want to remove this from the pending list on error
        // maybe you can send me another UdpClient where you specify the 
        // buffer and it won't fail. There is really nothing wrong with the socket
        return(false);
    }

    // at this point we want to copy the cache over to the UdpClient cache
    // right now we are using the servers cache, and we want to move that
    // to the UdpClient cache. 
    // the ExchangeCacheBuffer will toss UPD datagrams that don't fit 
    // in the new buffer. It is possible for the buffer to be empty if all
    // datagrams are too big to fit in the exchanged buffer
    ExchangeCacheBuffer( pUdpClient->_hUDP, pUdpClient->_rgbCache,  pUdpClient->_cbCache);
 
    // We got the UdpClient, no remove this from our pending list
    // AvailableClient will do that if the socket is invalid
    _rghUDP[index] = INVALID_UDP_SOCKET;
    availableClients();
    return(true);
}
Beispiel #3
0
/***	void UdpClient::close(void)
**
**	Synopsis:   
**      Closes the socket and clears the UdpClient instance;
**      Returns the instance to a just constructed state releasing
**      all resources except the user supplied datagram cache buffer
**      which will be reused if SetEndPoint is called again.
**
**	Parameters:
**      None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**
**      Returns the UdpClient instance to 
**      a state just as if the instance had just been
**      constructed. The user supplied datagram cache
**      should still be kept valid.
**
*/
void UdpClient::close(void)
{
    if(_hUDP < INVALID_UDP_SOCKET)
    {
        // remove from the UDP Cache
        ExchangeCacheBuffer(_hUDP, NULL, 0);

        // release MAL socket
        UDPClose(_hUDP);
        _hUDP = INVALID_UDP_SOCKET;
    }

    // initialize this instance of the class
    initUdpClient();
}
Beispiel #4
0
/***	void UdpServer::close(void)
**
**	Synopsis:   
**      Stops Listening and closes all unaccepted sockets
**      and clears everything back to it's originally constructed state.
**      The datagram cache buffers remain in use as this is specified on the constuctor
**
**	Parameters:
**      None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**
**      Returns the UdpServer instance to 
**      a state just as if the instance had just been
**      constructed. It also, Close all connections
**      and releases all resources (sockets).
**
*/
void UdpServer::close(void)
{
    stopListening();

    for(int i = 0; i < _cMaxPendingAllowed; i++)
    {
        if(_rghUDP[i] < INVALID_UDP_SOCKET)
        {
            // clean out the buffer
            UDPIsGetReady(_rghUDP[i]);
            UDPDiscard();
            UDPClose(_rghUDP[i]);
            ExchangeCacheBuffer(_rghUDP[i], NULL, 0);
            _rghUDP[i] = INVALID_UDP_SOCKET;
        }
    }

    clear();
}
Beispiel #5
0
/***	void UdpServer::stopListening(void)
**
**	Synopsis:   
**      This stops listening on the server port, but does not shutdown UdpServer
**
**	Parameters:
**     None
**
**	Return Values:
**      None
**
**	Errors:
**      None
**
**  Notes:
**      To resume listening, just call ResumeListening
**      This is a soft stop listening in that only the server stops listening on the port
**      however the instance is still valid and you can continue to accept pending client.
**      and you can resume the listening.
**
*/
void UdpServer::stopListening(void)
{
   // DO NOT blow away pending clients.
   // that will be done on a close()
   // update the pending count so we have them all.
    availableClients();

   // blow away any listening socket
   if(_cPending < _cPendingMax && _rghUDP[_cPending] < INVALID_UDP_SOCKET)
    {
        UDPIsGetReady(_rghUDP[_cPending]);
        UDPDiscard();
        UDPClose(_rghUDP[_cPending]);
        ExchangeCacheBuffer(_rghUDP[_cPending], NULL, 0);
        _rghUDP[_cPending] = INVALID_UDP_SOCKET;
    }

    // no longer listening
    _fListening = false;
}
Beispiel #6
0
bool UdpClient::isEndPointResolved(unsigned long msBlockMax, DNETcK::STATUS * pStatus)
{
    unsigned long tStart = 0;
    DNETcK::STATUS statusT = DNETcK::None;

    // we want this to be PeriodicTasks and not StackTask because we
    // want to run all of the applications when IsDNETcK::EndPointResolved is called
    // because this is a common call and we want to keep all things running
   EthernetPeriodicTasks();

    // nothing to do if we have already resolved it.
    if(_fEndPointsSetUp)
    {
        if(pStatus != NULL) *pStatus = DNETcK::EndPointResolved;
        return(true);
    }

    // make sure the network is initialized
    if(!DNETcK::isInitialzied(msBlockMax, pStatus))
    {
        return(false);
    }
    
    // make sure the UDP cache is big enough
    if(_cbCache < UdpClient::cbDatagramCacheMin)
    {
        if(pStatus != NULL) *pStatus = DNETcK::UDPCacheToSmall;
        return(false);
    }

    // initialize our status to our current state
    if(pStatus != NULL) *pStatus = _classState;

    // return our current state, except if we are in the process of resolving
    if(DNETcK::isStatusAnError(_classState))
    {
        return(false);
    }

    // continue with the resolve process
    tStart = millis();
    do
    {
        // run the stack
        EthernetPeriodicTasks();

        switch(_classState)
        {
            case DNETcK::DNSResolving:
                if(DNETcK::isDNSResolved(_szHostName, &_remoteEP.ip, DNETcK::msImmediate, &statusT))
                {
                    DNETcK::requestARPIpMacResolution(_remoteEP.ip);
                    _classState = DNETcK::ARPResolving;
                    _msARPtStart = millis();
                }

                // stay at the resolving state until an error occurs
                // if an error, then we fail.
                else if(DNETcK::isStatusAnError(statusT))
                {
                    _classState = DNETcK::DNSResolutionFailed;
                }
                break;

            case DNETcK::ARPResolving:

                // see if we resolved the MAC address
                if(DNETcK::isARPIpMacResolved(_remoteEP.ip, &_remoteMAC, DNETcK::msImmediate))
                {
                    _classState = DNETcK::AcquiringSocket;
                    _msARPtStart = 0;
                }

                // if the ARP timeout has occured; rmember, ARP really doesn't give us failues
                else if(hasTimeElapsed(_msARPtStart, _msARPWait, millis())) 
                {
                    // resend the ARP Request
                    if(_cARPRetries > 0)
                    {
                        DNETcK::requestARPIpMacResolution(_remoteEP.ip);
                        _msARPtStart = millis();
                        _cARPRetries--;
                    }
                    // otherwise we are done
                    else
                    {
                        _classState = DNETcK::ARPResolutionFailed;
                        _msARPtStart = 0;
                    }
                }
                break;

            case DNETcK::AcquiringSocket:

                // set up the socket
                _hUDP = UdpClientSetEndPoint(_remoteEP.ip.rgbIP, _remoteMAC.rgbMAC, _remoteEP.port, _localPort);

                if(_hUDP >= INVALID_UDP_SOCKET)
                {
                    _classState = DNETcK::SocketError;
                    if(pStatus != NULL) *pStatus = _classState;
                    break;
                }

                // fall right into finalize; we have finalize for the UdpServer to use

            case DNETcK::Finalizing:

                // assume the best that we will finish, unless something bad happens.
                _classState = DNETcK::EndPointResolved;

                // we just set up the socket, so all of the IP and port info should be correct
                // let's just update our code so we know we have what the MAL thinks.
                GetUdpSocketEndPoints(_hUDP, &_remoteEP.ip, &_remoteMAC, &_remoteEP.port, &_localPort);

                // see if a cache buffer came in.
                if(_rgbCache == NULL)
                {
                    close();
                    _classState = DNETcK::UDPCacheToSmall;
                }

                // add it to the underlying caching engine
                else
                {
                    ExchangeCacheBuffer(_hUDP, _rgbCache, _cbCache);
                }
                break;

            // if we got an error in the process, we are done. 
            // this is how we get out of the do-while on an error
            default:
                if(pStatus != NULL) *pStatus = _classState;
                return(false);
        }

    } while(_classState != DNETcK::EndPointResolved && !hasTimeElapsed(tStart, msBlockMax, millis()));

    // not sure how we got out of the loop
    // but assign our state and only return true if we succeeded.
    if(pStatus != NULL) *pStatus = _classState;
    if(_classState == DNETcK::EndPointResolved)
    {
        _fEndPointsSetUp = true;
        return(true);
    }

    return(false);
}