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 
198  void set_ts_info(uint64_t clock_start, uint32_t clock_rate, uint32_t rtp_ts_start);
199 
200  /* Alternate way to get RTCP packets is to install a hook for them. So instead of
201  * polling an RTCP packet, user can install a function that is called when
202  * a specific RTCP packet is received. */
203  rtp_error_t install_sender_hook(void (*hook)(uvgrtp::frame::rtcp_sender_report *));
204  rtp_error_t install_receiver_hook(void (*hook)(uvgrtp::frame::rtcp_receiver_report *));
205  rtp_error_t install_sdes_hook(void (*hook)(uvgrtp::frame::rtcp_sdes_packet *));
206  rtp_error_t install_app_hook(void (*hook)(uvgrtp::frame::rtcp_app_packet *));
207 
209  /* Update RTCP-related sender statistics */
210  rtp_error_t update_sender_stats(size_t pkt_size);
211 
212  /* Update RTCP-related receiver statistics */
213  static rtp_error_t recv_packet_handler(void *arg, int flags, frame::rtp_frame **out);
214 
215  /* Update RTCP-related sender statistics */
216  static rtp_error_t send_packet_handler_vec(void *arg, uvgrtp::buf_vec& buffers);
218 
219  private:
220  static void rtcp_runner(rtcp *rtcp);
221 
222  /* when we start the RTCP instance, we don't know what the SSRC of the remote is
223  * when an RTP packet is received, we must check if we've already received a packet
224  * from this sender and if not, create new entry to receiver_stats_ map */
225  bool is_participant(uint32_t ssrc);
226 
227  /* When we receive an RTP or RTCP packet, we need to check the source address and see if it's
228  * the same address where we've received packets before.
229  *
230  * If the address is new, it means we have detected an SSRC collision and the paket should
231  * be dropped We also need to check whether this SSRC matches with our own SSRC and if it does
232  * we need to send RTCP BYE and rejoin to the session */
233  bool collision_detected(uint32_t ssrc, sockaddr_in& src_addr);
234 
235  /* Move participant from initial_peers_ to participants_ */
236  rtp_error_t add_participant(uint32_t ssrc);
237 
238  /* We've got a message from new source (the SSRC of the frame is not known to us)
239  * Initialize statistics for the peer and move it to participants_ */
240  rtp_error_t init_new_participant(uvgrtp::frame::rtp_frame *frame);
241 
242  /* Initialize the RTP Sequence related stuff of peer
243  * This function assumes that the peer already exists in the participants_ map */
244  rtp_error_t init_participant_seq(uint32_t ssrc, uint16_t base_seq);
245 
246  /* Update the SSRC's sequence related data in participants_ map
247  *
248  * Return RTP_OK if the received packet was OK
249  * Return RTP_GENERIC_ERROR if it wasn't and
250  * packet-related statistics should not be updated */
251  rtp_error_t update_participant_seq(uint32_t ssrc, uint16_t seq);
252 
253  /* Update the RTCP bandwidth variables
254  *
255  * "pkt_size" tells how much rtcp_byte_count_
256  * should be increased before calculating the new average */
257  void update_rtcp_bandwidth(size_t pkt_size);
258 
259  /* Functions for generating different kinds of reports.
260  * These functions will both generate the report and send it
261  *
262  * Return RTP_OK on success and RTP_ERROR on error */
263  rtp_error_t generate_sender_report();
264  rtp_error_t generate_receiver_report();
265 
266  /* Because struct statistics contains uvgRTP clock object we cannot
267  * zero it out without compiler complaining about it so all the fields
268  * must be set to zero manually */
269  void zero_stats(uvgrtp::rtcp_statistics *stats);
270 
271  /* Pointer to RTP context from which clock rate etc. info is collected and which is
272  * used to change SSRC if a collision is detected */
273  uvgrtp::rtp *rtp_;
274 
275  /* Secure RTCP context */
276  uvgrtp::srtcp *srtcp_;
277 
278  /* RTP context flags */
279  int flags_;
280 
281  /* are we a sender or a receiver */
282  int our_role_;
283 
284  /* TODO: time_t?? */
285  size_t tp_; /* the last time an RTCP packet was transmitted */
286  size_t tc_; /* the current time */
287  size_t tn_; /* the next scheduled transmission time of an RTCP packet */
288  size_t pmembers_; /* the estimated number of session members at the time tn was last recomputed */
289  size_t members_; /* the most current estimate for the number of session members */
290  size_t senders_; /* the most current estimate for the number of senders in the session */
291 
292  /* The target RTCP bandwidth, i.e., the total bandwidth
293  * that will be used for RTCP packets by all members of this session,
294  * in octets per second. This will be a specified fraction of the
295  * "session bandwidth" parameter supplied to the application at startup. */
296  size_t rtcp_bandwidth_;
297 
298  /* Flag that is true if the application has sent data since
299  * the 2nd previous RTCP report was transmitted. */
300  bool we_sent_;
301 
302  /* The average compound RTCP packet size, in octets,
303  * over all RTCP packets sent and received by this participant. The
304  * size includes lower-layer transport and network protocol headers
305  * (e.g., UDP and IP) as explained in Section 6.2 */
306  size_t avg_rtcp_pkt_pize_;
307 
308  /* Number of RTCP packets and bytes sent and received by this participant */
309  size_t rtcp_pkt_count_;
310  size_t rtcp_byte_count_;
311 
312  /* Number of RTCP packets sent */
313  size_t rtcp_pkt_sent_count_;
314 
315  /* Flag that is true if the application has not yet sent an RTCP packet. */
316  bool initial_;
317 
318  /* Copy of our own current SSRC */
319  uint32_t ssrc_;
320 
321  /* NTP timestamp associated with initial RTP timestamp (aka t = 0) */
322  uint64_t clock_start_;
323 
324  /* Clock rate of the media ie. how fast does the time increase */
325  uint32_t clock_rate_;
326 
327  /* The first value of RTP timestamp (aka t = 0) */
328  uint32_t rtp_ts_start_;
329 
330  std::map<uint32_t, rtcp_participant *> participants_;
331  size_t num_receivers_;
332 
333  /* statistics for RTCP Sender and Receiver Reports */
334  struct rtcp_statistics our_stats;
335 
336  /* If we expect frames from remote but haven't received anything from remote yet,
337  * the participant resides in this vector until he's moved to participants_ */
338  std::vector<rtcp_participant *> initial_participants_;
339 
340  /* Vector of sockets the RTCP runner is listening to
341  *
342  * The socket are also stored here (in addition to participants_ map) so they're easier
343  * to pass to poll when RTCP runner is listening to incoming packets */
344  std::vector<uvgrtp::socket> sockets_;
345 
346  void (*sender_hook_)(uvgrtp::frame::rtcp_sender_report *);
347  void (*receiver_hook_)(uvgrtp::frame::rtcp_receiver_report *);
348  void (*sdes_hook_)(uvgrtp::frame::rtcp_sdes_packet *);
349  void (*app_hook_)(uvgrtp::frame::rtcp_app_packet *);
350  };
351 };
352 
353 namespace uvg_rtp = uvgrtp;
Definition: rtcp.hh:74
void set_ts_info(uint64_t clock_start, uint32_t clock_rate, uint32_t rtp_ts_start)
Provide timestamping information for RTCP.