1/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/session/media/bundlefilter.h"
29#include "webrtc/base/gunit.h"
30
31using cricket::StreamParams;
32
33static const int kSsrc1 = 0x1111;
34static const int kSsrc2 = 0x2222;
35static const int kSsrc3 = 0x3333;
36static const int kPayloadType1 = 0x11;
37static const int kPayloadType2 = 0x22;
38static const int kPayloadType3 = 0x33;
39
40// SSRC = 0x1111, Payload type = 0x11
41static const unsigned char kRtpPacketPt1Ssrc1[] = {
42    0x80, kPayloadType1, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
43    0x11,
44};
45
46// SSRC = 0x2222, Payload type = 0x22
47static const unsigned char kRtpPacketPt2Ssrc2[] = {
48    0x80, 0x80 + kPayloadType2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49    0x22, 0x22,
50};
51
52// SSRC = 0x2222, Payload type = 0x33
53static const unsigned char kRtpPacketPt3Ssrc2[] = {
54    0x80, kPayloadType3, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22,
55    0x22,
56};
57
58// PT = 200 = SR, len = 28, SSRC of sender = 0x0001
59// NTP TS = 0, RTP TS = 0, packet count = 0
60static const unsigned char kRtcpPacketSrSsrc01[] = {
61    0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01,
62    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64    0x00, 0x00, 0x00, 0x00,
65};
66
67// PT = 200 = SR, len = 28, SSRC of sender = 0x2222
68// NTP TS = 0, RTP TS = 0, packet count = 0
69static const unsigned char kRtcpPacketSrSsrc2[] = {
70    0x80, 0xC8, 0x00, 0x1B, 0x00, 0x00, 0x22, 0x22,
71    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73    0x00, 0x00, 0x00, 0x00,
74};
75
76// First packet - SR = PT = 200, len = 0, SSRC of sender = 0x1111
77// NTP TS = 0, RTP TS = 0, packet count = 0
78// second packet - SDES = PT =  202, count = 0, SSRC = 0x1111, cname len = 0
79static const unsigned char kRtcpPacketCompoundSrSdesSsrc1[] = {
80    0x80, 0xC8, 0x00, 0x01, 0x00, 0x00, 0x11, 0x11,
81    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83    0x00, 0x00, 0x00, 0x00,
84    0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x01, 0x00,
85};
86
87// SDES = PT =  202, count = 0, SSRC = 0x2222, cname len = 0
88static const unsigned char kRtcpPacketSdesSsrc2[] = {
89    0x81, 0xCA, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x01, 0x00,
90};
91
92// Packet has only mandatory fixed RTCP header
93static const unsigned char kRtcpPacketFixedHeaderOnly[] = {
94    0x80, 0xC8, 0x00, 0x00,
95};
96
97// Small packet for SSRC demux.
98static const unsigned char kRtcpPacketTooSmall[] = {
99    0x80, 0xC8, 0x00, 0x00, 0x00, 0x00,
100};
101
102// PT = 206, FMT = 1, Sender SSRC  = 0x1111, Media SSRC = 0x1111
103// No FCI information is needed for PLI.
104static const unsigned char kRtcpPacketNonCompoundRtcpPliFeedback[] = {
105    0x81, 0xCE, 0x00, 0x0C, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x11, 0x11,
106};
107
108// An SCTP packet.
109static const unsigned char kSctpPacket[] = {
110    0x00, 0x01, 0x00, 0x01,
111    0xff, 0xff, 0xff, 0xff,
112    0x00, 0x00, 0x00, 0x00,
113    0x03, 0x00, 0x00, 0x04,
114    0x00, 0x00, 0x00, 0x00,
115};
116
117TEST(BundleFilterTest, AddRemoveStreamTest) {
118  cricket::BundleFilter bundle_filter;
119  EXPECT_FALSE(bundle_filter.HasStreams());
120  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
121  StreamParams stream2;
122  stream2.ssrcs.push_back(kSsrc2);
123  stream2.ssrcs.push_back(kSsrc3);
124  EXPECT_TRUE(bundle_filter.AddStream(stream2));
125
126  EXPECT_TRUE(bundle_filter.HasStreams());
127  EXPECT_TRUE(bundle_filter.FindStream(kSsrc1));
128  EXPECT_TRUE(bundle_filter.FindStream(kSsrc2));
129  EXPECT_TRUE(bundle_filter.FindStream(kSsrc3));
130  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc1));
131  EXPECT_FALSE(bundle_filter.FindStream(kSsrc1));
132  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc3));
133  EXPECT_FALSE(bundle_filter.RemoveStream(kSsrc2));  // Already removed.
134  EXPECT_FALSE(bundle_filter.HasStreams());
135}
136
137TEST(BundleFilterTest, RtpPacketTest) {
138  cricket::BundleFilter bundle_filter;
139  bundle_filter.AddPayloadType(kPayloadType1);
140  EXPECT_TRUE(bundle_filter.DemuxPacket(
141      reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1),
142      sizeof(kRtpPacketPt1Ssrc1), false));
143  bundle_filter.AddPayloadType(kPayloadType2);
144  EXPECT_TRUE(bundle_filter.DemuxPacket(
145      reinterpret_cast<const char*>(kRtpPacketPt2Ssrc2),
146      sizeof(kRtpPacketPt2Ssrc2), false));
147
148  // Payload type 0x33 is not added.
149  EXPECT_FALSE(bundle_filter.DemuxPacket(
150      reinterpret_cast<const char*>(kRtpPacketPt3Ssrc2),
151      sizeof(kRtpPacketPt3Ssrc2), false));
152  // Size is too small.
153  EXPECT_FALSE(bundle_filter.DemuxPacket(
154      reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1), 11, false));
155
156  bundle_filter.ClearAllPayloadTypes();
157  EXPECT_FALSE(bundle_filter.DemuxPacket(
158      reinterpret_cast<const char*>(kRtpPacketPt1Ssrc1),
159      sizeof(kRtpPacketPt1Ssrc1), false));
160  EXPECT_FALSE(bundle_filter.DemuxPacket(
161      reinterpret_cast<const char*>(kRtpPacketPt2Ssrc2),
162      sizeof(kRtpPacketPt2Ssrc2), false));
163}
164
165TEST(BundleFilterTest, RtcpPacketTest) {
166  cricket::BundleFilter bundle_filter;
167  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
168  EXPECT_TRUE(bundle_filter.DemuxPacket(
169      reinterpret_cast<const char*>(kRtcpPacketCompoundSrSdesSsrc1),
170      sizeof(kRtcpPacketCompoundSrSdesSsrc1), true));
171  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc2)));
172  EXPECT_TRUE(bundle_filter.DemuxPacket(
173      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
174      sizeof(kRtcpPacketSrSsrc2), true));
175  EXPECT_TRUE(bundle_filter.DemuxPacket(
176      reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2),
177      sizeof(kRtcpPacketSdesSsrc2), true));
178  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc2));
179  // RTCP Packets other than SR and RR are demuxed regardless of SSRC.
180  EXPECT_TRUE(bundle_filter.DemuxPacket(
181      reinterpret_cast<const char*>(kRtcpPacketSdesSsrc2),
182      sizeof(kRtcpPacketSdesSsrc2), true));
183  // RTCP Packets with 'special' SSRC 0x01 are demuxed also
184  EXPECT_TRUE(bundle_filter.DemuxPacket(
185      reinterpret_cast<const char*>(kRtcpPacketSrSsrc01),
186      sizeof(kRtcpPacketSrSsrc01), true));
187  EXPECT_FALSE(bundle_filter.DemuxPacket(
188      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
189      sizeof(kRtcpPacketSrSsrc2), true));
190  EXPECT_FALSE(bundle_filter.DemuxPacket(
191      reinterpret_cast<const char*>(kRtcpPacketFixedHeaderOnly),
192      sizeof(kRtcpPacketFixedHeaderOnly), true));
193  EXPECT_FALSE(bundle_filter.DemuxPacket(
194      reinterpret_cast<const char*>(kRtcpPacketTooSmall),
195      sizeof(kRtcpPacketTooSmall), true));
196  EXPECT_TRUE(bundle_filter.DemuxPacket(
197      reinterpret_cast<const char*>(kRtcpPacketNonCompoundRtcpPliFeedback),
198      sizeof(kRtcpPacketNonCompoundRtcpPliFeedback), true));
199  // If the streams_ is empty, rtcp packet passes through
200  EXPECT_TRUE(bundle_filter.RemoveStream(kSsrc1));
201  EXPECT_FALSE(bundle_filter.HasStreams());
202  EXPECT_TRUE(bundle_filter.DemuxPacket(
203      reinterpret_cast<const char*>(kRtcpPacketSrSsrc2),
204      sizeof(kRtcpPacketSrSsrc2), true));
205}
206
207TEST(BundleFilterTest, InvalidRtpPacket) {
208  cricket::BundleFilter bundle_filter;
209  EXPECT_TRUE(bundle_filter.AddStream(StreamParams::CreateLegacy(kSsrc1)));
210  EXPECT_FALSE(bundle_filter.DemuxPacket(
211      reinterpret_cast<const char*>(kSctpPacket),
212      sizeof(kSctpPacket), false));
213}
214