From eb6d329dfa6159896feb586f798f90e3016adf19 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 19 Sep 2016 15:30:55 -0700 Subject: [PATCH] exit status depends on what happened. timeout added so it wont wait for server responses forever. --- tools/ice-client/src/ICEClientApp.cpp | 164 ++++++++++++++++++++------ tools/ice-client/src/ICEClientApp.h | 16 +++ 2 files changed, 146 insertions(+), 34 deletions(-) diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index 9f11e0b569..1a251a45c2 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -10,15 +10,16 @@ // #include +#include #include #include #include +#include #include "ICEClientApp.h" ICEClientApp::ICEClientApp(int argc, char* argv[]) : - QCoreApplication(argc, argv), - _stunSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT) + QCoreApplication(argc, argv) { // parse command-line QCommandLineParser parser; @@ -33,7 +34,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : const QCommandLineOption iceServerAddressOption("i", "ice-server address", "IP:PORT or HOSTNAME:PORT"); parser.addOption(iceServerAddressOption); - const QCommandLineOption howManyTimesOption("n", "how many times to cycle", "0"); + const QCommandLineOption howManyTimesOption("n", "how many times to cycle", "1"); parser.addOption(howManyTimesOption); const QCommandLineOption domainIDOption("d", "domain-server uuid", "00000000-0000-0000-0000-000000000000"); @@ -42,7 +43,6 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : const QCommandLineOption cacheSTUNOption("s", "cache stun-server response"); parser.addOption(cacheSTUNOption); - if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -55,18 +55,29 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : } _verbose = parser.isSet(verboseOutput); + if (!_verbose) { + const_cast(&networking())->setEnabled(QtDebugMsg, false); + const_cast(&networking())->setEnabled(QtInfoMsg, false); + const_cast(&networking())->setEnabled(QtWarningMsg, false); + } + + _stunSockAddr = HifiSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT, true); + _cacheSTUNResult = parser.isSet(cacheSTUNOption); if (parser.isSet(howManyTimesOption)) { _actionMax = parser.value(howManyTimesOption).toInt(); + } else { + _actionMax = 1; } if (parser.isSet(domainIDOption)) { _domainID = QUuid(parser.value(domainIDOption)); - qDebug() << "domain-server ID is" << _domainID; + if (_verbose) { + qDebug() << "domain-server ID is" << _domainID; + } } - _iceServerAddr = HifiSockAddr("127.0.0.1", ICE_SERVER_DEFAULT_PORT); if (parser.isSet(iceServerAddressOption)) { // parse the IP and port combination for this target @@ -74,8 +85,11 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QHostAddress address { hostnamePortString.left(hostnamePortString.indexOf(':')) }; quint16 port { (quint16) hostnamePortString.mid(hostnamePortString.indexOf(':') + 1).toUInt() }; + if (port == 0) { + port = 7337; + } - if (address.isNull() || port == 0) { + if (address.isNull()) { qCritical() << "Could not parse an IP address and port combination from" << hostnamePortString << "-" << "The parsed IP was" << address.toString() << "and the parsed port was" << port; @@ -85,7 +99,9 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : } } - qDebug() << "ICE-server address is" << _iceServerAddr; + if (_verbose) { + qDebug() << "ICE-server address is" << _iceServerAddr; + } setState(lookUpStunServer); @@ -99,7 +115,6 @@ ICEClientApp::~ICEClientApp() { } void ICEClientApp::setState(int newState) { - // qDebug() << "state: " << _state << " --> " << newState; _state = newState; } @@ -123,9 +138,12 @@ void ICEClientApp::openSocket() { processSTUNResponse(std::move(packet)); }); - qDebug() << "local port is" << _socket->localPort(); + if (_verbose) { + qDebug() << "local port is" << _socket->localPort(); + } _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); + _domainPingCount = 0; } void ICEClientApp::doSomething() { @@ -136,8 +154,15 @@ void ICEClientApp::doSomething() { } else if (_state == lookUpStunServer) { // lookup STUN server address if (!_stunSockAddr.getAddress().isNull()) { - qDebug() << "stun server is" << _stunSockAddr; + if (_verbose) { + qDebug() << "stun server is" << _stunSockAddr; + } setState(sendStunRequestPacket); + } else { + if (_verbose) { + qDebug() << "_stunSockAddr is" << _stunSockAddr.getAddress(); + } + QCoreApplication::exit(stunFailureExitStatus); } } else if (_state == sendStunRequestPacket) { @@ -149,12 +174,26 @@ void ICEClientApp::doSomething() { const int NUM_BYTES_STUN_HEADER = 20; char stunRequestPacket[NUM_BYTES_STUN_HEADER]; LimitedNodeList::makeSTUNRequestPacket(stunRequestPacket); - qDebug() << "sending STUN request"; + if (_verbose) { + qDebug() << "sending STUN request"; + } _socket->writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr); + _stunResponseTimerCanceled = false; + _stunResponseTimer.singleShot(stunResponseTimeoutMilliSeconds, this, [&] { + if (_stunResponseTimerCanceled) { + return; + } + if (_verbose) { + qDebug() << "timeout waiting for stun-server response"; + } + QCoreApplication::exit(stunFailureExitStatus); + }); setState(waitForStunResponse); } else { - qDebug() << "using cached STUN resposne"; + if (_verbose) { + qDebug() << "using cached STUN response"; + } _publicSockAddr.setPort(_socket->localPort()); setState(talkToIceServer); } @@ -171,18 +210,30 @@ void ICEClientApp::doSomething() { setState(waitForIceReply); } _sessionUUID = QUuid::createUuid(); - qDebug() << "I am" << _sessionUUID; + if (_verbose) { + qDebug() << "I am" << _sessionUUID; + } sendPacketToIceServer(PacketType::ICEServerQuery, _iceServerAddr, _sessionUUID, peerID); - - _actionCount++; + _iceResponseTimerCanceled = false; + _iceResponseTimer.singleShot(iceResponseTimeoutMilliSeconds, this, [=] { + if (_iceResponseTimerCanceled) { + return; + } + if (_verbose) { + qDebug() << "timeout waiting for ice-server response"; + } + QCoreApplication::exit(iceFailureExitStatus); + }); } else if (_state == pause0) { setState(pause1); } else if (_state == pause1) { - qDebug() << ""; + if (_verbose) { + qDebug() << ""; + } + closeSocket(); setState(sendStunRequestPacket); - delete _socket; - _socket = nullptr; + _actionCount++; } } @@ -198,42 +249,68 @@ void ICEClientApp::sendPacketToIceServer(PacketType packetType, const HifiSockAd iceDataStream << peerID; - qDebug() << "Sending packet to ICE server to request connection info for peer with ID" - << uuidStringWithoutCurlyBraces(peerID); + if (_verbose) { + qDebug() << "Sending packet to ICE server to request connection info for peer with ID" + << uuidStringWithoutCurlyBraces(peerID); + } } // fillPacketHeader(packet, connectionSecret); _socket->writePacket(*icePacket, _iceServerAddr); } +void ICEClientApp::checkDomainPingCount() { + _domainPingCount++; + if (_domainPingCount > 5) { + if (_verbose) { + qDebug() << "too many unanswered pings to domain-server."; + } + QCoreApplication::exit(domainPingExitStatus); + } +} + void ICEClientApp::icePingDomainServer() { if (!_domainServerPeerSet) { return; } - qDebug() << "ice-pinging domain-server: " << _domainServerPeer; + if (_verbose) { + qDebug() << "ice-pinging domain-server: " << _domainServerPeer; + } auto localPingPacket = LimitedNodeList::constructICEPingPacket(PingType::Local, _sessionUUID); _socket->writePacket(*localPingPacket, _domainServerPeer.getLocalSocket()); auto publicPingPacket = LimitedNodeList::constructICEPingPacket(PingType::Public, _sessionUUID); _socket->writePacket(*publicPingPacket, _domainServerPeer.getPublicSocket()); + checkDomainPingCount(); } void ICEClientApp::processSTUNResponse(std::unique_ptr packet) { - qDebug() << "got stun response"; - if (_state != waitForStunResponse) { - qDebug() << "got unexpected stun response"; - return; + if (_verbose) { + qDebug() << "got stun response"; } + if (_state != waitForStunResponse) { + if (_verbose) { + qDebug() << "got unexpected stun response"; + } + QCoreApplication::exit(stunFailureExitStatus); + } + + _stunResponseTimer.stop(); + _stunResponseTimerCanceled = true; uint16_t newPublicPort; QHostAddress newPublicAddress; if (LimitedNodeList::parseSTUNResponse(packet.get(), newPublicAddress, newPublicPort)) { _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); - qDebug() << "My public address is" << _publicSockAddr; + if (_verbose) { + qDebug() << "My public address is" << _publicSockAddr; + } _stunResultSet = true; setState(talkToIceServer); + } else { + QCoreApplication::exit(stunFailureExitStatus); } } @@ -242,7 +319,9 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { std::unique_ptr nlPacket = NLPacket::fromBase(std::move(packet)); if (nlPacket->getPayloadSize() < NLPacket::localHeaderSize(PacketType::ICEServerHeartbeat)) { - qDebug() << "got a short packet."; + if (_verbose) { + qDebug() << "got a short packet."; + } return; } @@ -250,10 +329,16 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { const HifiSockAddr& senderAddr = message->getSenderSockAddr(); if (nlPacket->getType() == PacketType::ICEServerPeerInformation) { + // cancel the timeout timer + _iceResponseTimer.stop(); + _iceResponseTimerCanceled = true; + QDataStream iceResponseStream(message->getMessage()); if (!_domainServerPeerSet) { iceResponseStream >> _domainServerPeer; - qDebug() << "got ICEServerPeerInformation from" << _domainServerPeer; + if (_verbose) { + qDebug() << "got ICEServerPeerInformation from" << _domainServerPeer; + } _domainServerPeerSet = true; icePingDomainServer(); @@ -263,16 +348,23 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { } else { NetworkPeer domainServerPeer; iceResponseStream >> domainServerPeer; - qDebug() << "got repeat ICEServerPeerInformation from" << domainServerPeer; + if (_verbose) { + qDebug() << "got repeat ICEServerPeerInformation from" << domainServerPeer; + } } } else if (nlPacket->getType() == PacketType::ICEPing) { - qDebug() << "got packet: " << nlPacket->getType(); + if (_verbose) { + qDebug() << "got packet: " << nlPacket->getType(); + } auto replyPacket = LimitedNodeList::constructICEPingReplyPacket(*message, _sessionUUID); _socket->writePacket(*replyPacket, senderAddr); + checkDomainPingCount(); } else if (nlPacket->getType() == PacketType::ICEPingReply) { - qDebug() << "got packet: " << nlPacket->getType(); + if (_verbose) { + qDebug() << "got packet: " << nlPacket->getType(); + } if (_domainServerPeerSet && _state == waitForIceReply && (senderAddr == _domainServerPeer.getLocalSocket() || senderAddr == _domainServerPeer.getPublicSocket())) { @@ -282,10 +374,14 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { setState(pause0); } else { - qDebug() << "got unexpected ICEPingReply" << senderAddr; + if (_verbose) { + qDebug() << "got unexpected ICEPingReply" << senderAddr; + } } } else { - qDebug() << "got unexpected packet: " << nlPacket->getType(); + if (_verbose) { + qDebug() << "got unexpected packet: " << nlPacket->getType(); + } } } diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h index a3adc3e665..3635bc07f4 100644 --- a/tools/ice-client/src/ICEClientApp.h +++ b/tools/ice-client/src/ICEClientApp.h @@ -26,6 +26,13 @@ public: ICEClientApp(int argc, char* argv[]); ~ICEClientApp(); + const int stunFailureExitStatus { 1 }; + const int iceFailureExitStatus { 2 }; + const int domainPingExitStatus { 3 }; + + const int stunResponseTimeoutMilliSeconds { 2000 }; + const int iceResponseTimeoutMilliSeconds { 2000 }; + private: enum State { lookUpStunServer, // 0 @@ -48,6 +55,7 @@ private: void icePingDomainServer(); void processSTUNResponse(std::unique_ptr packet); void processPacket(std::unique_ptr packet); + void checkDomainPingCount(); bool _verbose; bool _cacheSTUNResult; // should we only talk to stun server once? @@ -73,8 +81,16 @@ private: NetworkPeer _domainServerPeer; int _state { 0 }; + + QTimer _stunResponseTimer; + bool _stunResponseTimerCanceled { false }; + QTimer _iceResponseTimer; + bool _iceResponseTimerCanceled { false }; + int _domainPingCount { 0 }; }; + + #endif //hifi_ICEClientApp_h