tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

dcsctp_transport_unittest.cc (11721B)


      1 /*
      2 *  Copyright 2022 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "media/sctp/dcsctp_transport.h"
     12 
     13 #include <memory>
     14 #include <type_traits>
     15 #include <utility>
     16 
     17 #include "api/environment/environment.h"
     18 #include "api/environment/environment_factory.h"
     19 #include "api/priority.h"
     20 #include "api/rtc_error.h"
     21 #include "api/transport/data_channel_transport_interface.h"
     22 #include "net/dcsctp/public/dcsctp_message.h"
     23 #include "net/dcsctp/public/dcsctp_options.h"
     24 #include "net/dcsctp/public/dcsctp_socket.h"
     25 #include "net/dcsctp/public/mock_dcsctp_socket.h"
     26 #include "net/dcsctp/public/mock_dcsctp_socket_factory.h"
     27 #include "net/dcsctp/public/types.h"
     28 #include "p2p/dtls/fake_dtls_transport.h"
     29 #include "rtc_base/copy_on_write_buffer.h"
     30 #include "rtc_base/thread.h"
     31 #include "system_wrappers/include/clock.h"
     32 #include "test/gmock.h"
     33 #include "test/gtest.h"
     34 
     35 using ::testing::_;
     36 using ::testing::ByMove;
     37 using ::testing::ElementsAre;
     38 using ::testing::InSequence;
     39 using ::testing::Invoke;
     40 using ::testing::NiceMock;
     41 using ::testing::Return;
     42 using ::testing::ReturnPointee;
     43 
     44 namespace webrtc {
     45 
     46 namespace {
     47 
     48 constexpr char kTransportName[] = "transport";
     49 constexpr int kComponent = 77;
     50 
     51 const PriorityValue kDefaultPriority = PriorityValue(Priority::kLow);
     52 
     53 class MockDataChannelSink : public DataChannelSink {
     54 public:
     55  MOCK_METHOD(void, OnConnected, ());
     56 
     57  // DataChannelSink
     58  MOCK_METHOD(void,
     59              OnDataReceived,
     60              (int, DataMessageType, const CopyOnWriteBuffer&));
     61  MOCK_METHOD(void, OnChannelClosing, (int));
     62  MOCK_METHOD(void, OnChannelClosed, (int));
     63  MOCK_METHOD(void, OnReadyToSend, ());
     64  MOCK_METHOD(void, OnTransportClosed, (RTCError));
     65  MOCK_METHOD(void, OnBufferedAmountLow, (int channel_id), (override));
     66 };
     67 
     68 static_assert(!std::is_abstract_v<MockDataChannelSink>);
     69 
     70 class Peer {
     71 public:
     72  Peer()
     73      : fake_dtls_transport_(kTransportName, kComponent),
     74        simulated_clock_(1000),
     75        env_(CreateEnvironment(&simulated_clock_)) {
     76    auto socket_ptr = std::make_unique<dcsctp::MockDcSctpSocket>();
     77    socket_ = socket_ptr.get();
     78 
     79    auto mock_dcsctp_socket_factory =
     80        std::make_unique<dcsctp::MockDcSctpSocketFactory>();
     81    EXPECT_CALL(*mock_dcsctp_socket_factory, Create)
     82        .Times(1)
     83        .WillOnce(Return(ByMove(std::move(socket_ptr))));
     84 
     85    sctp_transport_ = std::make_unique<DcSctpTransport>(
     86        env_, Thread::Current(), &fake_dtls_transport_,
     87        std::move(mock_dcsctp_socket_factory));
     88    sctp_transport_->SetDataChannelSink(&sink_);
     89    sctp_transport_->SetOnConnectedCallback([this]() { sink_.OnConnected(); });
     90  }
     91 
     92  FakeDtlsTransport fake_dtls_transport_;
     93  SimulatedClock simulated_clock_;
     94  Environment env_;
     95  dcsctp::MockDcSctpSocket* socket_;
     96  std::unique_ptr<DcSctpTransport> sctp_transport_;
     97  NiceMock<MockDataChannelSink> sink_;
     98 };
     99 }  // namespace
    100 
    101 TEST(DcSctpTransportTest, OpenSequence) {
    102  AutoThread main_thread;
    103  Peer peer_a;
    104  peer_a.fake_dtls_transport_.SetWritable(true);
    105 
    106  EXPECT_CALL(*peer_a.socket_, Connect)
    107      .Times(1)
    108      .WillOnce(Invoke(peer_a.sctp_transport_.get(),
    109                       &dcsctp::DcSctpSocketCallbacks::OnConnected));
    110  EXPECT_CALL(peer_a.sink_, OnReadyToSend);
    111  EXPECT_CALL(peer_a.sink_, OnConnected);
    112  peer_a.sctp_transport_->Start({.local_port = 5000,
    113                                 .remote_port = 5000,
    114                                 .max_message_size = 256 * 1024});
    115 }
    116 
    117 // Tests that the close sequence invoked from one end results in the stream to
    118 // be reset from both ends and all the proper signals are sent.
    119 TEST(DcSctpTransportTest, CloseSequence) {
    120  AutoThread main_thread;
    121  Peer peer_a;
    122  Peer peer_b;
    123  peer_a.fake_dtls_transport_.SetDestination(&peer_b.fake_dtls_transport_,
    124                                             false);
    125  {
    126    InSequence sequence;
    127 
    128    EXPECT_CALL(
    129        *peer_a.socket_,
    130        SetStreamPriority(dcsctp::StreamID(1),
    131                          dcsctp::StreamPriority(kDefaultPriority.value())));
    132    EXPECT_CALL(*peer_a.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
    133        .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
    134 
    135    EXPECT_CALL(*peer_b.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
    136        .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
    137 
    138    EXPECT_CALL(peer_a.sink_, OnChannelClosing(1)).Times(0);
    139    EXPECT_CALL(peer_b.sink_, OnChannelClosing(1));
    140    EXPECT_CALL(peer_a.sink_, OnChannelClosed(1));
    141    EXPECT_CALL(peer_b.sink_, OnChannelClosed(1));
    142  }
    143 
    144  peer_a.sctp_transport_->Start({.local_port = 5000,
    145                                 .remote_port = 5000,
    146                                 .max_message_size = 256 * 1024});
    147  peer_b.sctp_transport_->Start({.local_port = 5000,
    148                                 .remote_port = 5000,
    149                                 .max_message_size = 256 * 1024});
    150  peer_a.sctp_transport_->OpenStream(1, kDefaultPriority);
    151  peer_b.sctp_transport_->OpenStream(1, kDefaultPriority);
    152  peer_a.sctp_transport_->ResetStream(1);
    153 
    154  // Simulate the callbacks from the stream resets
    155  dcsctp::StreamID streams[1] = {dcsctp::StreamID(1)};
    156  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
    157      ->OnStreamsResetPerformed(streams);
    158  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
    159      ->OnIncomingStreamsReset(streams);
    160  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
    161      ->OnIncomingStreamsReset(streams);
    162  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
    163      ->OnStreamsResetPerformed(streams);
    164 }
    165 
    166 // Tests that the close sequence initiated from both peers at the same time
    167 // terminates properly. Both peers will think they initiated it, so no
    168 // OnClosingProcedureStartedRemotely should be called.
    169 TEST(DcSctpTransportTest, CloseSequenceSimultaneous) {
    170  AutoThread main_thread;
    171  Peer peer_a;
    172  Peer peer_b;
    173  peer_a.fake_dtls_transport_.SetDestination(&peer_b.fake_dtls_transport_,
    174                                             false);
    175  {
    176    InSequence sequence;
    177 
    178    EXPECT_CALL(*peer_a.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
    179        .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
    180 
    181    EXPECT_CALL(*peer_b.socket_, ResetStreams(ElementsAre(dcsctp::StreamID(1))))
    182        .WillOnce(Return(dcsctp::ResetStreamsStatus::kPerformed));
    183 
    184    EXPECT_CALL(peer_a.sink_, OnChannelClosing(1)).Times(0);
    185    EXPECT_CALL(peer_b.sink_, OnChannelClosing(1)).Times(0);
    186    EXPECT_CALL(peer_a.sink_, OnChannelClosed(1));
    187    EXPECT_CALL(peer_b.sink_, OnChannelClosed(1));
    188  }
    189 
    190  peer_a.sctp_transport_->Start({.local_port = 5000,
    191                                 .remote_port = 5000,
    192                                 .max_message_size = 256 * 1024});
    193  peer_b.sctp_transport_->Start({.local_port = 5000,
    194                                 .remote_port = 5000,
    195                                 .max_message_size = 256 * 1024});
    196  peer_a.sctp_transport_->OpenStream(1, kDefaultPriority);
    197  peer_b.sctp_transport_->OpenStream(1, kDefaultPriority);
    198  peer_a.sctp_transport_->ResetStream(1);
    199  peer_b.sctp_transport_->ResetStream(1);
    200 
    201  // Simulate the callbacks from the stream resets
    202  dcsctp::StreamID streams[1] = {dcsctp::StreamID(1)};
    203  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
    204      ->OnStreamsResetPerformed(streams);
    205  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
    206      ->OnStreamsResetPerformed(streams);
    207  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
    208      ->OnIncomingStreamsReset(streams);
    209  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_b.sctp_transport_.get())
    210      ->OnIncomingStreamsReset(streams);
    211 }
    212 
    213 TEST(DcSctpTransportTest, SetStreamPriority) {
    214  AutoThread main_thread;
    215  Peer peer_a;
    216 
    217  {
    218    InSequence sequence;
    219 
    220    EXPECT_CALL(
    221        *peer_a.socket_,
    222        SetStreamPriority(dcsctp::StreamID(1), dcsctp::StreamPriority(1337)));
    223    EXPECT_CALL(
    224        *peer_a.socket_,
    225        SetStreamPriority(dcsctp::StreamID(2), dcsctp::StreamPriority(3141)));
    226  }
    227 
    228  EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(0);
    229 
    230  peer_a.sctp_transport_->OpenStream(1, PriorityValue(1337));
    231  peer_a.sctp_transport_->Start({.local_port = 5000,
    232                                 .remote_port = 5000,
    233                                 .max_message_size = 256 * 1024});
    234  peer_a.sctp_transport_->OpenStream(2, PriorityValue(3141));
    235 }
    236 
    237 TEST(DcSctpTransportTest, DiscardMessageClosedChannel) {
    238  AutoThread main_thread;
    239  Peer peer_a;
    240 
    241  EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(0);
    242 
    243  peer_a.sctp_transport_->Start({.local_port = 5000,
    244                                 .remote_port = 5000,
    245                                 .max_message_size = 256 * 1024});
    246 
    247  SendDataParams params;
    248  CopyOnWriteBuffer payload;
    249  EXPECT_EQ(peer_a.sctp_transport_->SendData(1, params, payload).type(),
    250            RTCErrorType::INVALID_STATE);
    251 }
    252 
    253 TEST(DcSctpTransportTest, DiscardMessageClosingChannel) {
    254  AutoThread main_thread;
    255  Peer peer_a;
    256 
    257  EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(0);
    258 
    259  peer_a.sctp_transport_->OpenStream(1, kDefaultPriority);
    260  peer_a.sctp_transport_->Start({.local_port = 5000,
    261                                 .remote_port = 5000,
    262                                 .max_message_size = 256 * 1024});
    263  peer_a.sctp_transport_->ResetStream(1);
    264 
    265  SendDataParams params;
    266  CopyOnWriteBuffer payload;
    267  EXPECT_EQ(peer_a.sctp_transport_->SendData(1, params, payload).type(),
    268            RTCErrorType::INVALID_STATE);
    269 }
    270 
    271 TEST(DcSctpTransportTest, SendDataOpenChannel) {
    272  AutoThread main_thread;
    273  Peer peer_a;
    274  dcsctp::DcSctpOptions options;
    275 
    276  EXPECT_CALL(*peer_a.socket_, Send(_, _)).Times(1);
    277  EXPECT_CALL(*peer_a.socket_, options()).WillOnce(ReturnPointee(&options));
    278 
    279  peer_a.sctp_transport_->OpenStream(1, kDefaultPriority);
    280  peer_a.sctp_transport_->Start({.local_port = 5000,
    281                                 .remote_port = 5000,
    282                                 .max_message_size = 256 * 1024});
    283 
    284  SendDataParams params;
    285  CopyOnWriteBuffer payload;
    286  EXPECT_TRUE(peer_a.sctp_transport_->SendData(1, params, payload).ok());
    287 }
    288 
    289 TEST(DcSctpTransportTest, DeliversMessage) {
    290  AutoThread main_thread;
    291  Peer peer_a;
    292 
    293  EXPECT_CALL(peer_a.sink_, OnDataReceived(1, DataMessageType::kBinary, _))
    294      .Times(1);
    295 
    296  peer_a.sctp_transport_->OpenStream(1, kDefaultPriority);
    297  peer_a.sctp_transport_->Start({.local_port = 5000,
    298                                 .remote_port = 5000,
    299                                 .max_message_size = 256 * 1024});
    300 
    301  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
    302      ->OnMessageReceived(
    303          dcsctp::DcSctpMessage(dcsctp::StreamID(1), dcsctp::PPID(53), {0}));
    304 }
    305 
    306 TEST(DcSctpTransportTest, DropMessageWithUnknownPpid) {
    307  AutoThread main_thread;
    308  Peer peer_a;
    309 
    310  EXPECT_CALL(peer_a.sink_, OnDataReceived(_, _, _)).Times(0);
    311 
    312  peer_a.sctp_transport_->OpenStream(1, kDefaultPriority);
    313  peer_a.sctp_transport_->Start({.local_port = 5000,
    314                                 .remote_port = 5000,
    315                                 .max_message_size = 256 * 1024});
    316 
    317  static_cast<dcsctp::DcSctpSocketCallbacks*>(peer_a.sctp_transport_.get())
    318      ->OnMessageReceived(
    319          dcsctp::DcSctpMessage(dcsctp::StreamID(1), dcsctp::PPID(1337), {0}));
    320 }
    321 }  // namespace webrtc