1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cast/streaming/receiver_packet_router.h"
6 
7 #include <algorithm>
8 
9 #include "cast/streaming/packet_util.h"
10 #include "cast/streaming/receiver.h"
11 #include "util/osp_logging.h"
12 #include "util/stringprintf.h"
13 
14 namespace openscreen {
15 namespace cast {
16 
ReceiverPacketRouter(Environment * environment)17 ReceiverPacketRouter::ReceiverPacketRouter(Environment* environment)
18     : environment_(environment) {
19   OSP_DCHECK(environment_);
20 }
21 
~ReceiverPacketRouter()22 ReceiverPacketRouter::~ReceiverPacketRouter() {
23   OSP_DCHECK(receivers_.empty());
24 }
25 
OnReceiverCreated(Ssrc sender_ssrc,Receiver * receiver)26 void ReceiverPacketRouter::OnReceiverCreated(Ssrc sender_ssrc,
27                                              Receiver* receiver) {
28   OSP_DCHECK(receivers_.find(sender_ssrc) == receivers_.end());
29   receivers_.emplace_back(sender_ssrc, receiver);
30 
31   // If there were no Receiver instances before, resume receiving packets for
32   // dispatch. Reset/Clear the remote endpoint, in preparation for later setting
33   // it to the source of the first packet received.
34   if (receivers_.size() == 1) {
35     environment_->set_remote_endpoint(IPEndpoint{});
36     environment_->ConsumeIncomingPackets(this);
37   }
38 }
39 
OnReceiverDestroyed(Ssrc sender_ssrc)40 void ReceiverPacketRouter::OnReceiverDestroyed(Ssrc sender_ssrc) {
41   receivers_.erase_key(sender_ssrc);
42   // If there are no longer any Receivers, suspend receiving packets.
43   if (receivers_.empty()) {
44     environment_->DropIncomingPackets();
45   }
46 }
47 
SendRtcpPacket(absl::Span<const uint8_t> packet)48 void ReceiverPacketRouter::SendRtcpPacket(absl::Span<const uint8_t> packet) {
49   OSP_DCHECK(InspectPacketForRouting(packet).first == ApparentPacketType::RTCP);
50 
51   // Do not proceed until the remote endpoint is known. See OnReceivedPacket().
52   if (environment_->remote_endpoint().port == 0) {
53     return;
54   }
55 
56   environment_->SendPacket(packet);
57 }
58 
OnReceivedPacket(const IPEndpoint & source,Clock::time_point arrival_time,std::vector<uint8_t> packet)59 void ReceiverPacketRouter::OnReceivedPacket(const IPEndpoint& source,
60                                             Clock::time_point arrival_time,
61                                             std::vector<uint8_t> packet) {
62   OSP_DCHECK_NE(source.port, uint16_t{0});
63 
64   // If the sender endpoint is known, ignore any packet that did not come from
65   // that same endpoint.
66   if (environment_->remote_endpoint().port != 0) {
67     if (source != environment_->remote_endpoint()) {
68       return;
69     }
70   }
71 
72   const std::pair<ApparentPacketType, Ssrc> seems_like =
73       InspectPacketForRouting(packet);
74   if (seems_like.first == ApparentPacketType::UNKNOWN) {
75     constexpr int kMaxPartiaHexDumpSize = 96;
76     OSP_LOG_WARN << "UNKNOWN packet of " << packet.size()
77                  << " bytes. Partial hex dump: "
78                  << HexEncode(absl::Span<const uint8_t>(packet).subspan(
79                         0, kMaxPartiaHexDumpSize));
80     return;
81   }
82   auto it = receivers_.find(seems_like.second);
83   if (it == receivers_.end()) {
84     return;
85   }
86   // At this point, a valid packet has been matched with a receiver. Lock-in
87   // the remote endpoint as the |source| of this |packet| so that only packets
88   // from the same source are permitted from here onwards.
89   if (environment_->remote_endpoint().port == 0) {
90     environment_->set_remote_endpoint(source);
91   }
92 
93   if (seems_like.first == ApparentPacketType::RTP) {
94     it->second->OnReceivedRtpPacket(arrival_time, std::move(packet));
95   } else if (seems_like.first == ApparentPacketType::RTCP) {
96     it->second->OnReceivedRtcpPacket(arrival_time, std::move(packet));
97   }
98 }
99 
100 }  // namespace cast
101 }  // namespace openscreen
102