Overte C++ Documentation
PacketReceiver.h
1 //
2 // PacketReceiver.h
3 // libraries/networking/src
4 //
5 // Created by Stephen Birarda on 1/23/2014.
6 // Update by Ryan Huffman on 7/8/2015.
7 // Copyright 2014 High Fidelity, Inc.
8 // Copyright 2021 Vircadia contributors.
9 //
10 // Distributed under the Apache License, Version 2.0.
11 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
12 //
13 
14 #ifndef hifi_PacketReceiver_h
15 #define hifi_PacketReceiver_h
16 
17 #include <vector>
18 #include <unordered_map>
19 
20 #include <QtCore/QMutex>
21 #include <QtCore/QObject>
22 #include <QtCore/QPointer>
23 #include <QtCore/QSet>
24 #include <QtCore/QSharedPointer>
25 #include <QtCore/QEnableSharedFromThis>
26 
27 #include "NLPacket.h"
28 #include "NLPacketList.h"
29 #include "ReceivedMessage.h"
30 #include "udt/PacketHeaders.h"
31 
32 struct sock_and_msgnum_hash {
33  size_t operator()(const std::pair<SockAddr, udt::Packet::MessageNumber>& pair) const {
34  return std::hash<SockAddr>()(pair.first) ^ std::hash<udt::Packet::MessageNumber>()(pair.second);
35  }
36 };
37 
39 class Node;
41 
42 class PacketReceiver : public QObject {
43  Q_OBJECT
44 public:
45  class ListenerReference : public QEnableSharedFromThis<ListenerReference> {
46  public:
47  virtual bool invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) = 0;
48  bool invokeWithQt(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode);
49  virtual bool isSourced() const = 0;
50  virtual QObject* getObject() const = 0;
51  };
52  typedef QSharedPointer<ListenerReference> ListenerReferencePointer;
53 
54  template<class T>
55  static ListenerReferencePointer makeUnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>));
56 
57  template <class T>
58  static ListenerReferencePointer makeSourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>));
59 
60 public:
61  using PacketTypeList = std::vector<PacketType>;
62 
63  PacketReceiver(QObject* parent = 0);
64  PacketReceiver(const PacketReceiver&) = delete;
65 
66  PacketReceiver& operator=(const PacketReceiver&) = delete;
67 
68  void setShouldDropPackets(bool shouldDropPackets) { _shouldDropPackets = shouldDropPackets; }
69 
70  // If deliverPending is false, ReceivedMessage will only be delivered once all packets for the message have
71  // been received. If deliverPending is true, ReceivedMessage will be delivered as soon as the first packet
72  // for the message is received.
73  bool registerListener(PacketType type, const ListenerReferencePointer& listener, bool deliverPending = false);
74  bool registerListenerForTypes(PacketTypeList types, const ListenerReferencePointer& listener);
75  void unregisterListener(QObject* listener);
76 
77  void handleVerifiedPacket(std::unique_ptr<udt::Packet> packet);
78  void handleVerifiedMessagePacket(std::unique_ptr<udt::Packet> message);
79  void handleMessageFailure(SockAddr from, udt::Packet::MessageNumber messageNumber);
80 
81 private:
82  template <class T>
83  class UnsourcedListenerReference : public ListenerReference {
84  public:
85  inline UnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>));
86  virtual bool invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) override;
87  virtual bool isSourced() const override { return false; }
88  virtual QObject* getObject() const override { return _target; }
89 
90  private:
91  QPointer<T> _target;
92  void (T::*_slot)(QSharedPointer<ReceivedMessage>);
93  };
94 
95  template <class T>
96  class SourcedListenerReference : public ListenerReference {
97  public:
98  inline SourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>));
99  virtual bool invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) override;
100  virtual bool isSourced() const override { return true; }
101  virtual QObject* getObject() const override { return _target; }
102 
103  private:
104  QPointer<T> _target;
105  void (T::*_slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>);
106  };
107 
108  struct Listener {
109  ListenerReferencePointer listener;
110  bool deliverPending;
111  };
112 
113  void handleVerifiedMessage(QSharedPointer<ReceivedMessage> message, bool justReceived);
114 
115  // these are brutal hacks for now - ideally GenericThread / ReceivedPacketProcessor
116  // should be changed to have a true event loop and be able to handle our QMetaMethod::invoke
117  void registerDirectListenerForTypes(PacketTypeList types, const ListenerReferencePointer& listener);
118  void registerDirectListener(PacketType type, const ListenerReferencePointer& listener);
119 
120  bool matchingMethodForListener(PacketType type, const ListenerReferencePointer& listener) const;
121  void registerVerifiedListener(PacketType type, const ListenerReferencePointer& listener, bool deliverPending = false);
122 
123  QMutex _packetListenerLock;
124  QHash<PacketType, Listener> _messageListenerMap;
125 
126  bool _shouldDropPackets = false;
127  QMutex _directConnectSetMutex;
128  QSet<QObject*> _directlyConnectedObjects;
129 
130  std::unordered_map<std::pair<SockAddr, udt::Packet::MessageNumber>, QSharedPointer<ReceivedMessage>, sock_and_msgnum_hash>
131  _pendingMessages;
132 
133  friend class EntityEditPacketSender;
134  friend class OctreePacketProcessor;
135 };
136 
137 template <class T>
138 PacketReceiver::ListenerReferencePointer PacketReceiver::makeUnsourcedListenerReference(T* target, void (T::* slot)(QSharedPointer<ReceivedMessage>)) {
139  auto ptr = QSharedPointer<UnsourcedListenerReference<T>>::create(target, slot);
140  return ptr;
141 }
142 
143 template <class T>
144 PacketReceiver::ListenerReferencePointer PacketReceiver::makeSourcedListenerReference(T* target, void (T::* slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>)) {
145  auto ptr = QSharedPointer<SourcedListenerReference<T>>::create(target, slot);
146  return ptr;
147 }
148 
149 template <class T>
150 PacketReceiver::UnsourcedListenerReference<T>::UnsourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>)) :
151  _target(target),_slot(slot) {
152 }
153 
154 template <class T>
155 bool PacketReceiver::UnsourcedListenerReference<T>::invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>&) {
156  if (_target.isNull()) {
157  return false;
158  }
159  (_target->*_slot)(receivedMessagePointer);
160  return true;
161 }
162 
163 template <class T>
164 PacketReceiver::SourcedListenerReference<T>::SourcedListenerReference(T* target, void (T::*slot)(QSharedPointer<ReceivedMessage>, QSharedPointer<Node>)) :
165  _target(target),_slot(slot) {
166 }
167 
168 template <class T>
169 bool PacketReceiver::SourcedListenerReference<T>::invokeDirectly(const QSharedPointer<ReceivedMessage>& receivedMessagePointer, const QSharedPointer<Node>& sourceNode) {
170  if (_target.isNull()) {
171  return false;
172  }
173  (_target->*_slot)(receivedMessagePointer, sourceNode);
174  return true;
175 }
176 
177 #endif // hifi_PacketReceiver_h
Utility for processing, packing, queueing and sending of outbound edit voxel messages.
Definition: EntityEditPacketSender.h:25
Definition: OctreePacketProcessor.h:25