177 lines · 7.0 KB · C
RawDownload
////  PacketReceiver.h//  libraries/networking/src////  Created by Stephen Birarda on 1/23/2014.//  Update by Ryan Huffman on 7/8/2015.//  Copyright 2014 High Fidelity, Inc.//  Copyright 2021 Vircadia contributors.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #ifndef hifi_PacketReceiver_h#define hifi_PacketReceiver_h #include <vector>#include <unordered_map> #include <QtCore/QMutex>#include <QtCore/QObject>#include <QtCore/QPointer>#include <QtCore/QSet>#include <QtCore/QSharedPointer>#include <QtCore/QEnableSharedFromThis> #include "NLPacket.h"#include "NLPacketList.h"#include "ReceivedMessage.h"#include "udt/PacketHeaders.h" struct sock_and_msgnum_hash {    size_t operator()(const std::pair<SockAddr, udt::Packet::MessageNumber>& pair) const {        return std::hash<SockAddr>()(pair.first) ^ std::hash<udt::Packet::MessageNumber>()(pair.second);    }}; class EntityEditPacketSender;class Node;class OctreePacketProcessor; class PacketReceiver : public QObject {    Q_OBJECTpublic:    class ListenerReference : public QEnableSharedFromThis<ListenerReference> {    public:        virtual bool invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) = 0;        bool invokeWithQt(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode);        virtual bool isSourced() const = 0;        virtual QObject* getObject() const = 0;    };    typedef QSharedPointer<ListenerReference> ListenerReferencePointer;     template<class T>    static ListenerReferencePointer makeUnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>));     template <class T>    static ListenerReferencePointer makeSourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>)); public:    using PacketTypeList = std::vector<PacketType>;     PacketReceiver(QObject* parent = 0);    PacketReceiver(const PacketReceiver&) = delete;     PacketReceiver& operator=(const PacketReceiver&) = delete;     void setShouldDropPackets(bool shouldDropPackets) { _shouldDropPackets = shouldDropPackets; }     // If deliverPending is false, ReceivedMessage will only be delivered once all packets for the message have    // been received. If deliverPending is true, ReceivedMessage will be delivered as soon as the first packet    // for the message is received.    bool registerListener(PacketType type, const ListenerReferencePointer& listener, bool deliverPending = false);    bool registerListenerForTypes(PacketTypeList types, const ListenerReferencePointer& listener);    void unregisterListener(QObject* listener);     void handleVerifiedPacket(std::unique_ptr<udt::Packet> packet);    void handleVerifiedMessagePacket(std::unique_ptr<udt::Packet> message);    void handleMessageFailure(SockAddr from, udt::Packet::MessageNumber messageNumber); private:    template <class T>    class UnsourcedListenerReference : public ListenerReference {    public:        inline UnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>));        virtual bool invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) override;        virtual bool isSourced() const override { return false; }        virtual QObject* getObject() const override { return _target; }     private:        QPointer<T> _target;        void (T::*_slot)(QSharedPointer<ReceivedMessage>);    };     template <class T>    class SourcedListenerReference : public ListenerReference {    public:        inline SourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>));        virtual bool invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) override;        virtual bool isSourced() const override { return true; }        virtual QObject* getObject() const override { return _target; }     private:        QPointer<T> _target;        void (T::*_slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>);    };     struct Listener {        ListenerReferencePointer listener;        bool deliverPending;    };     void handleVerifiedMessage(QSharedPointer<ReceivedMessage> message, bool justReceived);     // these are brutal hacks for now - ideally GenericThread / ReceivedPacketProcessor    // should be changed to have a true event loop and be able to handle our QMetaMethod::invoke    void registerDirectListenerForTypes(PacketTypeList types, const ListenerReferencePointer& listener);    void registerDirectListener(PacketType type, const ListenerReferencePointer& listener);     bool matchingMethodForListener(PacketType type, const ListenerReferencePointer& listener) const;    void registerVerifiedListener(PacketType type, const ListenerReferencePointer& listener, bool deliverPending = false);     QMutex _packetListenerLock;    QHash<PacketType, Listener> _messageListenerMap;     bool _shouldDropPackets = false;    QMutex _directConnectSetMutex;    QSet<QObject*> _directlyConnectedObjects;     std::unordered_map<std::pair<SockAddr, udt::Packet::MessageNumber>, QSharedPointer<ReceivedMessage>, sock_and_msgnum_hash>        _pendingMessages;     friend class EntityEditPacketSender;    friend class OctreePacketProcessor;}; template <class T>PacketReceiver::ListenerReferencePointer PacketReceiver::makeUnsourcedListenerReference(T* target, void (T::* slot)(QSharedPointer<ReceivedMessage>)) {    auto ptr = QSharedPointer<UnsourcedListenerReference<T>>::create(target, slot);    return ptr;} template <class T>PacketReceiver::ListenerReferencePointer PacketReceiver::makeSourcedListenerReference(T* target, void (T::* slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>)) {    auto ptr = QSharedPointer<SourcedListenerReference<T>>::create(target, slot);    return ptr;} template <class T>PacketReceiver::UnsourcedListenerReference<T>::UnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>)) :    _target(target),_slot(slot) {} template <class T>bool PacketReceiver::UnsourcedListenerReference<T>::invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>&) {    if (_target.isNull()) {        return false;    }    (_target->*_slot)(receivedMessagePointer);    return true;} template <class T>PacketReceiver::SourcedListenerReference<T>::SourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>)) :    _target(target),_slot(slot) {} template <class T>bool PacketReceiver::SourcedListenerReference<T>::invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) {    if (_target.isNull()) {        return false;    }    (_target->*_slot)(receivedMessagePointer, sourceNode);    return true;} #endif  // hifi_PacketReceiver_h