bool UdpServer::getAvailableClientsRemoteEndPoint(IPEndPoint *pRemoteEP, MAC * pRemoteMAC, int index) { IPEndPoint remoteEP; unsigned short localPort; MAC macRemote; if(index >= _cPending) { return(false); } // careful not to run PendingClients or IsListening so index order does not change GetUdpSocketEndPoints(_rghUDP[index], &remoteEP.ip, &macRemote, &remoteEP.port, &localPort); if(pRemoteEP != 0) { *pRemoteEP = remoteEP; } if(pRemoteMAC != 0) { *pRemoteMAC = macRemote; } }
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); }