From babe8f95bcedc0036f270c353fe9ee2000ec94d6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 13:34:05 -0700 Subject: [PATCH 01/14] tool for testing ice-server --- libraries/networking/src/LimitedNodeList.h | 4 ++-- tools/CMakeLists.txt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index cd343a5232..1a3599e226 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -166,8 +166,8 @@ public: std::unique_ptr constructPingPacket(PingType_t pingType = PingType::Agnostic); std::unique_ptr constructPingReplyPacket(ReceivedMessage& message); - std::unique_ptr constructICEPingPacket(PingType_t pingType, const QUuid& iceID); - std::unique_ptr constructICEPingReplyPacket(ReceivedMessage& message, const QUuid& iceID); + static std::unique_ptr constructICEPingPacket(PingType_t pingType, const QUuid& iceID); + static std::unique_ptr constructICEPingReplyPacket(ReceivedMessage& message, const QUuid& iceID); void sendPeerQueryToIceServer(const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index bf645f25c2..a077efc335 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -7,3 +7,6 @@ set_target_properties(udt-test PROPERTIES FOLDER "Tools") add_subdirectory(vhacd-util) set_target_properties(vhacd-util PROPERTIES FOLDER "Tools") + +add_subdirectory(ice-client) +set_target_properties(ice-client PROPERTIES FOLDER "Tools") From cadbbd619496cedde6b0a4f88062631808aa870e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 13:34:32 -0700 Subject: [PATCH 02/14] tool for testing ice-server --- tools/ice-client/CMakeLists.txt | 3 ++ tools/ice-client/src/ICEClientApp.h | 63 +++++++++++++++++++++++++++++ tools/ice-client/src/main.cpp | 23 +++++++++++ 3 files changed, 89 insertions(+) create mode 100644 tools/ice-client/CMakeLists.txt create mode 100644 tools/ice-client/src/ICEClientApp.h create mode 100644 tools/ice-client/src/main.cpp diff --git a/tools/ice-client/CMakeLists.txt b/tools/ice-client/CMakeLists.txt new file mode 100644 index 0000000000..a80145974c --- /dev/null +++ b/tools/ice-client/CMakeLists.txt @@ -0,0 +1,3 @@ +set(TARGET_NAME ice-client) +setup_hifi_project(Core Widgets) +link_hifi_libraries(shared networking) diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h new file mode 100644 index 0000000000..6728a0ed83 --- /dev/null +++ b/tools/ice-client/src/ICEClientApp.h @@ -0,0 +1,63 @@ +// +// ICEClient.h +// tools/ice-client/src +// +// Created by Seth Alves on 2016-9-16 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#ifndef hifi_ICEClientApp_h +#define hifi_ICEClientApp_h + +#include +#include +#include +#include +#include + + +class ICEClientApp : public QCoreApplication { + Q_OBJECT +public: + ICEClientApp(int argc, char* argv[]); + ~ICEClientApp(); + +private: + void doSomething(); + void sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, + const QUuid& clientID, const QUuid& peerID); + void icePingDomainServer(); + void processPacket(std::unique_ptr packet); + + bool _verbose; + + unsigned int _actionCount { 0 }; + unsigned int _actionMax { 0 }; + + QUuid _sessionUUID; + + QTimer* _pingDomainTimer { nullptr }; + + HifiSockAddr _iceServerAddr; + + HifiSockAddr _localSockAddr; + HifiSockAddr _publicSockAddr; + udt::Socket* _socket { nullptr }; + + bool _domainServerPeerSet { false }; + NetworkPeer _domainServerPeer; + + // 0 -- time to talk to ice server + // 1 -- waiting for ICEPingReply + // 2 -- pause + // 3 -- pause + int _state { 0 }; +}; + + + +#endif //hifi_ICEClientApp_h diff --git a/tools/ice-client/src/main.cpp b/tools/ice-client/src/main.cpp new file mode 100644 index 0000000000..c70a7eb7d7 --- /dev/null +++ b/tools/ice-client/src/main.cpp @@ -0,0 +1,23 @@ +// +// main.cpp +// tools/ice-client/src +// +// Created by Seth Alves on 2016-9-16 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +#include +#include +#include +#include + +#include "ICEClientApp.h" + +using namespace std; + +int main(int argc, char * argv[]) { + ICEClientApp app(argc, argv); + return app.exec(); +} From 6231fc4ba1da32d856e01217ed80f6a14735cd07 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 13:34:40 -0700 Subject: [PATCH 03/14] tool for testing ice-server --- tools/ice-client/src/ICEClientApp.cpp | 195 ++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 tools/ice-client/src/ICEClientApp.cpp diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp new file mode 100644 index 0000000000..f1629bf5e7 --- /dev/null +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -0,0 +1,195 @@ +// +// ICEClient.h +// tools/ice-client/src +// +// Created by Seth Alves on 3/5/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include + +#include "ICEClientApp.h" + +ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity ICE client"); + parser.addHelpOption(); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption verboseOutput("v", "verbose output"); + parser.addOption(verboseOutput); + + 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"); + parser.addOption(howManyTimesOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + _verbose = parser.isSet(verboseOutput); + + if (parser.isSet(howManyTimesOption)) { + _actionMax = parser.value(howManyTimesOption).toInt(); + } + + _iceServerAddr = HifiSockAddr("127.0.0.1", ICE_SERVER_DEFAULT_PORT); + if (parser.isSet(iceServerAddressOption)) { + // parse the IP and port combination for this target + QString hostnamePortString = parser.value(iceServerAddressOption); + + QHostAddress address { hostnamePortString.left(hostnamePortString.indexOf(':')) }; + quint16 port { (quint16) hostnamePortString.mid(hostnamePortString.indexOf(':') + 1).toUInt() }; + + if (address.isNull() || port == 0) { + qCritical() << "Could not parse an IP address and port combination from" << hostnamePortString << "-" << + "The parsed IP was" << address.toString() << "and the parsed port was" << port; + + QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); + } else { + _iceServerAddr = HifiSockAddr(address, port); + } + } + + qDebug() << "ICE-server address is" << _iceServerAddr; + + _state = 0; + + QTimer* doTimer = new QTimer(this); + connect(doTimer, &QTimer::timeout, this, &ICEClientApp::doSomething); + doTimer->start(200); +} + +ICEClientApp::~ICEClientApp() { + delete _socket; +} + +void ICEClientApp::doSomething() { + if (_actionMax > 0 && _actionCount >= _actionMax) { + QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); + } + + if (_state == 0) { + _domainServerPeerSet = false; + unsigned int localPort = 0; + _socket = new udt::Socket(); + _socket->bind(QHostAddress::AnyIPv4, localPort); + _socket->setPacketHandler([this](std::unique_ptr packet) { processPacket(std::move(packet)); }); + + qDebug() << "local port is" << _socket->localPort(); + _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); + _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); + + QUuid peerID = QUuid("75cd162a-53dc-4292-aaa5-1304ab1bb0f2"); + _sessionUUID = QUuid::createUuid(); + + sendPacketToIceServer(PacketType::ICEServerQuery, _iceServerAddr, _sessionUUID, peerID); + + _state = 1; + _actionCount++; + } else if (_state == 2) { + _state = 3; + } else if (_state == 3) { + qDebug() << ""; + _state = 0; + delete _socket; + _socket = nullptr; + } +} + +void ICEClientApp::sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, + const QUuid& clientID, const QUuid& peerID) { + std::unique_ptr icePacket = NLPacket::create(packetType); + + QDataStream iceDataStream(icePacket.get()); + iceDataStream << clientID << _publicSockAddr << _localSockAddr; + + if (packetType == PacketType::ICEServerQuery) { + assert(!peerID.isNull()); + + iceDataStream << peerID; + + 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::icePingDomainServer() { + if (!_domainServerPeerSet) { + return; + } + + qDebug() << "ice-pinging domain-server"; + + auto localPingPacket = LimitedNodeList::constructICEPingPacket(PingType::Local, _sessionUUID); + _socket->writePacket(*localPingPacket, _domainServerPeer.getLocalSocket()); + + auto publicPingPacket = LimitedNodeList::constructICEPingPacket(PingType::Public, _sessionUUID); + _socket->writePacket(*publicPingPacket, _domainServerPeer.getPublicSocket()); +} + + +void ICEClientApp::processPacket(std::unique_ptr packet) { + auto nlPacket = NLPacket::fromBase(std::move(packet)); + + if (nlPacket->getPayloadSize() < NLPacket::localHeaderSize(PacketType::ICEServerHeartbeat)) { + qDebug() << "got a short packet."; + return; + } + + QSharedPointer message = QSharedPointer::create(*nlPacket); + const HifiSockAddr& senderAddr = message->getSenderSockAddr(); + + if (nlPacket->getType() == PacketType::ICEServerPeerInformation) { + QDataStream iceResponseStream(message->getMessage()); + iceResponseStream >> _domainServerPeer; + _domainServerPeerSet = true; + + icePingDomainServer(); + _pingDomainTimer = new QTimer(this); + connect(_pingDomainTimer, &QTimer::timeout, this, &ICEClientApp::icePingDomainServer); + _pingDomainTimer->start(1000); + + qDebug() << "got ICEServerPeerInformation from" << _domainServerPeer.getUUID(); + + } else if (nlPacket->getType() == PacketType::ICEPing) { + qDebug() << "got packet: " << nlPacket->getType(); + auto replyPacket = LimitedNodeList::constructICEPingReplyPacket(*message, _sessionUUID); + _socket->writePacket(*replyPacket, senderAddr); + + } else if (nlPacket->getType() == PacketType::ICEPingReply) { + qDebug() << "got packet: " << nlPacket->getType(); + if (_domainServerPeerSet && _state == 1 && + (senderAddr == _domainServerPeer.getLocalSocket() || + senderAddr == _domainServerPeer.getPublicSocket())) { + + delete _pingDomainTimer; + _pingDomainTimer = nullptr; + + _state = 2; + } + + } else { + qDebug() << "got unexpected packet: " << nlPacket->getType(); + } +} From d3dc0698a52f4885d72c12ef1d9808828bcd6e82 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 13:51:33 -0700 Subject: [PATCH 04/14] more command-line arguments --- tools/ice-client/src/ICEClientApp.cpp | 22 ++++++++++++++++++++-- tools/ice-client/src/ICEClientApp.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index f1629bf5e7..c1c2d047cc 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -33,6 +33,10 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv const QCommandLineOption howManyTimesOption("n", "how many times to cycle", "0"); parser.addOption(howManyTimesOption); + const QCommandLineOption domainIDOption("d", "domain-server uuid"); + parser.addOption(domainIDOption); + + if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); @@ -50,6 +54,11 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv _actionMax = parser.value(howManyTimesOption).toInt(); } + if (parser.isSet(domainIDOption)) { + _domainID = QUuid(parser.value(howManyTimesOption)); + } + + _iceServerAddr = HifiSockAddr("127.0.0.1", ICE_SERVER_DEFAULT_PORT); if (parser.isSet(iceServerAddressOption)) { // parse the IP and port combination for this target @@ -97,12 +106,21 @@ void ICEClientApp::doSomething() { _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); - QUuid peerID = QUuid("75cd162a-53dc-4292-aaa5-1304ab1bb0f2"); + // QUuid peerID = QUuid("75cd162a-53dc-4292-aaa5-1304ab1bb0f2"); + QUuid peerID; + if (_domainID == QUuid()) { + // pick a random domain-id + peerID = QUuid::createUuid(); + _state = 2; + } else { + // use the domain UUID given on the command-line + peerID = _domainID; + _state = 1; + } _sessionUUID = QUuid::createUuid(); sendPacketToIceServer(PacketType::ICEServerQuery, _iceServerAddr, _sessionUUID, peerID); - _state = 1; _actionCount++; } else if (_state == 2) { _state = 3; diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h index 6728a0ed83..de40d07338 100644 --- a/tools/ice-client/src/ICEClientApp.h +++ b/tools/ice-client/src/ICEClientApp.h @@ -39,6 +39,7 @@ private: unsigned int _actionMax { 0 }; QUuid _sessionUUID; + QUuid _domainID; QTimer* _pingDomainTimer { nullptr }; From 793687bb08414bed94f311aee553dfdc3df249f5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 14:11:44 -0700 Subject: [PATCH 05/14] more command-line arguments --- tools/ice-client/src/ICEClientApp.cpp | 7 ++++--- tools/ice-client/src/ICEClientApp.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index c1c2d047cc..f0000c78cf 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -1,5 +1,5 @@ // -// ICEClient.h +// ICEClientApp.cpp // tools/ice-client/src // // Created by Seth Alves on 3/5/15. @@ -33,7 +33,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv const QCommandLineOption howManyTimesOption("n", "how many times to cycle", "0"); parser.addOption(howManyTimesOption); - const QCommandLineOption domainIDOption("d", "domain-server uuid"); + const QCommandLineOption domainIDOption("d", "domain-server uuid", "00000000-0000-0000-0000-000000000000"); parser.addOption(domainIDOption); @@ -55,7 +55,8 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv } if (parser.isSet(domainIDOption)) { - _domainID = QUuid(parser.value(howManyTimesOption)); + _domainID = QUuid(parser.value(domainIDOption)); + qDebug() << "domain-server ID is" << _domainID; } diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h index de40d07338..efdbc9e022 100644 --- a/tools/ice-client/src/ICEClientApp.h +++ b/tools/ice-client/src/ICEClientApp.h @@ -1,5 +1,5 @@ // -// ICEClient.h +// ICEClientApp.h // tools/ice-client/src // // Created by Seth Alves on 2016-9-16 From 2e0cc158de4500a7b16b304d44ca242ef0e4d02c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 17:21:28 -0700 Subject: [PATCH 06/14] ice test-client uses stun server to get public address --- libraries/networking/src/LimitedNodeList.cpp | 170 ++++++++++--------- libraries/networking/src/LimitedNodeList.h | 8 +- tools/ice-client/src/ICEClientApp.cpp | 106 +++++++++--- 3 files changed, 177 insertions(+), 107 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 5aa31efea4..ec4b2c3573 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -745,8 +745,32 @@ void LimitedNodeList::removeSilentNodes() { const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442; const int NUM_BYTES_STUN_HEADER = 20; -void LimitedNodeList::sendSTUNRequest() { +void LimitedNodeList::makeSTUNRequestPacket(char* stunRequestPacket) { + int packetIndex = 0; + + const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE); + + // leading zeros + message type + const uint16_t REQUEST_MESSAGE_TYPE = htons(0x0001); + memcpy(stunRequestPacket + packetIndex, &REQUEST_MESSAGE_TYPE, sizeof(REQUEST_MESSAGE_TYPE)); + packetIndex += sizeof(REQUEST_MESSAGE_TYPE); + + // message length (no additional attributes are included) + uint16_t messageLength = 0; + memcpy(stunRequestPacket + packetIndex, &messageLength, sizeof(messageLength)); + packetIndex += sizeof(messageLength); + + memcpy(stunRequestPacket + packetIndex, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)); + packetIndex += sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); + + // transaction ID (random 12-byte unsigned integer) + const uint NUM_TRANSACTION_ID_BYTES = 12; + QUuid randomUUID = QUuid::createUuid(); + memcpy(stunRequestPacket + packetIndex, randomUUID.toRfc4122().data(), NUM_TRANSACTION_ID_BYTES); +} + +void LimitedNodeList::sendSTUNRequest() { if (!_stunSockAddr.getAddress().isNull()) { const int NUM_INITIAL_STUN_REQUESTS_BEFORE_FAIL = 10; @@ -762,36 +786,14 @@ void LimitedNodeList::sendSTUNRequest() { } char stunRequestPacket[NUM_BYTES_STUN_HEADER]; - - int packetIndex = 0; - - const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(RFC_5389_MAGIC_COOKIE); - - // leading zeros + message type - const uint16_t REQUEST_MESSAGE_TYPE = htons(0x0001); - memcpy(stunRequestPacket + packetIndex, &REQUEST_MESSAGE_TYPE, sizeof(REQUEST_MESSAGE_TYPE)); - packetIndex += sizeof(REQUEST_MESSAGE_TYPE); - - // message length (no additional attributes are included) - uint16_t messageLength = 0; - memcpy(stunRequestPacket + packetIndex, &messageLength, sizeof(messageLength)); - packetIndex += sizeof(messageLength); - - memcpy(stunRequestPacket + packetIndex, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)); - packetIndex += sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); - - // transaction ID (random 12-byte unsigned integer) - const uint NUM_TRANSACTION_ID_BYTES = 12; - QUuid randomUUID = QUuid::createUuid(); - memcpy(stunRequestPacket + packetIndex, randomUUID.toRfc4122().data(), NUM_TRANSACTION_ID_BYTES); - + makeSTUNRequestPacket(stunRequestPacket); flagTimeForConnectionStep(ConnectionStep::SendSTUNRequest); - _nodeSocket.writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr); } } -void LimitedNodeList::processSTUNResponse(std::unique_ptr packet) { +bool LimitedNodeList::parseSTUNResponse(udt::BasePacket* packet, + QHostAddress& newPublicAddress, uint16_t& newPublicPort) { // check the cookie to make sure this is actually a STUN response // and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4; @@ -803,71 +805,79 @@ void LimitedNodeList::processSTUNResponse(std::unique_ptr packe if (memcmp(packet->getData() + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, - sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0) { + sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) != 0) { + return false; + } - // enumerate the attributes to find XOR_MAPPED_ADDRESS_TYPE - while (attributeStartIndex < packet->getDataSize()) { + // enumerate the attributes to find XOR_MAPPED_ADDRESS_TYPE + while (attributeStartIndex < packet->getDataSize()) { + if (memcmp(packet->getData() + attributeStartIndex, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { + const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4; + const int NUM_BYTES_FAMILY_ALIGN = 1; + const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8; - if (memcmp(packet->getData() + attributeStartIndex, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { - const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4; - const int NUM_BYTES_FAMILY_ALIGN = 1; - const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8; + int byteIndex = attributeStartIndex + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN; - int byteIndex = attributeStartIndex + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN; + uint8_t addressFamily = 0; + memcpy(&addressFamily, packet->getData() + byteIndex, sizeof(addressFamily)); - uint8_t addressFamily = 0; - memcpy(&addressFamily, packet->getData() + byteIndex, sizeof(addressFamily)); + byteIndex += sizeof(addressFamily); - byteIndex += sizeof(addressFamily); + if (addressFamily == IPV4_FAMILY_NETWORK_ORDER) { + // grab the X-Port + uint16_t xorMappedPort = 0; + memcpy(&xorMappedPort, packet->getData() + byteIndex, sizeof(xorMappedPort)); - if (addressFamily == IPV4_FAMILY_NETWORK_ORDER) { - // grab the X-Port - uint16_t xorMappedPort = 0; - memcpy(&xorMappedPort, packet->getData() + byteIndex, sizeof(xorMappedPort)); + newPublicPort = ntohs(xorMappedPort) ^ (ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER) >> 16); - uint16_t newPublicPort = ntohs(xorMappedPort) ^ (ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER) >> 16); + byteIndex += sizeof(xorMappedPort); - byteIndex += sizeof(xorMappedPort); + // grab the X-Address + uint32_t xorMappedAddress = 0; + memcpy(&xorMappedAddress, packet->getData() + byteIndex, sizeof(xorMappedAddress)); - // grab the X-Address - uint32_t xorMappedAddress = 0; - memcpy(&xorMappedAddress, packet->getData() + byteIndex, sizeof(xorMappedAddress)); + uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); - uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); - - QHostAddress newPublicAddress(stunAddress); - - if (newPublicAddress != _publicSockAddr.getAddress() || newPublicPort != _publicSockAddr.getPort()) { - _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); - - qCDebug(networking, "New public socket received from STUN server is %s:%hu", - _publicSockAddr.getAddress().toString().toLocal8Bit().constData(), - _publicSockAddr.getPort()); - - if (!_hasCompletedInitialSTUN) { - // if we're here we have definitely completed our initial STUN sequence - stopInitialSTUNUpdate(true); - } - - emit publicSockAddrChanged(_publicSockAddr); - - flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN); - } - - // we're done reading the packet so we can return now - return; - } - } else { - // push forward attributeStartIndex by the length of this attribute - const int NUM_BYTES_ATTRIBUTE_TYPE = 2; - - uint16_t attributeLength = 0; - memcpy(&attributeLength, packet->getData() + attributeStartIndex + NUM_BYTES_ATTRIBUTE_TYPE, - sizeof(attributeLength)); - attributeLength = ntohs(attributeLength); - - attributeStartIndex += NUM_BYTES_MESSAGE_TYPE_AND_LENGTH + attributeLength; + // QHostAddress newPublicAddress(stunAddress); + newPublicAddress = QHostAddress(stunAddress); + return true; } + } else { + // push forward attributeStartIndex by the length of this attribute + const int NUM_BYTES_ATTRIBUTE_TYPE = 2; + + uint16_t attributeLength = 0; + memcpy(&attributeLength, packet->getData() + attributeStartIndex + NUM_BYTES_ATTRIBUTE_TYPE, + sizeof(attributeLength)); + attributeLength = ntohs(attributeLength); + + attributeStartIndex += NUM_BYTES_MESSAGE_TYPE_AND_LENGTH + attributeLength; + } + } + return false; +} + + +void LimitedNodeList::processSTUNResponse(std::unique_ptr packet) { + uint16_t newPublicPort; + QHostAddress newPublicAddress; + if (parseSTUNResponse(packet.get(), newPublicAddress, newPublicPort)) { + + if (newPublicAddress != _publicSockAddr.getAddress() || newPublicPort != _publicSockAddr.getPort()) { + _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); + + qCDebug(networking, "New public socket received from STUN server is %s:%hu", + _publicSockAddr.getAddress().toString().toLocal8Bit().constData(), + _publicSockAddr.getPort()); + + if (!_hasCompletedInitialSTUN) { + // if we're here we have definitely completed our initial STUN sequence + stopInitialSTUNUpdate(true); + } + + emit publicSockAddrChanged(_publicSockAddr); + + flagTimeForConnectionStep(ConnectionStep::SetPublicSocketFromSTUN); } } } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 1a3599e226..e74a6c49f8 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -146,6 +146,7 @@ public: const NodePermissions& permissions = DEFAULT_AGENT_PERMISSIONS, const QUuid& connectionSecret = QUuid()); + static bool parseSTUNResponse(udt::BasePacket* packet, QHostAddress& newPublicAddress, uint16_t& newPublicPort); bool hasCompletedInitialSTUN() const { return _hasCompletedInitialSTUN; } const HifiSockAddr& getLocalSockAddr() const { return _localSockAddr; } @@ -232,6 +233,9 @@ public: bool packetVersionMatch(const udt::Packet& packet); bool isPacketVerified(const udt::Packet& packet); + static void makeSTUNRequestPacket(char* stunRequestPacket); + + public slots: void reset(); void eraseAllNodes(); @@ -275,7 +279,7 @@ protected: LimitedNodeList(int socketListenPort = INVALID_PORT, int dtlsListenPort = INVALID_PORT); LimitedNodeList(LimitedNodeList const&) = delete; // Don't implement, needed to avoid copies of singleton void operator=(LimitedNodeList const&) = delete; // Don't implement, needed to avoid copies of singleton - + qint64 sendPacket(std::unique_ptr packet, const Node& destinationNode, const HifiSockAddr& overridenSockAddr); qint64 writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr, @@ -284,7 +288,7 @@ protected: void fillPacketHeader(const NLPacket& packet, const QUuid& connectionSecret = QUuid()); void setLocalSocket(const HifiSockAddr& sockAddr); - + bool packetSourceAndHashMatchAndTrackBandwidth(const udt::Packet& packet); void processSTUNResponse(std::unique_ptr packet); diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index f0000c78cf..8614fbf960 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -16,7 +16,10 @@ #include "ICEClientApp.h" -ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv) { +ICEClientApp::ICEClientApp(int argc, char* argv[]) : + QCoreApplication(argc, argv), + _stunSockAddr(STUN_SERVER_HOSTNAME, STUN_SERVER_PORT) +{ // parse command-line QCommandLineParser parser; parser.setApplicationDescription("High Fidelity ICE client"); @@ -80,7 +83,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : QCoreApplication(argc, argv qDebug() << "ICE-server address is" << _iceServerAddr; - _state = 0; + setState(lookUpStunServer); QTimer* doTimer = new QTimer(this); connect(doTimer, &QTimer::timeout, this, &ICEClientApp::doSomething); @@ -91,43 +94,71 @@ ICEClientApp::~ICEClientApp() { delete _socket; } +void ICEClientApp::setState(int newState) { + // qDebug() << "state: " << _state << " --> " << newState; + _state = newState; +} + void ICEClientApp::doSomething() { if (_actionMax > 0 && _actionCount >= _actionMax) { + // time to stop. QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); - } - if (_state == 0) { + } else if (_state == lookUpStunServer) { + // lookup STUN server address + if (!_stunSockAddr.getAddress().isNull()) { + qDebug() << "stun server is" << _stunSockAddr; + setState(sendStunRequestPacket); + } + + } else if (_state == sendStunRequestPacket) { + // send STUN request packet + _domainServerPeerSet = false; unsigned int localPort = 0; + delete _socket; _socket = new udt::Socket(); _socket->bind(QHostAddress::AnyIPv4, localPort); - _socket->setPacketHandler([this](std::unique_ptr packet) { processPacket(std::move(packet)); }); + _socket->setPacketHandler([this](std::unique_ptr packet) { processPacket(std::move(packet)); }); + _socket->addUnfilteredHandler(_stunSockAddr, + [this](std::unique_ptr packet) { + processSTUNResponse(std::move(packet)); + }); qDebug() << "local port is" << _socket->localPort(); _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); - // QUuid peerID = QUuid("75cd162a-53dc-4292-aaa5-1304ab1bb0f2"); + const int NUM_BYTES_STUN_HEADER = 20; + char stunRequestPacket[NUM_BYTES_STUN_HEADER]; + LimitedNodeList::makeSTUNRequestPacket(stunRequestPacket); + qDebug() << "sending STUN request"; + _socket->writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr); + + setState(waitForStunResponse); + + } else if (_state == talkToIceServer) { QUuid peerID; if (_domainID == QUuid()) { - // pick a random domain-id + // pick a random domain-id which will fail peerID = QUuid::createUuid(); - _state = 2; + setState(pause0); } else { // use the domain UUID given on the command-line peerID = _domainID; - _state = 1; + setState(waitForIceReply); } _sessionUUID = QUuid::createUuid(); + qDebug() << "I am" << _sessionUUID; sendPacketToIceServer(PacketType::ICEServerQuery, _iceServerAddr, _sessionUUID, peerID); _actionCount++; - } else if (_state == 2) { - _state = 3; - } else if (_state == 3) { + } else if (_state == pause0) { + setState(pause1); + } else if (_state == pause1) { qDebug() << ""; - _state = 0; + setState(sendStunRequestPacket); delete _socket; _socket = nullptr; } @@ -158,7 +189,7 @@ void ICEClientApp::icePingDomainServer() { return; } - qDebug() << "ice-pinging domain-server"; + qDebug() << "ice-pinging domain-server: " << _domainServerPeer; auto localPingPacket = LimitedNodeList::constructICEPingPacket(PingType::Local, _sessionUUID); _socket->writePacket(*localPingPacket, _domainServerPeer.getLocalSocket()); @@ -167,29 +198,52 @@ void ICEClientApp::icePingDomainServer() { _socket->writePacket(*publicPingPacket, _domainServerPeer.getPublicSocket()); } +void ICEClientApp::processSTUNResponse(std::unique_ptr packet) { + qDebug() << "got stun response"; + if (_state != waitForStunResponse) { + qDebug() << "got unexpected stun response"; + return; + } + + uint16_t newPublicPort; + QHostAddress newPublicAddress; + if (LimitedNodeList::parseSTUNResponse(packet.get(), newPublicAddress, newPublicPort)) { + _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); + qDebug() << "My public address is" << _publicSockAddr; + setState(talkToIceServer); + } +} + void ICEClientApp::processPacket(std::unique_ptr packet) { - auto nlPacket = NLPacket::fromBase(std::move(packet)); + std::unique_ptr nlPacket = NLPacket::fromBase(std::move(packet)); if (nlPacket->getPayloadSize() < NLPacket::localHeaderSize(PacketType::ICEServerHeartbeat)) { qDebug() << "got a short packet."; return; } + qDebug() << "here" << nlPacket->getType(); + QSharedPointer message = QSharedPointer::create(*nlPacket); const HifiSockAddr& senderAddr = message->getSenderSockAddr(); if (nlPacket->getType() == PacketType::ICEServerPeerInformation) { QDataStream iceResponseStream(message->getMessage()); - iceResponseStream >> _domainServerPeer; - _domainServerPeerSet = true; + if (!_domainServerPeerSet) { + iceResponseStream >> _domainServerPeer; + qDebug() << "got ICEServerPeerInformation from" << _domainServerPeer; + _domainServerPeerSet = true; - icePingDomainServer(); - _pingDomainTimer = new QTimer(this); - connect(_pingDomainTimer, &QTimer::timeout, this, &ICEClientApp::icePingDomainServer); - _pingDomainTimer->start(1000); - - qDebug() << "got ICEServerPeerInformation from" << _domainServerPeer.getUUID(); + icePingDomainServer(); + _pingDomainTimer = new QTimer(this); + connect(_pingDomainTimer, &QTimer::timeout, this, &ICEClientApp::icePingDomainServer); + _pingDomainTimer->start(500); + } else { + // NetworkPeer domainServerPeer; + // iceResponseStream >> domainServerPeer; + // qDebug() << "got repeat ICEServerPeerInformation from" << domainServerPeer; + } } else if (nlPacket->getType() == PacketType::ICEPing) { qDebug() << "got packet: " << nlPacket->getType(); @@ -198,14 +252,16 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { } else if (nlPacket->getType() == PacketType::ICEPingReply) { qDebug() << "got packet: " << nlPacket->getType(); - if (_domainServerPeerSet && _state == 1 && + if (_domainServerPeerSet && _state == waitForIceReply && (senderAddr == _domainServerPeer.getLocalSocket() || senderAddr == _domainServerPeer.getPublicSocket())) { delete _pingDomainTimer; _pingDomainTimer = nullptr; - _state = 2; + setState(pause0); + } else { + qDebug() << "got unexpected ICEPingReply" << senderAddr; } } else { From b5e216db684e088b06709722408d88ae3129f78a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 16 Sep 2016 17:21:42 -0700 Subject: [PATCH 07/14] ice test-client uses stun server to get public address --- tools/ice-client/src/ICEClientApp.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h index efdbc9e022..eee759b2ba 100644 --- a/tools/ice-client/src/ICEClientApp.h +++ b/tools/ice-client/src/ICEClientApp.h @@ -27,14 +27,29 @@ public: ~ICEClientApp(); private: + enum State { + lookUpStunServer, // 0 + sendStunRequestPacket, // 1 + waitForStunResponse, // 2 + talkToIceServer, // 3 + waitForIceReply, // 4 + pause0, // 5 + pause1 // 6 + }; + + void setState(int newState); + void doSomething(); void sendPacketToIceServer(PacketType packetType, const HifiSockAddr& iceServerSockAddr, const QUuid& clientID, const QUuid& peerID); void icePingDomainServer(); + void processSTUNResponse(std::unique_ptr packet); void processPacket(std::unique_ptr packet); bool _verbose; + HifiSockAddr _stunSockAddr; + unsigned int _actionCount { 0 }; unsigned int _actionMax { 0 }; @@ -52,10 +67,6 @@ private: bool _domainServerPeerSet { false }; NetworkPeer _domainServerPeer; - // 0 -- time to talk to ice server - // 1 -- waiting for ICEPingReply - // 2 -- pause - // 3 -- pause int _state { 0 }; }; From c87652ab6dc332e58772f9f5879e5d116315dc48 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 19 Sep 2016 13:34:56 -0700 Subject: [PATCH 08/14] cl flag to cache stun-server resposne --- tools/ice-client/src/ICEClientApp.cpp | 73 +++++++++++++++++---------- tools/ice-client/src/ICEClientApp.h | 5 ++ 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index 8614fbf960..9f11e0b569 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -39,6 +39,9 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : const QCommandLineOption domainIDOption("d", "domain-server uuid", "00000000-0000-0000-0000-000000000000"); parser.addOption(domainIDOption); + const QCommandLineOption cacheSTUNOption("s", "cache stun-server response"); + parser.addOption(cacheSTUNOption); + if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; @@ -52,6 +55,7 @@ ICEClientApp::ICEClientApp(int argc, char* argv[]) : } _verbose = parser.isSet(verboseOutput); + _cacheSTUNResult = parser.isSet(cacheSTUNOption); if (parser.isSet(howManyTimesOption)) { _actionMax = parser.value(howManyTimesOption).toInt(); @@ -99,6 +103,31 @@ void ICEClientApp::setState(int newState) { _state = newState; } +void ICEClientApp::closeSocket() { + _domainServerPeerSet = false; + delete _socket; + _socket = nullptr; +} + +void ICEClientApp::openSocket() { + if (_socket) { + return; + } + + _socket = new udt::Socket(); + unsigned int localPort = 0; + _socket->bind(QHostAddress::AnyIPv4, localPort); + _socket->setPacketHandler([this](std::unique_ptr packet) { processPacket(std::move(packet)); }); + _socket->addUnfilteredHandler(_stunSockAddr, + [this](std::unique_ptr packet) { + processSTUNResponse(std::move(packet)); + }); + + qDebug() << "local port is" << _socket->localPort(); + _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); + _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); +} + void ICEClientApp::doSomething() { if (_actionMax > 0 && _actionCount >= _actionMax) { // time to stop. @@ -113,29 +142,22 @@ void ICEClientApp::doSomething() { } else if (_state == sendStunRequestPacket) { // send STUN request packet + closeSocket(); + openSocket(); - _domainServerPeerSet = false; - unsigned int localPort = 0; - delete _socket; - _socket = new udt::Socket(); - _socket->bind(QHostAddress::AnyIPv4, localPort); - _socket->setPacketHandler([this](std::unique_ptr packet) { processPacket(std::move(packet)); }); - _socket->addUnfilteredHandler(_stunSockAddr, - [this](std::unique_ptr packet) { - processSTUNResponse(std::move(packet)); - }); + if (!_cacheSTUNResult || !_stunResultSet) { + const int NUM_BYTES_STUN_HEADER = 20; + char stunRequestPacket[NUM_BYTES_STUN_HEADER]; + LimitedNodeList::makeSTUNRequestPacket(stunRequestPacket); + qDebug() << "sending STUN request"; + _socket->writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr); - qDebug() << "local port is" << _socket->localPort(); - _localSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); - _publicSockAddr = HifiSockAddr("127.0.0.1", _socket->localPort()); - - const int NUM_BYTES_STUN_HEADER = 20; - char stunRequestPacket[NUM_BYTES_STUN_HEADER]; - LimitedNodeList::makeSTUNRequestPacket(stunRequestPacket); - qDebug() << "sending STUN request"; - _socket->writeDatagram(stunRequestPacket, sizeof(stunRequestPacket), _stunSockAddr); - - setState(waitForStunResponse); + setState(waitForStunResponse); + } else { + qDebug() << "using cached STUN resposne"; + _publicSockAddr.setPort(_socket->localPort()); + setState(talkToIceServer); + } } else if (_state == talkToIceServer) { QUuid peerID; @@ -210,6 +232,7 @@ void ICEClientApp::processSTUNResponse(std::unique_ptr packet) if (LimitedNodeList::parseSTUNResponse(packet.get(), newPublicAddress, newPublicPort)) { _publicSockAddr = HifiSockAddr(newPublicAddress, newPublicPort); qDebug() << "My public address is" << _publicSockAddr; + _stunResultSet = true; setState(talkToIceServer); } } @@ -223,8 +246,6 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { return; } - qDebug() << "here" << nlPacket->getType(); - QSharedPointer message = QSharedPointer::create(*nlPacket); const HifiSockAddr& senderAddr = message->getSenderSockAddr(); @@ -240,9 +261,9 @@ void ICEClientApp::processPacket(std::unique_ptr packet) { connect(_pingDomainTimer, &QTimer::timeout, this, &ICEClientApp::icePingDomainServer); _pingDomainTimer->start(500); } else { - // NetworkPeer domainServerPeer; - // iceResponseStream >> domainServerPeer; - // qDebug() << "got repeat ICEServerPeerInformation from" << domainServerPeer; + NetworkPeer domainServerPeer; + iceResponseStream >> domainServerPeer; + qDebug() << "got repeat ICEServerPeerInformation from" << domainServerPeer; } } else if (nlPacket->getType() == PacketType::ICEPing) { diff --git a/tools/ice-client/src/ICEClientApp.h b/tools/ice-client/src/ICEClientApp.h index eee759b2ba..a3adc3e665 100644 --- a/tools/ice-client/src/ICEClientApp.h +++ b/tools/ice-client/src/ICEClientApp.h @@ -37,6 +37,9 @@ private: pause1 // 6 }; + void closeSocket(); + void openSocket(); + void setState(int newState); void doSomething(); @@ -47,6 +50,8 @@ private: void processPacket(std::unique_ptr packet); bool _verbose; + bool _cacheSTUNResult; // should we only talk to stun server once? + bool _stunResultSet { false }; // have we already talked to stun server? HifiSockAddr _stunSockAddr; From 45b48c01bfdbe90e829048fc0d449a2c48bcde01 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 19 Sep 2016 13:39:42 -0700 Subject: [PATCH 09/14] command-line arguments to control ice-server ip address and domain-server ID --- domain-server/src/DomainServer.cpp | 78 ++++++++++++++++++++++++------ domain-server/src/DomainServer.h | 6 +++ 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 72e9751294..654fe500c6 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -62,8 +63,11 @@ DomainServer::DomainServer(int argc, char* argv[]) : _webAuthenticationStateSet(), _cookieSessionHash(), _automaticNetworkingSetting(), - _settingsManager() + _settingsManager(), + _iceServerAddr(ICE_SERVER_DEFAULT_HOSTNAME), + _iceServerPort(ICE_SERVER_DEFAULT_PORT) { + parseCommandLine(); qInstallMessageHandler(LogHandler::verboseMessageHandler); LogUtils::init(); @@ -147,6 +151,46 @@ DomainServer::DomainServer(int argc, char* argv[]) : qDebug() << "domain-server is running"; } +void DomainServer::parseCommandLine() { + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Domain Server"); + parser.addHelpOption(); + + const QCommandLineOption iceServerAddressOption("i", "ice-server address", "IP:PORT or HOSTNAME:PORT"); + parser.addOption(iceServerAddressOption); + + const QCommandLineOption domainIDOption("d", "domain-server uuid"); + parser.addOption(domainIDOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(iceServerAddressOption)) { + // parse the IP and port combination for this target + QString hostnamePortString = parser.value(iceServerAddressOption); + + _iceServerAddr = hostnamePortString.left(hostnamePortString.indexOf(':')); + _iceServerPort = (quint16) hostnamePortString.mid(hostnamePortString.indexOf(':') + 1).toUInt(); + if (_iceServerPort == 0) { + _iceServerPort = ICE_SERVER_DEFAULT_PORT; + } + + if (_iceServerAddr.isEmpty()) { + qCritical() << "Could not parse an IP address and port combination from" << hostnamePortString; + QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); + } + } + + if (parser.isSet(domainIDOption)) { + _overridingDomainID = QUuid(parser.value(domainIDOption)); + _overRideDomainID = true; + qDebug() << "domain-server ID is" << _overridingDomainID; + } +} + DomainServer::~DomainServer() { // destroy the LimitedNodeList before the DomainServer QCoreApplication is down DependencyManager::destroy(); @@ -295,7 +339,7 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) { auto domainObject = jsonObject[DATA_KEY].toObject()[DOMAIN_KEY].toObject(); if (!domainObject.isEmpty()) { - auto id = domainObject[ID_KEY].toString(); + auto id = _overRideDomainID ? _overridingDomainID.toString() : domainObject[ID_KEY].toString(); auto name = domainObject[NAME_KEY].toString(); auto key = domainObject[KEY_KEY].toString(); @@ -403,26 +447,33 @@ void DomainServer::setupNodeListAndAssignments() { quint16 localHttpsPort = DOMAIN_SERVER_HTTPS_PORT; nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_HTTPS_PORT_SMEM_KEY, this, localHttpsPort); - // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain - const QVariant* idValueVariant = valueForKeyPath(settingsMap, METAVERSE_DOMAIN_ID_KEY_PATH); - if (idValueVariant) { - nodeList->setSessionUUID(idValueVariant->toString()); + bool isMetaverseDomain = false; + if (_overRideDomainID) { + nodeList->setSessionUUID(_overridingDomainID); + isMetaverseDomain = true; // assume metaverse domain + } else { + const QVariant* idValueVariant = valueForKeyPath(settingsMap, METAVERSE_DOMAIN_ID_KEY_PATH); + if (idValueVariant) { + nodeList->setSessionUUID(idValueVariant->toString()); + isMetaverseDomain = true; // if we have an ID, we'll assume we're a metaverse domain + } else { + nodeList->setSessionUUID(QUuid::createUuid()); // Use random UUID + } + } - // if we have an ID, we'll assume we're a metaverse domain - // now see if we think we're a temp domain (we have an API key) or a full domain + if (isMetaverseDomain) { + // see if we think we're a temp domain (we have an API key) or a full domain const auto& temporaryDomainKey = DependencyManager::get()->getTemporaryDomainKey(getID()); if (temporaryDomainKey.isEmpty()) { _type = MetaverseDomain; } else { _type = MetaverseTemporaryDomain; } - - } else { - nodeList->setSessionUUID(QUuid::createUuid()); // Use random UUID } + connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); @@ -536,7 +587,7 @@ void DomainServer::setupAutomaticNetworking() { } else { qDebug() << "Cannot enable domain-server automatic networking without a domain ID." << "Please add an ID to your config file or via the web interface."; - + return; } } @@ -594,12 +645,11 @@ void DomainServer::setupICEHeartbeatForFullNetworking() { void DomainServer::updateICEServerAddresses() { if (_iceAddressLookupID == -1) { - _iceAddressLookupID = QHostInfo::lookupHost(ICE_SERVER_DEFAULT_HOSTNAME, this, SLOT(handleICEHostInfo(QHostInfo))); + _iceAddressLookupID = QHostInfo::lookupHost(_iceServerAddr, this, SLOT(handleICEHostInfo(QHostInfo))); } } void DomainServer::parseAssignmentConfigs(QSet& excludedTypes) { - // check for configs from the command line, these take precedence const QString ASSIGNMENT_CONFIG_REGEX_STRING = "config-([\\d]+)"; QRegExp assignmentConfigRegex(ASSIGNMENT_CONFIG_REGEX_STRING); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index e30f4515cc..de08c15468 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -105,6 +105,7 @@ signals: private: const QUuid& getID(); + void parseCommandLine(); void setupNodeListAndAssignments(); bool optionallySetupOAuth(); @@ -205,6 +206,11 @@ private: friend class DomainGatekeeper; friend class DomainMetadata; + + QString _iceServerAddr; + int _iceServerPort; + bool _overRideDomainID { false }; // should we override the domain-id from settings? + QUuid _overridingDomainID { QUuid() }; // what should we override it with? }; From eb6d329dfa6159896feb586f798f90e3016adf19 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 19 Sep 2016 15:30:55 -0700 Subject: [PATCH 10/14] 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 From 8108557e10f271124f825a294af28d4816460bf8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 19 Sep 2016 15:37:50 -0700 Subject: [PATCH 11/14] whitespace --- domain-server/src/DomainServer.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 654fe500c6..5965b8aa5c 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -473,7 +473,6 @@ void DomainServer::setupNodeListAndAssignments() { } } - connect(nodeList.data(), &LimitedNodeList::nodeAdded, this, &DomainServer::nodeAdded); connect(nodeList.data(), &LimitedNodeList::nodeKilled, this, &DomainServer::nodeKilled); @@ -587,7 +586,6 @@ void DomainServer::setupAutomaticNetworking() { } else { qDebug() << "Cannot enable domain-server automatic networking without a domain ID." << "Please add an ID to your config file or via the web interface."; - return; } } From ba8aa5b50cc1a01b31c1c62663c79cd5295cee58 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 19 Sep 2016 16:38:34 -0700 Subject: [PATCH 12/14] fix camelcase --- domain-server/src/DomainServer.cpp | 6 +++--- domain-server/src/DomainServer.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 6a30604abd..4489f0d607 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -198,7 +198,7 @@ void DomainServer::parseCommandLine() { if (parser.isSet(domainIDOption)) { _overridingDomainID = QUuid(parser.value(domainIDOption)); - _overRideDomainID = true; + _overrideDomainID = true; qDebug() << "domain-server ID is" << _overridingDomainID; } } @@ -351,7 +351,7 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) { auto domainObject = jsonObject[DATA_KEY].toObject()[DOMAIN_KEY].toObject(); if (!domainObject.isEmpty()) { - auto id = _overRideDomainID ? _overridingDomainID.toString() : domainObject[ID_KEY].toString(); + auto id = _overrideDomainID ? _overridingDomainID.toString() : domainObject[ID_KEY].toString(); auto name = domainObject[NAME_KEY].toString(); auto key = domainObject[KEY_KEY].toString(); @@ -462,7 +462,7 @@ void DomainServer::setupNodeListAndAssignments() { // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain bool isMetaverseDomain = false; - if (_overRideDomainID) { + if (_overrideDomainID) { nodeList->setSessionUUID(_overridingDomainID); isMetaverseDomain = true; // assume metaverse domain } else { diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index de08c15468..066f2be0d1 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -209,7 +209,7 @@ private: QString _iceServerAddr; int _iceServerPort; - bool _overRideDomainID { false }; // should we override the domain-id from settings? + bool _overrideDomainID { false }; // should we override the domain-id from settings? QUuid _overridingDomainID { QUuid() }; // what should we override it with? }; From b9ea93de57c81e16960d009ccb6e757a99c0e265 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 21 Sep 2016 10:08:02 -0700 Subject: [PATCH 13/14] use qWarning rather than qCritical because qCritical may exit --- domain-server/src/DomainServer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 4489f0d607..99bbffa750 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -175,7 +175,7 @@ void DomainServer::parseCommandLine() { parser.addOption(domainIDOption); if (!parser.parse(QCoreApplication::arguments())) { - qCritical() << parser.errorText() << endl; + qWarning() << parser.errorText() << endl; parser.showHelp(); Q_UNREACHABLE(); } @@ -191,7 +191,7 @@ void DomainServer::parseCommandLine() { } if (_iceServerAddr.isEmpty()) { - qCritical() << "Could not parse an IP address and port combination from" << hostnamePortString; + qWarning() << "Could not parse an IP address and port combination from" << hostnamePortString; QMetaObject::invokeMethod(this, "quit", Qt::QueuedConnection); } } @@ -210,7 +210,7 @@ DomainServer::~DomainServer() { void DomainServer::queuedQuit(QString quitMessage, int exitCode) { if (!quitMessage.isEmpty()) { - qCritical() << qPrintable(quitMessage); + qWarning() << qPrintable(quitMessage); } QCoreApplication::exit(exitCode); From 0192f72a110446cf184c7a65445920da906c85cc Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 22 Sep 2016 10:34:00 -0700 Subject: [PATCH 14/14] use named constant rather than 7337 --- tools/ice-client/src/ICEClientApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ice-client/src/ICEClientApp.cpp b/tools/ice-client/src/ICEClientApp.cpp index 1a251a45c2..992014ad7d 100644 --- a/tools/ice-client/src/ICEClientApp.cpp +++ b/tools/ice-client/src/ICEClientApp.cpp @@ -86,7 +86,7 @@ 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; + port = ICE_SERVER_DEFAULT_PORT; } if (address.isNull()) {