void IceServer::processDatagrams() { HifiSockAddr sendingSockAddr; while (_serverSocket.hasPendingDatagrams()) { // setup a buffer to read the packet into int packetSizeWithHeader = _serverSocket.pendingDatagramSize(); auto buffer = std::unique_ptr<char[]>(new char[packetSizeWithHeader]); _serverSocket.readDatagram(buffer.get(), packetSizeWithHeader, sendingSockAddr.getAddressPointer(), sendingSockAddr.getPortPointer()); // make sure that this packet at least looks like something we can read if (packetSizeWithHeader >= Packet::localHeaderSize(PacketType::ICEServerHeartbeat)) { auto packet = Packet::fromReceivedPacket(std::move(buffer), packetSizeWithHeader, sendingSockAddr); PacketType::Value packetType = packet->getType(); if (packetType == PacketType::ICEServerHeartbeat) { SharedNetworkPeer peer = addOrUpdateHeartbeatingPeer(*packet); // so that we can send packets to the heartbeating peer when we need, we need to activate a socket now peer->activateMatchingOrNewSymmetricSocket(sendingSockAddr); } else if (packetType == PacketType::ICEServerQuery) { QDataStream heartbeatStream(packet.get()); // this is a node hoping to connect to a heartbeating peer - do we have the heartbeating peer? QUuid senderUUID; heartbeatStream >> senderUUID; // pull the public and private sock addrs for this peer HifiSockAddr publicSocket, localSocket; heartbeatStream >> publicSocket >> localSocket; // check if this node also included a UUID that they would like to connect to QUuid connectRequestID; heartbeatStream >> connectRequestID; SharedNetworkPeer matchingPeer = _activePeers.value(connectRequestID); if (matchingPeer) { qDebug() << "Sending information for peer" << connectRequestID << "to peer" << senderUUID; // we have the peer they want to connect to - send them pack the information for that peer sendPeerInformationPacket(*(matchingPeer.data()), &sendingSockAddr); // we also need to send them to the active peer they are hoping to connect to // create a dummy peer object we can pass to sendPeerInformationPacket NetworkPeer dummyPeer(senderUUID, publicSocket, localSocket); sendPeerInformationPacket(dummyPeer, matchingPeer->getActiveSocket()); } else { qDebug() << "Peer" << senderUUID << "asked for" << connectRequestID << "but no matching peer found"; } } }
void IceServer::processPacket(std::unique_ptr<udt::Packet> packet) { auto nlPacket = NLPacket::fromBase(std::move(packet)); // make sure that this packet at least looks like something we can read if (nlPacket->getPayloadSize() >= NLPacket::localHeaderSize(PacketType::ICEServerHeartbeat)) { if (nlPacket->getType() == PacketType::ICEServerHeartbeat) { SharedNetworkPeer peer = addOrUpdateHeartbeatingPeer(*nlPacket); if (peer) { // so that we can send packets to the heartbeating peer when we need, we need to activate a socket now peer->activateMatchingOrNewSymmetricSocket(nlPacket->getSenderSockAddr()); // we have an active and verified heartbeating peer // send them an ACK packet so they know that they are being heard and ready for ICE static auto ackPacket = NLPacket::create(PacketType::ICEServerHeartbeatACK); _serverSocket.writePacket(*ackPacket, nlPacket->getSenderSockAddr()); } else { // we couldn't verify this peer - respond back to them so they know they may need to perform keypair re-generation static auto deniedPacket = NLPacket::create(PacketType::ICEServerHeartbeatDenied); _serverSocket.writePacket(*deniedPacket, nlPacket->getSenderSockAddr()); } } else if (nlPacket->getType() == PacketType::ICEServerQuery) { QDataStream heartbeatStream(nlPacket.get()); // this is a node hoping to connect to a heartbeating peer - do we have the heartbeating peer? QUuid senderUUID; heartbeatStream >> senderUUID; // pull the public and private sock addrs for this peer HifiSockAddr publicSocket, localSocket; heartbeatStream >> publicSocket >> localSocket; // check if this node also included a UUID that they would like to connect to QUuid connectRequestID; heartbeatStream >> connectRequestID; SharedNetworkPeer matchingPeer = _activePeers.value(connectRequestID); if (matchingPeer) { qDebug() << "Sending information for peer" << connectRequestID << "to peer" << senderUUID; // we have the peer they want to connect to - send them pack the information for that peer sendPeerInformationPacket(*matchingPeer, &nlPacket->getSenderSockAddr()); // we also need to send them to the active peer they are hoping to connect to // create a dummy peer object we can pass to sendPeerInformationPacket NetworkPeer dummyPeer(senderUUID, publicSocket, localSocket); sendPeerInformationPacket(dummyPeer, matchingPeer->getActiveSocket()); } else { qDebug() << "Peer" << senderUUID << "asked for" << connectRequestID << "but no matching peer found"; } } }
void IceServer::processDatagrams() { HifiSockAddr sendingSockAddr; QByteArray incomingPacket; while (_serverSocket.hasPendingDatagrams()) { incomingPacket.resize(_serverSocket.pendingDatagramSize()); _serverSocket.readDatagram(incomingPacket.data(), incomingPacket.size(), sendingSockAddr.getAddressPointer(), sendingSockAddr.getPortPointer()); if (packetTypeForPacket(incomingPacket) == PacketTypeIceServerHeartbeat) { QUuid senderUUID = uuidFromPacketHeader(incomingPacket); // pull the public and private sock addrs for this peer HifiSockAddr publicSocket, localSocket; QDataStream hearbeatStream(incomingPacket); hearbeatStream.skipRawData(numBytesForPacketHeader(incomingPacket)); hearbeatStream >> publicSocket >> localSocket; // make sure we have this sender in our peer hash SharedNetworkPeer matchingPeer = _activePeers.value(senderUUID); if (!matchingPeer) { // if we don't have this sender we need to create them now matchingPeer = SharedNetworkPeer(new NetworkPeer(senderUUID, publicSocket, localSocket)); _activePeers.insert(senderUUID, matchingPeer); qDebug() << "Added a new network peer" << *matchingPeer; } else { // we already had the peer so just potentially update their sockets matchingPeer->setPublicSocket(publicSocket); matchingPeer->setLocalSocket(localSocket); qDebug() << "Matched hearbeat to existing network peer" << *matchingPeer; } // update our last heard microstamp for this network peer to now matchingPeer->setLastHeardMicrostamp(usecTimestampNow()); // check if this node also included a UUID that they would like to connect to QUuid connectRequestID; hearbeatStream >> connectRequestID; // get the peers asking for connections with this peer QSet<QUuid>& requestingConnections = _currentConnections[senderUUID]; if (!connectRequestID.isNull()) { qDebug() << "Peer wants to connect to peer with ID" << uuidStringWithoutCurlyBraces(connectRequestID); // ensure this peer is in the set of current connections for the peer with ID it wants to connect with _currentConnections[connectRequestID].insert(senderUUID); // add the ID of the node they have said they would like to connect to requestingConnections.insert(connectRequestID); } if (requestingConnections.size() > 0) { // send a heartbeart response based on the set of connections qDebug() << "Sending a heartbeat response to" << senderUUID << "who has" << requestingConnections.size() << "potential connections"; sendHeartbeatResponse(sendingSockAddr, requestingConnections); } } }