/* * Copyright 2025 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "p2p/test/test_port.h" #include #include #include #include #include "absl/strings/string_view.h" #include "api/array_view.h" #include "api/candidate.h" #include "api/transport/stun.h" #include "p2p/base/connection.h" #include "p2p/base/p2p_constants.h" #include "p2p/base/port.h" #include "rtc_base/async_packet_socket.h" #include "rtc_base/buffer.h" #include "rtc_base/byte_buffer.h" #include "rtc_base/net_helper.h" #include "rtc_base/network.h" #include "rtc_base/network/sent_packet.h" #include "rtc_base/socket.h" #include "rtc_base/socket_address.h" namespace webrtc { TestPort::TestPort(const PortParametersRef& args, uint16_t min_port, uint16_t max_port) : Port(args, IceCandidateType::kHost, min_port, max_port) {} TestPort::~TestPort() = default; ArrayView TestPort::last_stun_buf() { if (!last_stun_buf_) return ArrayView(); return *last_stun_buf_; } IceMessage* TestPort::last_stun_msg() { return last_stun_msg_.get(); } int TestPort::last_stun_error_code() { int code = 0; if (last_stun_msg_) { const StunErrorCodeAttribute* error_attr = last_stun_msg_->GetErrorCode(); if (error_attr) { code = error_attr->code(); } } return code; } void TestPort::PrepareAddress() { // Act as if the socket was bound to the best IP on the network, to the // first port in the allowed range. SocketAddress addr(Network()->GetBestIP(), min_port()); AddAddress(addr, addr, SocketAddress(), "udp", "", "", type(), ICE_TYPE_PREFERENCE_HOST, 0, "", true); } bool TestPort::SupportsProtocol(absl::string_view /* protocol */) const { return true; } ProtocolType TestPort::GetProtocol() const { return PROTO_UDP; } void TestPort::AddCandidateAddress(const SocketAddress& addr) { AddAddress(addr, addr, SocketAddress(), "udp", "", "", type(), type_preference_, 0, "", false); } void TestPort::AddCandidateAddress(const SocketAddress& addr, const SocketAddress& base_address, IceCandidateType type, int type_preference, bool final_candidate) { AddAddress(addr, base_address, SocketAddress(), "udp", "", "", type, type_preference, 0, "", final_candidate); } Connection* TestPort::CreateConnection(const Candidate& remote_candidate, CandidateOrigin /* origin */) { Connection* conn = new ProxyConnection(env(), NewWeakPtr(), 0, remote_candidate); AddOrReplaceConnection(conn); // Set use-candidate attribute flag as this will add USE-CANDIDATE attribute // in STUN binding requests. conn->set_use_candidate_attr(true); return conn; } int TestPort::SendTo(const void* data, size_t size, const SocketAddress& /* addr */, const AsyncSocketPacketOptions& /* options */, bool payload) { if (!payload) { auto msg = std::make_unique(); auto buf = std::make_unique>( static_cast(data), size); ByteBufferReader read_buf(*buf); if (!msg->Read(&read_buf)) { return -1; } last_stun_buf_ = std::move(buf); last_stun_msg_ = std::move(msg); } return static_cast(size); } int TestPort::SetOption(Socket::Option /* opt */, int /* value */) { return 0; } int TestPort::GetOption(Socket::Option opt, int* value) { return -1; } int TestPort::GetError() { return 0; } void TestPort::Reset() { last_stun_buf_.reset(); last_stun_msg_.reset(); } void TestPort::set_type_preference(int type_preference) { type_preference_ = type_preference; } void TestPort::OnSentPacket(AsyncPacketSocket* socket, const SentPacketInfo& sent_packet) { NotifySentPacket(sent_packet); } } // namespace webrtc