1 /* 2 * Copyright 2017 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 #ifndef P2P_BASE_FAKE_PACKET_TRANSPORT_H_ 12 #define P2P_BASE_FAKE_PACKET_TRANSPORT_H_ 13 14 #include <map> 15 #include <string> 16 17 #include "p2p/base/packet_transport_internal.h" 18 #include "rtc_base/async_invoker.h" 19 #include "rtc_base/copy_on_write_buffer.h" 20 21 namespace rtc { 22 23 // Used to simulate a packet-based transport. 24 class FakePacketTransport : public PacketTransportInternal { 25 public: FakePacketTransport(const std::string & transport_name)26 explicit FakePacketTransport(const std::string& transport_name) 27 : transport_name_(transport_name) {} ~FakePacketTransport()28 ~FakePacketTransport() override { 29 if (dest_ && dest_->dest_ == this) { 30 dest_->dest_ = nullptr; 31 } 32 } 33 34 // If async, will send packets by "Post"-ing to message queue instead of 35 // synchronously "Send"-ing. SetAsync(bool async)36 void SetAsync(bool async) { async_ = async; } SetAsyncDelay(int delay_ms)37 void SetAsyncDelay(int delay_ms) { async_delay_ms_ = delay_ms; } 38 39 // SetWritable, SetReceiving and SetDestination are the main methods that can 40 // be used for testing, to simulate connectivity or lack thereof. SetWritable(bool writable)41 void SetWritable(bool writable) { set_writable(writable); } SetReceiving(bool receiving)42 void SetReceiving(bool receiving) { set_receiving(receiving); } 43 44 // Simulates the two transports connecting to each other. 45 // If |asymmetric| is true this method only affects this FakePacketTransport. 46 // If false, it affects |dest| as well. SetDestination(FakePacketTransport * dest,bool asymmetric)47 void SetDestination(FakePacketTransport* dest, bool asymmetric) { 48 if (dest) { 49 dest_ = dest; 50 set_writable(true); 51 if (!asymmetric) { 52 dest->SetDestination(this, true); 53 } 54 } else { 55 // Simulates loss of connectivity, by asymmetrically forgetting dest_. 56 dest_ = nullptr; 57 set_writable(false); 58 } 59 } 60 61 // Fake PacketTransportInternal implementation. transport_name()62 const std::string& transport_name() const override { return transport_name_; } writable()63 bool writable() const override { return writable_; } receiving()64 bool receiving() const override { return receiving_; } SendPacket(const char * data,size_t len,const PacketOptions & options,int flags)65 int SendPacket(const char* data, 66 size_t len, 67 const PacketOptions& options, 68 int flags) override { 69 if (!dest_) { 70 return -1; 71 } 72 CopyOnWriteBuffer packet(data, len); 73 if (async_) { 74 invoker_.AsyncInvokeDelayed<void>( 75 RTC_FROM_HERE, Thread::Current(), 76 Bind(&FakePacketTransport::SendPacketInternal, this, packet), 77 async_delay_ms_); 78 } else { 79 SendPacketInternal(packet); 80 } 81 SentPacket sent_packet(options.packet_id, TimeMillis()); 82 SignalSentPacket(this, sent_packet); 83 return static_cast<int>(len); 84 } 85 SetOption(Socket::Option opt,int value)86 int SetOption(Socket::Option opt, int value) override { 87 options_[opt] = value; 88 return 0; 89 } 90 GetOption(Socket::Option opt,int * value)91 bool GetOption(Socket::Option opt, int* value) override { 92 auto it = options_.find(opt); 93 if (it == options_.end()) { 94 return false; 95 } 96 *value = it->second; 97 return true; 98 } 99 GetError()100 int GetError() override { return error_; } SetError(int error)101 void SetError(int error) { error_ = error; } 102 last_sent_packet()103 const CopyOnWriteBuffer* last_sent_packet() { return &last_sent_packet_; } 104 network_route()105 absl::optional<NetworkRoute> network_route() const override { 106 return network_route_; 107 } SetNetworkRoute(absl::optional<NetworkRoute> network_route)108 void SetNetworkRoute(absl::optional<NetworkRoute> network_route) { 109 network_route_ = network_route; 110 SignalNetworkRouteChanged(network_route); 111 } 112 113 private: set_writable(bool writable)114 void set_writable(bool writable) { 115 if (writable_ == writable) { 116 return; 117 } 118 writable_ = writable; 119 if (writable_) { 120 SignalReadyToSend(this); 121 } 122 SignalWritableState(this); 123 } 124 set_receiving(bool receiving)125 void set_receiving(bool receiving) { 126 if (receiving_ == receiving) { 127 return; 128 } 129 receiving_ = receiving; 130 SignalReceivingState(this); 131 } 132 SendPacketInternal(const CopyOnWriteBuffer & packet)133 void SendPacketInternal(const CopyOnWriteBuffer& packet) { 134 last_sent_packet_ = packet; 135 if (dest_) { 136 dest_->SignalReadPacket(dest_, packet.data<char>(), packet.size(), 137 TimeMicros(), 0); 138 } 139 } 140 141 CopyOnWriteBuffer last_sent_packet_; 142 AsyncInvoker invoker_; 143 std::string transport_name_; 144 FakePacketTransport* dest_ = nullptr; 145 bool async_ = false; 146 int async_delay_ms_ = 0; 147 bool writable_ = false; 148 bool receiving_ = false; 149 150 std::map<Socket::Option, int> options_; 151 int error_ = 0; 152 153 absl::optional<NetworkRoute> network_route_; 154 }; 155 156 } // namespace rtc 157 158 #endif // P2P_BASE_FAKE_PACKET_TRANSPORT_H_ 159