uvgRTP
rtcp.hh
1 #pragma once
2 
3 #include <bitset>
4 #include <map>
5 #include <thread>
6 #include <vector>
7 
8 #include "clock.hh"
9 #include "frame.hh"
10 #include "runner.hh"
11 #include "socket.hh"
12 #include "srtp/srtcp.hh"
13 #include "util.hh"
14 
15 namespace uvgrtp {
16 
18  enum RTCP_ROLE {
19  RECEIVER,
20  SENDER
21  };
22 
23  /* TODO: explain these constants */
24  const int RTP_SEQ_MOD = 1 << 16;
25  const int MIN_SEQUENTIAL = 2;
26  const int MAX_DROPOUT = 3000;
27  const int MAX_MISORDER = 100;
28  const int MIN_TIMEOUT = 5000;
29 
30  struct rtcp_statistics {
31  /* receiver stats */
32  uint32_t received_pkts; /* Number of packets received */
33  uint32_t dropped_pkts; /* Number of dropped RTP packets */
34  uint32_t received_bytes; /* Number of bytes received excluding RTP Header */
35 
36  /* sender stats */
37  uint32_t sent_pkts; /* Number of sent RTP packets */
38  uint32_t sent_bytes; /* Number of sent bytes excluding RTP Header */
39 
40  uint32_t jitter; /* TODO: */
41  uint32_t transit; /* TODO: */
42 
43  /* Receiver clock related stuff */
44  uint64_t initial_ntp; /* Wallclock reading when the first RTP packet was received */
45  uint32_t initial_rtp; /* RTP timestamp of the first RTP packet received */
46  uint32_t clock_rate; /* Rate of the clock (used for jitter calculations) */
47 
48  uint32_t lsr; /* Middle 32 bits of the 64-bit NTP timestamp of previous SR */
49  uvgrtp::clock::hrc::hrc_t sr_ts; /* When the last SR was received (used to calculate delay) */
50 
51  uint16_t max_seq; /* Highest sequence number received */
52  uint16_t base_seq; /* First sequence number received */
53  uint16_t bad_seq; /* TODO: */
54  uint16_t cycles; /* Number of sequence cycles */
55  };
56 
57  struct rtcp_participant {
58  uvgrtp::socket *socket; /* socket associated with this participant */
59  sockaddr_in address; /* address of the participant */
60  struct rtcp_statistics stats; /* RTCP session statistics of the participant */
61 
62  int probation; /* has the participant been fully accepted to the session */
63  int role; /* is the participant a sender or a receiver */
64 
65  /* Save the latest RTCP packets received from this participant
66  * Users can query these packets using the SSRC of participant */
67  uvgrtp::frame::rtcp_sender_report *s_frame;
68  uvgrtp::frame::rtcp_receiver_report *r_frame;
69  uvgrtp::frame::rtcp_sdes_packet *sdes_frame;
70  uvgrtp::frame::rtcp_app_packet *app_frame;
71  };
73 
74  class rtcp : public runner {
75  public:
77  rtcp(uvgrtp::rtp *rtp, int flags);
78  rtcp(uvgrtp::rtp *rtp, uvgrtp::srtcp *srtcp, int flags);
79  ~rtcp();
80 
81  /* start the RTCP runner thread
82  *
83  * return RTP_OK on success and RTP_MEMORY_ERROR if the allocation fails */
84  rtp_error_t start();
85 
86  /* End the RTCP session and send RTCP BYE to all participants
87  *
88  * return RTP_OK on success */
89  rtp_error_t stop();
90 
91  /* Generate either RTCP Sender or Receiver report and sent it to all participants
92  * Return RTP_OK on success and RTP_ERROR on error */
93  rtp_error_t generate_report();
94 
95  /* Handle different kinds of incoming packets
96  *
97  * These routines will convert the fields of "frame" from network to host byte order
98  *
99  * Currently nothing's done with valid packets, at some point an API for
100  * querying these reports is implemented
101  *
102  * Return RTP_OK on success and RTP_ERROR on error */
103  rtp_error_t handle_sender_report_packet(uint8_t *frame, size_t size);
104  rtp_error_t handle_receiver_report_packet(uint8_t *frame, size_t size);
105  rtp_error_t handle_sdes_packet(uint8_t *frame, size_t size);
106  rtp_error_t handle_bye_packet(uint8_t *frame, size_t size);
107  rtp_error_t handle_app_packet(uint8_t *frame, size_t size);
108 
109  /* Handle incoming RTCP packet (first make sure it's a valid RTCP packet)
110  * This function will call one of the above functions internally
111  *
112  * Return RTP_OK on success and RTP_ERROR on error */
113  rtp_error_t handle_incoming_packet(uint8_t *buffer, size_t size);
115 
116  /* Send "frame" to all participants
117  *
118  * These routines will convert all necessary fields to network byte order
119  *
120  * Return RTP_OK on success
121  * Return RTP_INVALID_VALUE if "frame" is in some way invalid
122  * Return RTP_SEND_ERROR if sending "frame" did not succeed (see socket.hh for details) */
123  rtp_error_t send_sdes_packet(std::vector<uvgrtp::frame::rtcp_sdes_item>& items);
124  rtp_error_t send_app_packet(char *name, uint8_t subtype, size_t payload_len, uint8_t *payload);
125  rtp_error_t send_bye_packet(std::vector<uint32_t> ssrcs);
126 
128  /* Return the latest RTCP packet received from participant of "ssrc"
129  * Return nullptr if we haven't received this kind of packet or if "ssrc" doesn't exist
130  *
131  * NOTE: Caller is responsible for deallocating the memory */
132  uvgrtp::frame::rtcp_sender_report *get_sender_packet(uint32_t ssrc);
133  uvgrtp::frame::rtcp_receiver_report *get_receiver_packet(uint32_t ssrc);
134  uvgrtp::frame::rtcp_sdes_packet *get_sdes_packet(uint32_t ssrc);
135  uvgrtp::frame::rtcp_app_packet *get_app_packet(uint32_t ssrc);
136 
137  /* Return a reference to vector that contains the sockets of all participants */
138  std::vector<uvgrtp::socket>& get_sockets();
139 
140  /* Somebody joined the multicast group the owner of this RTCP instance is part of
141  * Add it to RTCP participant list so we can start listening for reports
142  *
143  * "clock_rate" tells how much the RTP timestamp advances, this information is needed
144  * to calculate the interarrival jitter correctly. It has nothing do with our clock rate,
145  * (or whether we're even sending anything)
146  *
147  * Return RTP_OK on success and RTP_ERROR on error */
148  rtp_error_t add_participant(std::string dst_addr, uint16_t dst_port, uint16_t src_port, uint32_t clock_rate);
149 
150  /* Functions for updating various RTP sender statistics */
151  void sender_inc_seq_cycle_count();
152  void sender_inc_sent_pkts(size_t n);
153  void sender_inc_sent_bytes(size_t n);
154  void sender_update_stats(uvgrtp::frame::rtp_frame *frame);
155 
156  void receiver_inc_sent_bytes(uint32_t sender_ssrc, size_t n);
157  void receiver_inc_overhead_bytes(uint32_t sender_ssrc, size_t n);
158  void receiver_inc_total_bytes(uint32_t sender_ssrc, size_t n);
159  void receiver_inc_sent_pkts(uint32_t sender_ssrc, size_t n);
160 
161  /* Update the RTCP statistics regarding this packet
162  *
163  * Return RTP_OK if packet is valid
164  * Return RTP_INVALID_VALUE if SSRCs of remotes have collided or the packet is invalid in some way
165  * return RTP_SSRC_COLLISION if our own SSRC has collided and we need to reinitialize it */
166  rtp_error_t receiver_update_stats(uvgrtp::frame::rtp_frame *frame);
167 
168  /* If we've detected that our SSRC has collided with someone else's SSRC, we need to
169  * generate new random SSRC and reinitialize our own RTCP state.
170  * RTCP object still has the participants of "last session", we can use their SSRCs
171  * to detected new collision
172  *
173  * Return RTP_OK if reinitialization succeeded
174  * Return RTP_SSRC_COLLISION if our new SSRC has collided and we need to generate new SSRC */
175  rtp_error_t reset_rtcp_state(uint32_t ssrc);
176 
177  /* Update various session statistics */
178  void update_session_statistics(uvgrtp::frame::rtp_frame *frame);
179 
180  /* Return SSRCs of all participants */
181  std::vector<uint32_t> get_participants();
183 
184  /* Set wallclock reading for t = 0 and random RTP timestamp from where the counting is started
185  * + clock rate for calculating the correct increment */
186  void set_ts_info(uint64_t clock_start, uint32_t clock_rate, uint32_t rtp_ts_start);
187 
188  /* Alternate way to get RTCP packets is to install a hook for them. So instead of
189  * polling an RTCP packet, user can install a function that is called when
190  * a specific RTCP packet is received. */
191  rtp_error_t install_sender_hook(void (*hook)(uvgrtp::frame::rtcp_sender_report *));
192  rtp_error_t install_receiver_hook(void (*hook)(uvgrtp::frame::rtcp_receiver_report *));
193  rtp_error_t install_sdes_hook(void (*hook)(uvgrtp::frame::rtcp_sdes_packet *));
194  rtp_error_t install_app_hook(void (*hook)(uvgrtp::frame::rtcp_app_packet *));
195 
197  /* Update RTCP-related sender statistics */
198  rtp_error_t update_sender_stats(size_t pkt_size);
199 
200  /* Update RTCP-related receiver statistics */
201  static rtp_error_t recv_packet_handler(void *arg, int flags, frame::rtp_frame **out);
202 
203  /* Update RTCP-related sender statistics */
204  static rtp_error_t send_packet_handler_vec(void *arg, uvgrtp::buf_vec& buffers);
206 
207  private:
208  static void rtcp_runner(rtcp *rtcp);
209 
210  /* when we start the RTCP instance, we don't know what the SSRC of the remote is
211  * when an RTP packet is received, we must check if we've already received a packet
212  * from this sender and if not, create new entry to receiver_stats_ map */
213  bool is_participant(uint32_t ssrc);
214 
215  /* When we receive an RTP or RTCP packet, we need to check the source address and see if it's
216  * the same address where we've received packets before.
217  *
218  * If the address is new, it means we have detected an SSRC collision and the paket should
219  * be dropped We also need to check whether this SSRC matches with our own SSRC and if it does
220  * we need to send RTCP BYE and rejoin to the session */
221  bool collision_detected(uint32_t ssrc, sockaddr_in& src_addr);
222 
223  /* Move participant from initial_peers_ to participants_ */
224  rtp_error_t add_participant(uint32_t ssrc);
225 
226  /* We've got a message from new source (the SSRC of the frame is not known to us)
227  * Initialize statistics for the peer and move it to participants_ */
228  rtp_error_t init_new_participant(uvgrtp::frame::rtp_frame *frame);
229 
230  /* Initialize the RTP Sequence related stuff of peer
231  * This function assumes that the peer already exists in the participants_ map */
232  rtp_error_t init_participant_seq(uint32_t ssrc, uint16_t base_seq);
233 
234  /* Update the SSRC's sequence related data in participants_ map
235  *
236  * Return RTP_OK if the received packet was OK
237  * Return RTP_GENERIC_ERROR if it wasn't and
238  * packet-related statistics should not be updated */
239  rtp_error_t update_participant_seq(uint32_t ssrc, uint16_t seq);
240 
241  /* Update the RTCP bandwidth variables
242  *
243  * "pkt_size" tells how much rtcp_byte_count_
244  * should be increased before calculating the new average */
245  void update_rtcp_bandwidth(size_t pkt_size);
246 
247  /* Functions for generating different kinds of reports.
248  * These functions will both generate the report and send it
249  *
250  * Return RTP_OK on success and RTP_ERROR on error */
251  rtp_error_t generate_sender_report();
252  rtp_error_t generate_receiver_report();
253 
254  /* Because struct statistics contains uvgRTP clock object we cannot
255  * zero it out without compiler complaining about it so all the fields
256  * must be set to zero manually */
257  void zero_stats(uvgrtp::rtcp_statistics *stats);
258 
259  /* Pointer to RTP context from which clock rate etc. info is collected and which is
260  * used to change SSRC if a collision is detected */
261  uvgrtp::rtp *rtp_;
262 
263  /* Secure RTCP context */
264  uvgrtp::srtcp *srtcp_;
265 
266  /* RTP context flags */
267  int flags_;
268 
269  /* are we a sender or a receiver */
270  int our_role_;
271 
272  /* TODO: time_t?? */
273  size_t tp_; /* the last time an RTCP packet was transmitted */
274  size_t tc_; /* the current time */
275  size_t tn_; /* the next scheduled transmission time of an RTCP packet */
276  size_t pmembers_; /* the estimated number of session members at the time tn was last recomputed */
277  size_t members_; /* the most current estimate for the number of session members */
278  size_t senders_; /* the most current estimate for the number of senders in the session */
279 
280  /* The target RTCP bandwidth, i.e., the total bandwidth
281  * that will be used for RTCP packets by all members of this session,
282  * in octets per second. This will be a specified fraction of the
283  * "session bandwidth" parameter supplied to the application at startup. */
284  size_t rtcp_bandwidth_;
285 
286  /* Flag that is true if the application has sent data since
287  * the 2nd previous RTCP report was transmitted. */
288  bool we_sent_;
289 
290  /* The average compound RTCP packet size, in octets,
291  * over all RTCP packets sent and received by this participant. The
292  * size includes lower-layer transport and network protocol headers
293  * (e.g., UDP and IP) as explained in Section 6.2 */
294  size_t avg_rtcp_pkt_pize_;
295 
296  /* Number of RTCP packets and bytes sent and received by this participant */
297  size_t rtcp_pkt_count_;
298  size_t rtcp_byte_count_;
299 
300  /* Number of RTCP packets sent */
301  size_t rtcp_pkt_sent_count_;
302 
303  /* Flag that is true if the application has not yet sent an RTCP packet. */
304  bool initial_;
305 
306  /* Copy of our own current SSRC */
307  uint32_t ssrc_;
308 
309  /* NTP timestamp associated with initial RTP timestamp (aka t = 0) */
310  uint64_t clock_start_;
311 
312  /* Clock rate of the media ie. how fast does the time increase */
313  uint32_t clock_rate_;
314 
315  /* The first value of RTP timestamp (aka t = 0) */
316  uint32_t rtp_ts_start_;
317 
318  std::map<uint32_t, rtcp_participant *> participants_;
319  size_t num_receivers_;
320 
321  /* statistics for RTCP Sender and Receiver Reports */
322  struct rtcp_statistics our_stats;
323 
324  /* If we expect frames from remote but haven't received anything from remote yet,
325  * the participant resides in this vector until he's moved to participants_ */
326  std::vector<rtcp_participant *> initial_participants_;
327 
328  /* Vector of sockets the RTCP runner is listening to
329  *
330  * The socket are also stored here (in addition to participants_ map) so they're easier
331  * to pass to poll when RTCP runner is listening to incoming packets */
332  std::vector<uvgrtp::socket> sockets_;
333 
334  void (*sender_hook_)(uvgrtp::frame::rtcp_sender_report *);
335  void (*receiver_hook_)(uvgrtp::frame::rtcp_receiver_report *);
336  void (*sdes_hook_)(uvgrtp::frame::rtcp_sdes_packet *);
337  void (*app_hook_)(uvgrtp::frame::rtcp_app_packet *);
338  };
339 };
340 
341 namespace uvg_rtp = uvgrtp;
Definition: rtcp.hh:74