int NodeList::processDomainServerList(const QByteArray& packet) { // this is a packet from the domain server, reset the count of un-replied check-ins _numNoReplyDomainCheckIns = 0; // if this was the first domain-server list from this domain, we've now connected if (!_domainHandler.isConnected()) { _domainHandler.setUUID(uuidFromPacketHeader(packet)); _domainHandler.setIsConnected(true); } int readNodes = 0; // setup variables to read into from QDataStream qint8 nodeType; QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket; HifiSockAddr nodeLocalSocket; QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet)); // pull our owner UUID from the packet, it's always the first thing QUuid newUUID; packetStream >> newUUID; setSessionUUID(newUUID); // pull each node in the packet while(packetStream.device()->pos() < packet.size()) { packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket; // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.getAddress().isNull()) { nodePublicSocket.setAddress(_domainHandler.getIP()); } SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket); packetStream >> connectionUUID; node->setConnectionSecret(connectionUUID); } // ping inactive nodes in conjunction with receipt of list from domain-server // this makes it happen every second and also pings any newly added nodes pingInactiveNodes(); return readNodes; }
void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) { // find the avatar mixer in our node list and update the lastRecvTime from it Node* bulkSendNode = nodeWithAddress(senderAddress); if (bulkSendNode) { bulkSendNode->setLastHeardMicrostamp(usecTimestampNow()); bulkSendNode->recordBytesReceived(numTotalBytes); int numBytesPacketHeader = numBytesForPacketHeader(packetData); unsigned char* startPosition = packetData; unsigned char* currentPosition = startPosition + numBytesPacketHeader; unsigned char packetHolder[numTotalBytes]; // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA); uint16_t nodeID = -1; while ((currentPosition - startPosition) < numTotalBytes) { unpackNodeId(currentPosition, &nodeID); memcpy(packetHolder + numBytesPacketHeader, currentPosition, numTotalBytes - (currentPosition - startPosition)); Node* matchingNode = nodeWithID(nodeID); if (!matchingNode) { // we're missing this node, we need to add it to the list matchingNode = addOrUpdateNode(NULL, NULL, NODE_TYPE_AGENT, nodeID); } currentPosition += updateNodeWithData(matchingNode, packetHolder, numTotalBytes - (currentPosition - startPosition)); } } }
void NodeList::parseNodeFromPacketStream(QDataStream& packetStream) { // setup variables to read into from QDataStream qint8 nodeType; QUuid nodeUUID, connectionUUID; HifiSockAddr nodePublicSocket, nodeLocalSocket; bool isAllowedEditor; bool canRez; packetStream >> nodeType >> nodeUUID >> nodePublicSocket >> nodeLocalSocket >> isAllowedEditor >> canRez; // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.getAddress().isNull()) { nodePublicSocket.setAddress(_domainHandler.getIP()); } packetStream >> connectionUUID; SharedNodePointer node = addOrUpdateNode(nodeUUID, nodeType, nodePublicSocket, nodeLocalSocket, isAllowedEditor, canRez, connectionUUID); }
int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) { // this is a packet from the domain server, reset the count of un-replied check-ins _numNoReplyDomainCheckIns = 0; int readNodes = 0; char nodeType; uint16_t nodeId; // assumes only IPv4 addresses sockaddr_in nodePublicSocket; nodePublicSocket.sin_family = AF_INET; sockaddr_in nodeLocalSocket; nodeLocalSocket.sin_family = AF_INET; unsigned char* readPtr = packetData + numBytesForPacketHeader(packetData); unsigned char* startPtr = packetData; while((readPtr - startPtr) < dataBytes - sizeof(uint16_t)) { nodeType = *readPtr++; readPtr += unpackNodeId(readPtr, (uint16_t*) &nodeId); readPtr += unpackSocket(readPtr, (sockaddr*) &nodePublicSocket); readPtr += unpackSocket(readPtr, (sockaddr*) &nodeLocalSocket); // if the public socket address is 0 then it's reachable at the same IP // as the domain server if (nodePublicSocket.sin_addr.s_addr == 0) { nodePublicSocket.sin_addr.s_addr = htonl(_domainIP.toIPv4Address()); } addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId); } // read out our ID from the packet unpackNodeId(readPtr, &_ownerID); return readNodes; }
/** * @param masterList must be ordered; contained nodes will be removed and may no longer be * accessed after calling this method. * @param updateExisting true to call addOrUpdate for nodes that already existed in the store * @param appLocalNode just what you get from app->getLocalNode(), to determine NIC capabilities */ void NodeStoreServers::syncNodes(NodeList* masterList, UInt16List* outAddedNumIDs, UInt16List* outRemovedNumIDs, bool updateExisting, Node* appLocalNode) { // Note: We have two phases here: // Phase 1 (locked): Identify added/removed nodes. // Phase 2 (unlocked): Add/remove nodes from store. // This separation is required to not break compatibility with virtual overwritten add/remove // methods in derived classes (e.g. fhgfs_mgmtd). // P H A S E 1 (Identify added/removed nodes.) SafeMutexLock mutexLock(&mutex); // L O C K uint16_t localNodeNumID = 0; // 0 is invalid/unset, as usual for our numeric IDs NodeList addLaterNodes; // nodes to be added in phase 2 NodeReferencer localNodeRefer(localNode, false); /* don't move this into if-brackets, because it would be removed from stack then and we need to access it again further below.*/ // temporary insertion of localNode if(localNode) { localNodeNumID = localNode->getNumID(); activeNodes.insert(NodeMapVal(localNodeNumID, &localNodeRefer) ); } NodeMapIter activeIter = activeNodes.begin(); NodeListIter masterIter = masterList->begin(); while( (activeIter != activeNodes.end() ) && (masterIter != masterList->end() ) ) { uint16_t currentActive = activeIter->first; uint16_t currentMaster = (*masterIter)->getNumID(); if(currentMaster < currentActive) { // currentMaster is added outAddedNumIDs->push_back(currentMaster); addLaterNodes.push_back(*masterIter); masterList->pop_front(); masterIter = masterList->begin(); } else if(currentActive < currentMaster) { // currentActive is removed (but don't ever remove localNode) if(likely(localNodeNumID != currentActive) ) outRemovedNumIDs->push_back(currentActive); activeIter++; } else { // node unchanged if(!updateExisting) delete(*masterIter); else addLaterNodes.push_back(*masterIter); masterList->pop_front(); masterIter = masterList->begin(); activeIter++; } } // remaining masterList nodes are added while(masterIter != masterList->end() ) { outAddedNumIDs->push_back( (*masterIter)->getNumID() ); addLaterNodes.push_back(*masterIter); masterList->pop_front(); masterIter = masterList->begin(); } // remaining active nodes are removed for( ; activeIter != activeNodes.end(); activeIter++) { if(likely(localNodeNumID != activeIter->first) ) // (don't ever remove localNode) outRemovedNumIDs->push_back(activeIter->first); } if(localNode) // remove temporarily inserted localNode activeNodes.erase(localNodeNumID); mutexLock.unlock(); // U N L O C K // P H A S E 2 (Add/remove nodes from store.) // remove nodes UInt16ListIter iter = outRemovedNumIDs->begin(); while(iter != outRemovedNumIDs->end() ) { uint16_t nodeID = *iter; iter++; // (removal invalidates iter) deleteNode(nodeID); } // set supported nic capabilities for added nodes NicListCapabilities localNicCaps; if(appLocalNode) { NicAddressList localNicList(appLocalNode->getNicList() ); NetworkInterfaceCard::supportedCapabilities(&localNicList, &localNicCaps); } // add nodes for(NodeListIter iter = addLaterNodes.begin(); iter != addLaterNodes.end(); iter++) { Node* node = *iter; if(appLocalNode) node->getConnPool()->setLocalNicCaps(&localNicCaps); addOrUpdateNode(&node, NULL); } }
/** * Just forwards to the other addOrUpdateNode method (to provide compatibility with the * corresponding virtual AbstractNodeStore::addOrUpdateNode() method). */ bool NodeStoreServers::addOrUpdateNode(Node** node) { return addOrUpdateNode(node, NULL); }