13 #ifndef hifi_LimitedNodeList_h
14 #define hifi_LimitedNodeList_h
21 #include <unordered_map>
27 #include <QtCore/QElapsedTimer>
28 #include <QtCore/QPointer>
29 #include <QtCore/QReadWriteLock>
30 #include <QtCore/QSet>
31 #include <QtCore/QSharedMemory>
32 #include <QtCore/QSharedPointer>
33 #include <QtNetwork/QUdpSocket>
34 #include <QtNetwork/QHostAddress>
36 #include <TBBHelpers.h>
38 #include <DependencyManager.h>
39 #include <SharedUtil.h>
41 #include "NetworkingConstants.h"
44 #include "NLPacketList.h"
45 #include "PacketReceiver.h"
46 #include "ReceivedMessage.h"
47 #include "udt/ControlPacket.h"
48 #include "udt/PacketHeaders.h"
49 #include "udt/Socket.h"
50 #include "UUIDHasher.h"
52 const int INVALID_PORT = -1;
54 const quint64 NODE_SILENCE_THRESHOLD_MSECS = 10 * 1000;
56 static const size_t DEFAULT_MAX_CONNECTION_RATE { std::numeric_limits<size_t>::max() };
58 const char DEFAULT_ASSIGNMENT_SERVER_HOSTNAME[] =
"localhost";
60 const char STUN_SERVER_HOSTNAME[] =
"stun1.l.google.com";
61 const unsigned short STUN_SERVER_PORT = NetworkingConstants::STUN_SERVER_DEFAULT_PORT;
63 const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY =
"domain-server.local-port";
64 const QString DOMAIN_SERVER_LOCAL_HTTP_PORT_SMEM_KEY =
"domain-server.local-http-port";
65 const QString DOMAIN_SERVER_LOCAL_HTTPS_PORT_SMEM_KEY =
"domain-server.local-https-port";
67 const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::LocalHost;
69 const QString USERNAME_UUID_REPLACEMENT_STATS_KEY =
"$username";
71 using ConnectionID = int64_t;
72 const ConnectionID NULL_CONNECTION_ID { -1 };
73 const ConnectionID INITIAL_CONNECTION_ID { 0 };
75 typedef std::pair<QUuid, SharedNodePointer> UUIDNodePair;
76 typedef tbb::concurrent_unordered_map<QUuid, SharedNodePointer, UUIDHasher> NodeHash;
78 typedef quint8 PingType_t;
80 const PingType_t Agnostic = 0;
81 const PingType_t Local = 1;
82 const PingType_t Public = 2;
83 const PingType_t Symmetric = 3;
86 class LimitedNodeList :
public QObject,
public Dependency {
95 SetPublicSocketFromSTUN,
99 ReceiveDSPeerInformation,
109 ReceiveFirstAudioPacket
112 Q_ENUM(ConnectionStep);
114 enum ConnectReason : quint32 {
116 SilentDomainDisconnect,
119 Q_ENUM(ConnectReason);
121 QUuid getSessionUUID()
const;
122 void setSessionUUID(
const QUuid& sessionUUID);
123 Node::LocalID getSessionLocalID()
const;
124 void setSessionLocalID(Node::LocalID sessionLocalID);
126 void setPermissions(
const NodePermissions& newPermissions);
127 bool isAllowedEditor()
const {
return _permissions.can(NodePermissions::Permission::canAdjustLocks); }
128 bool getThisNodeCanRez()
const {
return _permissions.can(NodePermissions::Permission::canRezPermanentEntities); }
129 bool getThisNodeCanRezTmp()
const {
return _permissions.can(NodePermissions::Permission::canRezTemporaryEntities); }
130 bool getThisNodeCanWriteAssets()
const {
return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); }
131 bool getThisNodeCanKick()
const {
return _permissions.can(NodePermissions::Permission::canKick); }
132 bool getThisNodeCanReplaceContent()
const {
return _permissions.can(NodePermissions::Permission::canReplaceDomainContent); }
133 bool getThisNodeCanGetAndSetPrivateUserData()
const {
return _permissions.can(NodePermissions::Permission::canGetAndSetPrivateUserData); }
134 bool getThisNodeCanRezAvatarEntities()
const {
return _permissions.can(NodePermissions::Permission::canRezAvatarEntities); }
135 bool getThisNodeCanViewAssetURLs()
const {
return _permissions.can(NodePermissions::Permission::canViewAssetURLs); }
137 quint16 getSocketLocalPort(
SocketType socketType)
const {
return _nodeSocket.localPort(socketType); }
138 Q_INVOKABLE
void setSocketLocalPort(
SocketType socketType, quint16 socketLocalPort);
140 QUdpSocket& getDTLSSocket();
141 #if defined(WEBRTC_DATA_CHANNELS)
146 PacketReceiver& getPacketReceiver() {
return *_packetReceiver; }
148 virtual bool isDomainServer()
const {
return true; }
149 virtual QUuid getDomainUUID()
const { assert(
false);
return QUuid(); }
150 virtual Node::LocalID getDomainLocalID()
const { assert(
false);
return Node::NULL_LOCAL_ID; }
151 virtual SockAddr getDomainSockAddr()
const { assert(
false);
return SockAddr(); }
155 qint64 sendUnreliablePacket(
const NLPacket& packet,
const Node& destinationNode);
156 qint64 sendUnreliablePacket(
const NLPacket& packet,
const SockAddr& sockAddr, HMACAuth* hmacAuth =
nullptr);
159 qint64 sendPacket(std::unique_ptr<NLPacket> packet,
const Node& destinationNode);
160 qint64 sendPacket(std::unique_ptr<NLPacket> packet,
const SockAddr& sockAddr, HMACAuth* hmacAuth =
nullptr);
164 qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList,
const Node& destinationNode);
165 qint64 sendUnreliableUnorderedPacketList(NLPacketList& packetList,
const SockAddr& sockAddr,
166 HMACAuth* hmacAuth =
nullptr);
170 qint64 sendPacketList(std::unique_ptr<NLPacketList> packetList,
const SockAddr& sockAddr);
171 qint64 sendPacketList(std::unique_ptr<NLPacketList> packetList,
const Node& destinationNode);
173 std::function<void(Node*)> linkedDataCreateCallback;
175 size_t size()
const { QReadLocker readLock(&_nodeMutex);
return _nodeHash.size(); }
177 SharedNodePointer nodeWithUUID(
const QUuid& nodeUUID);
178 SharedNodePointer nodeWithLocalID(Node::LocalID localID)
const;
180 SharedNodePointer addOrUpdateNode(
const QUuid& uuid,
NodeType_t nodeType,
181 const SockAddr& publicSocket,
const SockAddr& localSocket,
182 Node::LocalID localID = Node::NULL_LOCAL_ID,
bool isReplicated =
false,
183 bool isUpstream =
false,
const QUuid& connectionSecret = QUuid(),
184 const NodePermissions& permissions = DEFAULT_AGENT_PERMISSIONS);
186 static bool parseSTUNResponse(udt::BasePacket* packet, QHostAddress& newPublicAddress, uint16_t& newPublicPort);
187 bool hasCompletedInitialSTUN()
const {
return _hasCompletedInitialSTUN; }
189 const SockAddr& getLocalSockAddr()
const {
return _localSockAddr; }
190 const SockAddr& getPublicSockAddr()
const {
return _publicSockAddr; }
191 const SockAddr& getSTUNSockAddr()
const {
return _stunSockAddr; }
193 void processKillNode(ReceivedMessage& message);
195 int updateNodeWithDataFromPacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer matchingNode);
196 NodeData* getOrCreateLinkedData(SharedNodePointer node);
198 unsigned int broadcastToNodes(std::unique_ptr<NLPacket> packet,
const NodeSet& destinationNodeTypes);
199 SharedNodePointer soloNodeOfType(
NodeType_t nodeType);
201 std::unique_ptr<NLPacket> constructPingPacket(
const QUuid& nodeId, PingType_t pingType = PingType::Agnostic);
202 std::unique_ptr<NLPacket> constructPingReplyPacket(ReceivedMessage& message);
204 static std::unique_ptr<NLPacket> constructICEPingPacket(PingType_t pingType,
const QUuid& iceID);
205 static std::unique_ptr<NLPacket> constructICEPingReplyPacket(ReceivedMessage& message,
const QUuid& iceID);
207 void sendPeerQueryToIceServer(
const SockAddr& iceServerSockAddr,
const QUuid& clientID,
const QUuid& peerID);
209 SharedNodePointer findNodeWithAddr(
const SockAddr& addr);
211 using value_type = SharedNodePointer;
212 using const_iterator = std::vector<value_type>::const_iterator;
218 template<
typename NestedNodeLambda>
219 void nestedEach(NestedNodeLambda functor,
220 int* lockWaitOut =
nullptr,
221 int* nodeTransformOut =
nullptr,
222 int* functorOut =
nullptr) {
223 quint64 start, endTransform, endFunctor;
225 start = usecTimestampNow();
226 std::vector<SharedNodePointer> nodes;
228 QReadLocker readLock(&_nodeMutex);
229 auto endLock = usecTimestampNow();
231 *lockWaitOut = (endLock - start);
237 nodes.reserve(_nodeHash.size());
238 std::transform(_nodeHash.cbegin(), _nodeHash.cend(), std::back_inserter(nodes), [&](
const NodeHash::value_type& it) {
242 endTransform = usecTimestampNow();
243 if (nodeTransformOut) {
244 *nodeTransformOut = (endTransform - endLock);
248 functor(nodes.cbegin(), nodes.cend());
249 endFunctor = usecTimestampNow();
251 *functorOut = (endFunctor - endTransform);
255 template<
typename NodeLambda>
256 void eachNode(NodeLambda functor) {
257 QReadLocker readLock(&_nodeMutex);
259 for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) {
264 template<
typename PredLambda,
typename NodeLambda>
265 void eachMatchingNode(PredLambda predicate, NodeLambda functor) {
266 QReadLocker readLock(&_nodeMutex);
268 for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) {
269 if (predicate(it->second)) {
275 template<
typename BreakableNodeLambda>
276 void eachNodeBreakable(BreakableNodeLambda functor) {
277 QReadLocker readLock(&_nodeMutex);
279 for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) {
280 if (!functor(it->second)) {
286 template<
typename PredLambda>
287 SharedNodePointer nodeMatchingPredicate(
const PredLambda predicate) {
288 QReadLocker readLock(&_nodeMutex);
290 for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) {
291 if (predicate(it->second)) {
296 return SharedNodePointer();
302 template<
typename NodeLambda>
303 void unsafeEachNode(NodeLambda functor) {
304 for (NodeHash::const_iterator it = _nodeHash.cbegin(); it != _nodeHash.cend(); ++it) {
309 void putLocalPortIntoSharedMemory(
const QString key, QObject* parent, quint16 localPort);
310 bool getLocalServerPortFromSharedMemory(
const QString key, quint16& localPort);
312 const QMap<quint64, ConnectionStep> getLastConnectionTimes()
const
313 { QReadLocker readLock(&_connectionTimeLock);
return _lastConnectionTimes; }
314 void flagTimeForConnectionStep(ConnectionStep connectionStep);
316 udt::Socket::StatsVector sampleStatsForAllConnections() {
return _nodeSocket.sampleStatsForAllConnections(); }
318 void setConnectionMaxBandwidth(
int maxBandwidth) { _nodeSocket.setConnectionMaxBandwidth(maxBandwidth); }
320 void setPacketFilterOperator(udt::PacketFilterOperator filterOperator) { _nodeSocket.setPacketFilterOperator(filterOperator); }
321 bool packetVersionMatch(
const udt::Packet& packet);
323 bool isPacketVerifiedWithSource(
const udt::Packet& packet, Node* sourceNode =
nullptr);
324 bool isPacketVerified(
const udt::Packet& packet) {
return isPacketVerifiedWithSource(packet); }
325 void setAuthenticatePackets(
bool useAuthentication) { _useAuthentication = useAuthentication; }
326 bool getAuthenticatePackets()
const {
return _useAuthentication; }
328 void setFlagTimeForConnectionStep(
bool flag) { _flagTimeForConnectionStep = flag; }
329 bool isFlagTimeForConnectionStep() {
return _flagTimeForConnectionStep; }
331 static void makeSTUNRequestPacket(
char* stunRequestPacket);
333 #if (PR_BUILD || DEV_BUILD)
334 void sendFakedHandshakeRequestToNode(SharedNodePointer node);
337 size_t getMaxConnectionRate()
const {
return _maxConnectionRate; }
338 void setMaxConnectionRate(
size_t rate) { _maxConnectionRate = rate; }
340 int getInboundPPS()
const {
return _inboundPPS; }
341 int getOutboundPPS()
const {
return _outboundPPS; }
342 float getInboundKbps()
const {
return _inboundKbps; }
343 float getOutboundKbps()
const {
return _outboundKbps; }
345 void setDropOutgoingNodeTraffic(
bool squelchOutgoingNodeTraffic) { _dropOutgoingNodeTraffic = squelchOutgoingNodeTraffic; }
347 const std::set<NodeType_t> SOLO_NODE_TYPES = {
348 NodeType::AvatarMixer,
349 NodeType::AudioMixer,
350 NodeType::AssetServer,
351 NodeType::EntityServer,
352 NodeType::MessagesMixer,
353 NodeType::EntityScriptServer
357 void reset(QString reason);
358 void eraseAllNodes(QString reason);
360 void removeSilentNodes();
362 void updateLocalSocket();
364 void startSTUNPublicSocketUpdate();
365 virtual void sendSTUNRequest();
367 bool killNodeWithUUID(
const QUuid& nodeUUID, ConnectionID newConnectionID = NULL_CONNECTION_ID);
368 void noteAwakening() { _connectReason = Awake; }
371 void sampleConnectionStats();
375 void packetVersionMismatch(PacketType type,
const SockAddr& senderSockAddr,
const QUuid& senderUUID);
377 void uuidChanged(
const QUuid& ownerUUID,
const QUuid& oldUUID);
378 void nodeAdded(SharedNodePointer);
379 void nodeSocketUpdated(SharedNodePointer);
380 void nodeKilled(SharedNodePointer);
381 void nodeActivated(SharedNodePointer);
383 void clientConnectionToNodeReset(SharedNodePointer);
385 void localSockAddrChanged(
const SockAddr& localSockAddr);
386 void publicSockAddrChanged(
const SockAddr& publicSockAddr);
388 void isAllowedEditorChanged(
bool isAllowedEditor);
389 void canRezChanged(
bool canRez);
390 void canRezTmpChanged(
bool canRezTmp);
391 void canWriteAssetsChanged(
bool canWriteAssets);
392 void canKickChanged(
bool canKick);
393 void canReplaceContentChanged(
bool canReplaceContent);
394 void canGetAndSetPrivateUserDataChanged(
bool canGetAndSetPrivateUserData);
395 void canRezAvatarEntitiesChanged(
bool canRezAvatarEntities);
396 void canViewAssetURLsChanged(
bool canViewAssetURLs);
399 void connectedForLocalSocketTest();
400 void errorTestingLocalSocket();
402 void clientConnectionToSockAddrReset(
const SockAddr& sockAddr);
404 void processDelayedAdds();
410 SockAddr publicSocket;
411 SockAddr localSocket;
412 NodePermissions permissions;
414 Node::LocalID sessionLocalID;
415 QUuid connectionSecretUUID;
418 LimitedNodeList(
int socketListenPort = INVALID_PORT,
int dtlsListenPort = INVALID_PORT);
419 LimitedNodeList(LimitedNodeList
const&) =
delete;
420 void operator=(LimitedNodeList
const&) =
delete;
422 qint64 sendPacket(std::unique_ptr<NLPacket> packet,
const Node& destinationNode,
423 const SockAddr& overridenSockAddr);
425 void setLocalSocket(
const SockAddr& sockAddr);
427 bool packetSourceAndHashMatchAndTrackBandwidth(
const udt::Packet& packet, Node* sourceNode =
nullptr);
428 void processSTUNResponse(std::unique_ptr<udt::BasePacket> packet);
430 void handleNodeKill(
const SharedNodePointer& node, ConnectionID newConnectionID = NULL_CONNECTION_ID);
432 void stopInitialSTUNUpdate(
bool success);
434 void sendPacketToIceServer(PacketType packetType,
const SockAddr& iceServerSockAddr,
const QUuid& clientID,
435 const QUuid& peerRequestID = QUuid());
437 bool sockAddrBelongsToNode(
const SockAddr& sockAddr);
439 void addNewNode(NewNodeInfo info);
440 void delayNodeAdd(NewNodeInfo info);
441 void removeDelayedAdd(QUuid nodeUUID);
442 bool isDelayedNode(QUuid nodeUUID);
445 mutable QReadWriteLock _nodeMutex { QReadWriteLock::Recursive };
446 udt::Socket _nodeSocket;
447 QUdpSocket* _dtlsSocket {
nullptr };
448 SockAddr _localSockAddr;
449 SockAddr _publicSockAddr;
450 SockAddr _stunSockAddr {
SocketType::UDP, STUN_SERVER_HOSTNAME, STUN_SERVER_PORT };
451 bool _hasTCPCheckedLocalSocket {
false };
452 bool _useAuthentication {
true };
454 PacketReceiver* _packetReceiver;
456 NodePermissions _permissions;
458 QPointer<QTimer> _initialSTUNTimer;
460 int _numInitialSTUNRequests = 0;
461 bool _hasCompletedInitialSTUN =
false;
462 quint64 _firstSTUNTime = 0;
463 quint64 _publicSocketUpdateTime = 0;
465 mutable QReadWriteLock _connectionTimeLock { };
466 QMap<quint64, ConnectionStep> _lastConnectionTimes;
467 bool _areConnectionTimesComplete =
false;
469 template<
typename IteratorLambda>
470 void eachNodeHashIterator(IteratorLambda functor) {
471 QWriteLocker writeLock(&_nodeMutex);
472 NodeHash::iterator it = _nodeHash.begin();
474 while (it != _nodeHash.end()) {
479 std::unordered_map<QUuid, ConnectionID> _connectionIDs;
480 quint64 _nodeConnectTimestamp{ 0 };
481 quint64 _nodeDisconnectTimestamp{ 0 };
482 ConnectReason _connectReason { Connect };
485 void flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp);
486 void possiblyTimeoutSTUNAddressLookup();
487 void addSTUNHandlerToUnfiltered();
490 void fillPacketHeader(
const NLPacket& packet, HMACAuth* hmacAuth =
nullptr);
492 mutable QReadWriteLock _sessionUUIDLock;
494 using LocalIDMapping = tbb::concurrent_unordered_map<Node::LocalID, SharedNodePointer>;
495 LocalIDMapping _localIDMap;
496 Node::LocalID _sessionLocalID { 0 };
497 bool _flagTimeForConnectionStep {
false };
499 size_t _maxConnectionRate { DEFAULT_MAX_CONNECTION_RATE };
500 size_t _nodesAddedInCurrentTimeSlice { 0 };
501 std::vector<NewNodeInfo> _delayedNodeAdds;
503 int _inboundPPS { 0 };
504 int _outboundPPS { 0 };
505 float _inboundKbps { 0.0f };
506 float _outboundKbps { 0.0f };
508 bool _dropOutgoingNodeTraffic {
false };
510 quint64 _sendErrorStatsTime { (quint64)0 };
511 static const quint64 ERROR_STATS_PERIOD_US { 1 * USECS_PER_SECOND };
quint8 NodeType_t
An 8-bit value identifying the type of a node - domain server, audio mixer, etc.
Definition: NodeType.h:22
Provides a QUdpSocket-style interface for using WebRTCDataChannels.
Definition: WebRTCSocket.h:31
SocketType
The types of network socket.
Definition: SocketType.h:22