mirror of
https://github.com/overte-org/overte.git
synced 2025-08-07 19:30:41 +02:00
continued STUN requests for keepalive, propagate socket changes
This commit is contained in:
parent
8d8278daef
commit
32680bbaad
4 changed files with 173 additions and 128 deletions
|
@ -33,17 +33,8 @@ Node::Node(const QUuid& uuid, char type, sockaddr* publicSocket, sockaddr* local
|
|||
_linkedData(NULL),
|
||||
_isAlive(true)
|
||||
{
|
||||
if (publicSocket) {
|
||||
_publicSocket = new sockaddr(*publicSocket);
|
||||
} else {
|
||||
_publicSocket = NULL;
|
||||
}
|
||||
|
||||
if (localSocket) {
|
||||
_localSocket = new sockaddr(*localSocket);
|
||||
} else {
|
||||
_localSocket = NULL;
|
||||
}
|
||||
setPublicSocket(publicSocket);
|
||||
setLocalSocket(localSocket);
|
||||
|
||||
pthread_mutex_init(&_mutex, 0);
|
||||
}
|
||||
|
@ -95,6 +86,32 @@ const char* Node::getTypeName() const {
|
|||
}
|
||||
}
|
||||
|
||||
void Node::setPublicSocket(sockaddr* publicSocket) {
|
||||
if (_activeSocket == _publicSocket) {
|
||||
// if the active socket was the public socket then reset it to NULL
|
||||
_activeSocket = NULL;
|
||||
}
|
||||
|
||||
if (publicSocket) {
|
||||
_publicSocket = new sockaddr(*publicSocket);
|
||||
} else {
|
||||
_publicSocket = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Node::setLocalSocket(sockaddr* localSocket) {
|
||||
if (_activeSocket == _localSocket) {
|
||||
// if the active socket was the local socket then reset it to NULL
|
||||
_activeSocket = NULL;
|
||||
}
|
||||
|
||||
if (localSocket) {
|
||||
_localSocket = new sockaddr(*localSocket);
|
||||
} else {
|
||||
_localSocket = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Node::activateLocalSocket() {
|
||||
qDebug() << "Activating local socket for node" << *this << "\n";
|
||||
_activeSocket = _localSocket;
|
||||
|
|
|
@ -47,9 +47,9 @@ public:
|
|||
void setLastHeardMicrostamp(uint64_t lastHeardMicrostamp) { _lastHeardMicrostamp = lastHeardMicrostamp; }
|
||||
|
||||
sockaddr* getPublicSocket() const { return _publicSocket; }
|
||||
void setPublicSocket(sockaddr* publicSocket) { _publicSocket = publicSocket; }
|
||||
void setPublicSocket(sockaddr* publicSocket);
|
||||
sockaddr* getLocalSocket() const { return _localSocket; }
|
||||
void setLocalSocket(sockaddr* localSocket) { _localSocket = localSocket; }
|
||||
void setLocalSocket(sockaddr* localSocket);
|
||||
|
||||
sockaddr* getActiveSocket() const { return _activeSocket; }
|
||||
|
||||
|
|
|
@ -71,11 +71,10 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
|
|||
_ownerUUID(QUuid::createUuid()),
|
||||
_numNoReplyDomainCheckIns(0),
|
||||
_assignmentServerSocket(NULL),
|
||||
_checkInPacket(NULL),
|
||||
_numBytesCheckInPacket(0),
|
||||
_publicAddress(),
|
||||
_publicPort(0),
|
||||
_shouldUseDomainServerAsSTUN(0)
|
||||
_hasCompletedInitialSTUNFailure(false),
|
||||
_stunRequestsSinceSuccess(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -288,11 +287,6 @@ void NodeList::reset() {
|
|||
clear();
|
||||
_numNoReplyDomainCheckIns = 0;
|
||||
|
||||
delete[] _checkInPacket;
|
||||
_checkInPacket = NULL;
|
||||
|
||||
_numBytesCheckInPacket = 0;
|
||||
|
||||
delete _nodeTypesOfInterest;
|
||||
_nodeTypesOfInterest = NULL;
|
||||
|
||||
|
@ -316,9 +310,6 @@ void NodeList::sendSTUNRequest() {
|
|||
const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
|
||||
const unsigned short STUN_SERVER_PORT = 3478;
|
||||
|
||||
static int failedStunRequests = 0;
|
||||
|
||||
if (failedStunRequests < NUM_STUN_REQUESTS_BEFORE_FALLBACK) {
|
||||
unsigned char stunRequestPacket[NUM_BYTES_STUN_HEADER];
|
||||
|
||||
int packetIndex = 0;
|
||||
|
@ -351,7 +342,9 @@ void NodeList::sendSTUNRequest() {
|
|||
if (stunInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
QString stunIPAddress = stunInfo.addresses()[i].toString();
|
||||
|
||||
qDebug("Sending a stun request to %s\n", stunIPAddress.toLocal8Bit().constData());
|
||||
if (!_hasCompletedInitialSTUNFailure) {
|
||||
qDebug("Sending intial stun request to %s\n", stunIPAddress.toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
_nodeSocket.send(stunIPAddress.toLocal8Bit().constData(),
|
||||
STUN_SERVER_PORT,
|
||||
|
@ -362,16 +355,22 @@ void NodeList::sendSTUNRequest() {
|
|||
}
|
||||
}
|
||||
|
||||
failedStunRequests++;
|
||||
|
||||
return;
|
||||
}
|
||||
_stunRequestsSinceSuccess++;
|
||||
|
||||
if (_stunRequestsSinceSuccess >= NUM_STUN_REQUESTS_BEFORE_FALLBACK) {
|
||||
if (!_hasCompletedInitialSTUNFailure) {
|
||||
// if we're here this was the last failed STUN request
|
||||
// use our DS as our stun server
|
||||
qDebug("Failed to lookup public address via STUN server at %s:%hu. Using DS for STUN.\n",
|
||||
STUN_SERVER_HOSTNAME, STUN_SERVER_PORT);
|
||||
_shouldUseDomainServerAsSTUN = true;
|
||||
|
||||
_hasCompletedInitialSTUNFailure = true;
|
||||
}
|
||||
|
||||
// reset the public address and port
|
||||
_publicAddress = QHostAddress::Null;
|
||||
_publicPort = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) {
|
||||
|
@ -395,6 +394,9 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes)
|
|||
const int NUM_BYTES_FAMILY_ALIGN = 1;
|
||||
const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8;
|
||||
|
||||
// reset the number of failed STUN requests since last success
|
||||
_stunRequestsSinceSuccess = 0;
|
||||
|
||||
int byteIndex = attributeStartIndex + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN;
|
||||
|
||||
uint8_t addressFamily = 0;
|
||||
|
@ -416,12 +418,20 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes)
|
|||
memcpy(&xorMappedAddress, packetData + byteIndex, sizeof(xorMappedAddress));
|
||||
|
||||
uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER);
|
||||
_publicAddress = QHostAddress(stunAddress);
|
||||
|
||||
qDebug("Public socket received from STUN server is %s:%hu\n",
|
||||
QHostAddress newPublicAddress = QHostAddress(stunAddress);
|
||||
|
||||
if (newPublicAddress != _publicAddress) {
|
||||
_publicAddress = newPublicAddress;
|
||||
|
||||
qDebug("New public socket received from STUN server is %s:%hu\n",
|
||||
_publicAddress.toString().toLocal8Bit().constData(),
|
||||
_publicPort);
|
||||
|
||||
}
|
||||
|
||||
_hasCompletedInitialSTUNFailure = true;
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -469,13 +479,12 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
printedDomainServerIP = true;
|
||||
}
|
||||
|
||||
if (_publicAddress.isNull() && !_shouldUseDomainServerAsSTUN) {
|
||||
if (_publicAddress.isNull() && !_hasCompletedInitialSTUNFailure) {
|
||||
// we don't know our public socket and we need to send it to the domain server
|
||||
// send a STUN request to figure it out
|
||||
sendSTUNRequest();
|
||||
} else {
|
||||
// construct the DS check in packet if we need to
|
||||
if (!_checkInPacket) {
|
||||
int numBytesNodesOfInterest = _nodeTypesOfInterest ? strlen((char*) _nodeTypesOfInterest) : 0;
|
||||
|
||||
const int IP_ADDRESS_BYTES = 4;
|
||||
|
@ -485,8 +494,8 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
NUM_BYTES_RFC4122_UUID + (2 * (sizeof(uint16_t) + IP_ADDRESS_BYTES)) +
|
||||
numBytesNodesOfInterest + sizeof(unsigned char);
|
||||
|
||||
_checkInPacket = new unsigned char[numPacketBytes];
|
||||
unsigned char* packetPosition = _checkInPacket;
|
||||
unsigned char* checkInPacket = new unsigned char[numPacketBytes];
|
||||
unsigned char* packetPosition = checkInPacket;
|
||||
|
||||
PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES)))
|
||||
? PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY
|
||||
|
@ -502,11 +511,11 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
packetPosition += rfcOwnerUUID.size();
|
||||
|
||||
// pack our public address to send to domain-server
|
||||
packetPosition += packSocket(_checkInPacket + (packetPosition - _checkInPacket),
|
||||
packetPosition += packSocket(checkInPacket + (packetPosition - checkInPacket),
|
||||
htonl(_publicAddress.toIPv4Address()), htons(_publicPort));
|
||||
|
||||
// pack our local address to send to domain-server
|
||||
packetPosition += packSocket(_checkInPacket + (packetPosition - _checkInPacket),
|
||||
packetPosition += packSocket(checkInPacket + (packetPosition - checkInPacket),
|
||||
getLocalAddress(),
|
||||
htons(_nodeSocket.getListeningPort()));
|
||||
|
||||
|
@ -521,10 +530,15 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
packetPosition += numBytesNodesOfInterest;
|
||||
}
|
||||
|
||||
_numBytesCheckInPacket = packetPosition - _checkInPacket;
|
||||
}
|
||||
_nodeSocket.send(_domainIP.toString().toLocal8Bit().constData(), _domainPort, checkInPacket, packetPosition - checkInPacket);
|
||||
|
||||
_nodeSocket.send(_domainIP.toString().toLocal8Bit().constData(), _domainPort, _checkInPacket, _numBytesCheckInPacket);
|
||||
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
|
||||
static unsigned int numDomainCheckins = 0;
|
||||
|
||||
// send a STUN request every Nth domain server check in so we update our public socket, if required
|
||||
if (numDomainCheckins++ % NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST == 0) {
|
||||
sendSTUNRequest();
|
||||
}
|
||||
|
||||
// increment the count of un-replied check-ins
|
||||
_numNoReplyDomainCheckIns++;
|
||||
|
@ -622,6 +636,8 @@ Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, sockaddr* publ
|
|||
|
||||
return newNode;
|
||||
} else {
|
||||
node->lock();
|
||||
|
||||
if (node->getType() == NODE_TYPE_AUDIO_MIXER ||
|
||||
node->getType() == NODE_TYPE_VOXEL_SERVER) {
|
||||
// until the Audio class also uses our nodeList, we need to update
|
||||
|
@ -629,6 +645,19 @@ Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, sockaddr* publ
|
|||
node->setLastHeardMicrostamp(usecTimestampNow());
|
||||
}
|
||||
|
||||
// check if we need to change this node's public or local sockets
|
||||
if (!socketMatch(publicSocket, node->getPublicSocket())) {
|
||||
node->setPublicSocket(publicSocket);
|
||||
qDebug() << "Public socket change for node" << *node << "\n";
|
||||
}
|
||||
|
||||
if (!socketMatch(localSocket, node->getLocalSocket())) {
|
||||
node->setLocalSocket(localSocket);
|
||||
qDebug() << "Local socket change for node" << *node << "\n";
|
||||
}
|
||||
|
||||
node->unlock();
|
||||
|
||||
// we had this node already, do nothing for now
|
||||
return &*node;
|
||||
}
|
||||
|
|
|
@ -167,11 +167,10 @@ private:
|
|||
pthread_t checkInWithDomainServerThread;
|
||||
int _numNoReplyDomainCheckIns;
|
||||
sockaddr* _assignmentServerSocket;
|
||||
uchar* _checkInPacket;
|
||||
int _numBytesCheckInPacket;
|
||||
QHostAddress _publicAddress;
|
||||
uint16_t _publicPort;
|
||||
bool _shouldUseDomainServerAsSTUN;
|
||||
bool _hasCompletedInitialSTUNFailure;
|
||||
unsigned int _stunRequestsSinceSuccess;
|
||||
|
||||
void activateSocketFromNodeCommunication(sockaddr *nodeAddress);
|
||||
void timePingReply(sockaddr *nodeAddress, unsigned char *packetData);
|
||||
|
|
Loading…
Reference in a new issue