// This method is called when the edit packet layer has determined that it has a fully formed packet destined for // a known nodeID. void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) { NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { if (node->getActiveSocket()) { queuePacketForSending(node, QByteArray(reinterpret_cast<char*>(buffer), length)); // debugging output... bool wantDebugging = false; if (wantDebugging) { int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<char*>(buffer)); unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); quint64 createdAt = (*((quint64*)(buffer + numBytesPacketHeader + sizeof(sequence)))); quint64 queuedAt = usecTimestampNow(); quint64 transitTime = queuedAt - createdAt; qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << " - command to node bytes=" << length << " sequence=" << sequence << " transitTimeSoFar=" << transitTime << " usecs"; } } } } }
void OctreeEditPacketSender::processNackPacket(const QByteArray& packet) { // parse sending node from packet, retrieve packet history for that node QUuid sendingNodeUUID = uuidFromPacketHeader(packet); // if packet history doesn't exist for the sender node (somehow), bail if (!_sentPacketHistories.contains(sendingNodeUUID)) { return; } const SentPacketHistory& sentPacketHistory = _sentPacketHistories.value(sendingNodeUUID); int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast<const unsigned char*>(packet.data()) + numBytesPacketHeader; // read number of sequence numbers uint16_t numSequenceNumbers = (*(uint16_t*)dataAt); dataAt += sizeof(uint16_t); // read sequence numbers and queue packets for resend for (int i = 0; i < numSequenceNumbers; i++) { unsigned short int sequenceNumber = (*(unsigned short int*)dataAt); dataAt += sizeof(unsigned short int); // retrieve packet from history const QByteArray* packet = sentPacketHistory.getPacket(sequenceNumber); if (packet) { const SharedNodePointer& node = DependencyManager::get<NodeList>()->nodeWithUUID(sendingNodeUUID); queuePacketForSending(node, *packet); } } }
// This method is called when the edit packet layer has determined that it has a fully formed packet destined for // a known nodeID. void OctreeEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, size_t length, qint64 satoshiCost) { bool wantDebug = false; DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& node){ // only send to the NodeTypes that are getMyNodeType() if (node->getType() == getMyNodeType() && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull())) && node->getActiveSocket()) { // pack sequence number int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<char*>(buffer)); unsigned char* sequenceAt = buffer + numBytesPacketHeader; quint16 sequence = _outgoingSequenceNumbers[nodeUUID]++; memcpy(sequenceAt, &sequence, sizeof(quint16)); // send packet QByteArray packet(reinterpret_cast<const char*>(buffer), length); queuePacketForSending(node, packet); if (hasDestinationWalletUUID() && satoshiCost > 0) { // if we have a destination wallet UUID and a cost associated with this packet, signal that it // needs to be sent emit octreePaymentRequired(satoshiCost, nodeUUID, _destinationWalletUUID); } // add packet to history _sentPacketHistories[nodeUUID].packetSent(sequence, packet); // debugging output... if (wantDebug) { int numBytesPacketHeader = numBytesForPacketHeader(reinterpret_cast<const char*>(buffer)); unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); quint64 createdAt = (*((quint64*)(buffer + numBytesPacketHeader + sizeof(sequence)))); quint64 queuedAt = usecTimestampNow(); quint64 transitTime = queuedAt - createdAt; qDebug() << "OctreeEditPacketSender::queuePacketToNode() queued " << buffer[0] << " - command to node bytes=" << length << " satoshiCost=" << satoshiCost << " sequence=" << sequence << " transitTimeSoFar=" << transitTime << " usecs"; } } }); }
// This method is called when the edit packet layer has determined that it has a fully formed packet destined for // a known nodeID. However, we also want to handle the case where the void VoxelEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getType() == NODE_TYPE_VOXEL_SERVER && ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { if (nodeList->getNodeActiveSocketOrPing(&(*node))) { sockaddr* nodeAddress = node->getActiveSocket(); queuePacketForSending(*nodeAddress, buffer, length); // debugging output... bool wantDebugging = false; if (wantDebugging) { int numBytesPacketHeader = numBytesForPacketHeader(buffer); unsigned short int sequence = (*((unsigned short int*)(buffer + numBytesPacketHeader))); uint64_t createdAt = (*((uint64_t*)(buffer + numBytesPacketHeader + sizeof(sequence)))); uint64_t queuedAt = usecTimestampNow(); uint64_t transitTime = queuedAt - createdAt; const char* messageName; switch (buffer[0]) { case PACKET_TYPE_SET_VOXEL: messageName = "PACKET_TYPE_SET_VOXEL"; break; case PACKET_TYPE_SET_VOXEL_DESTRUCTIVE: messageName = "PACKET_TYPE_SET_VOXEL_DESTRUCTIVE"; break; case PACKET_TYPE_ERASE_VOXEL: messageName = "PACKET_TYPE_ERASE_VOXEL"; break; } printf("VoxelEditPacketSender::queuePacketToNode() queued %s - command to node bytes=%ld sequence=%d transitTimeSoFar=%llu usecs\n", messageName, length, sequence, transitTime); } } } } }