tor-browser

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

commit d0126d1340b8bb5cca506e999540c81d24aa4336
parent 50c999e25d8ee1b77bed801bc49339e6143f8b37
Author: Michael Froman <mfroman@mozilla.com>
Date:   Wed, 15 Oct 2025 11:16:22 -0500

Bug 1993083 - Vendor libwebrtc from 58733c5bd2

Upstream commit: https://webrtc.googlesource.com/src/+/58733c5bd2b86bfac68cdc31bb7527945518d251
    Remove PseudoTcp implementation from WebRTC

    The webrtc::PseudoTcp class was only used by Chromium's remoting/protocol/
    and has been moved there as of crrev.com/c/6760418.

    Bug: chromium:431990415
    Change-Id: I3a25bbf1d968017d7a65c41a3feae5ef6a91533b
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/402480
    Commit-Queue: Helmut Januschka <helmut@januschka.com>
    Reviewed-by: Harald Alvestrand <hta@webrtc.org>
    Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45242}

Diffstat:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/moz-patch-stack/s0103.patch | 2+-
Mthird_party/libwebrtc/p2p/BUILD.gn | 24+-----------------------
Dthird_party/libwebrtc/p2p/base/pseudo_tcp.cc | 1434-------------------------------------------------------------------------------
Dthird_party/libwebrtc/p2p/base/pseudo_tcp.h | 296-------------------------------------------------------------------------------
Dthird_party/libwebrtc/p2p/base/pseudo_tcp_unittest.cc | 907-------------------------------------------------------------------------------
Mthird_party/libwebrtc/test/DEPS | 3---
Mthird_party/libwebrtc/test/fuzzers/BUILD.gn | 19+++++--------------
Mthird_party/libwebrtc/test/fuzzers/corpora/README | 2--
Dthird_party/libwebrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc | 47-----------------------------------------------
10 files changed, 9 insertions(+), 2729 deletions(-)

diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor @@ -1,4 +1,4 @@ # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc -libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-15T16:15:08.237570+00:00. +libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-15T16:16:10.069554+00:00. # base of lastest vendoring -244e9693bb +58733c5bd2 diff --git a/third_party/libwebrtc/moz-patch-stack/s0103.patch b/third_party/libwebrtc/moz-patch-stack/s0103.patch @@ -782,7 +782,7 @@ index 33f4ee8624..edd3e02d77 100644 deps = [ ":google_test_runner_delegate" ] } diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn -index d8f0eba11f..eb25867dc9 100644 +index 6bdaf144fb..184f608d1b 100644 --- a/test/fuzzers/BUILD.gn +++ b/test/fuzzers/BUILD.gn @@ -6,7 +6,7 @@ diff --git a/third_party/libwebrtc/p2p/BUILD.gn b/third_party/libwebrtc/p2p/BUILD.gn @@ -638,7 +638,7 @@ rtc_library("port_interface") { "../api:candidate", "../api:field_trials_view", "../api:packet_socket_factory", - "../api/task_queue:task_queue", + "../api/task_queue", "../rtc_base:async_packet_socket", "../rtc_base:callback_list", "../rtc_base:dscp", @@ -652,26 +652,6 @@ rtc_library("port_interface") { ] } -rtc_library("pseudo_tcp") { - sources = [ - "base/pseudo_tcp.cc", - "base/pseudo_tcp.h", - ] - deps = [ - "../api:array_view", - "../rtc_base:byte_buffer", - "../rtc_base:byte_order", - "../rtc_base:checks", - "../rtc_base:logging", - "../rtc_base:macromagic", - "../rtc_base:safe_minmax", - "../rtc_base:socket", - "../rtc_base:timeutils", - "../rtc_base/synchronization:mutex", - "../rtc_base/system:rtc_export", - ] -} - rtc_library("regathering_controller") { sources = [ "base/regathering_controller.cc", @@ -1172,7 +1152,6 @@ if (rtc_include_tests) { "base/packet_transport_internal_unittest.cc", "base/port_allocator_unittest.cc", "base/port_unittest.cc", - "base/pseudo_tcp_unittest.cc", "base/regathering_controller_unittest.cc", "base/stun_dictionary_unittest.cc", "base/stun_port_unittest.cc", @@ -1219,7 +1198,6 @@ if (rtc_include_tests) { ":port", ":port_allocator", ":port_interface", - ":pseudo_tcp", ":regathering_controller", ":relay_port_factory_interface", ":stun_dictionary", diff --git a/third_party/libwebrtc/p2p/base/pseudo_tcp.cc b/third_party/libwebrtc/p2p/base/pseudo_tcp.cc @@ -1,1434 +0,0 @@ -/* - * Copyright 2004 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/base/pseudo_tcp.h" - -#include <algorithm> -#include <cerrno> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <memory> -#include <set> - -#include "api/array_view.h" -#include "rtc_base/byte_buffer.h" -#include "rtc_base/byte_order.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/numerics/safe_minmax.h" -#include "rtc_base/socket.h" -#include "rtc_base/synchronization/mutex.h" -#include "rtc_base/time_utils.h" - -// The following logging is for detailed (packet-level) analysis only. -#define _DBG_NONE 0 -#define _DBG_NORMAL 1 -#define _DBG_VERBOSE 2 -#define _DEBUGMSG _DBG_NONE - -namespace webrtc { - -////////////////////////////////////////////////////////////////////// -// Network Constants -////////////////////////////////////////////////////////////////////// - -// Standard MTUs -const uint16_t PACKET_MAXIMUMS[] = { - 65535, // Theoretical maximum, Hyperchannel - 32000, // Nothing - 17914, // 16Mb IBM Token Ring - 8166, // IEEE 802.4 - // 4464, // IEEE 802.5 (4Mb max) - 4352, // FDDI - // 2048, // Wideband Network - 2002, // IEEE 802.5 (4Mb recommended) - // 1536, // Expermental Ethernet Networks - // 1500, // Ethernet, Point-to-Point (default) - 1492, // IEEE 802.3 - 1006, // SLIP, ARPANET - // 576, // X.25 Networks - // 544, // DEC IP Portal - // 512, // NETBIOS - 508, // IEEE 802/Source-Rt Bridge, ARCNET - 296, // Point-to-Point (low delay) - // 68, // Official minimum - 0, // End of list marker -}; - -const uint32_t MAX_PACKET = 65535; -// Note: we removed lowest level because packet overhead was larger! -const uint32_t MIN_PACKET = 296; - -const uint32_t IP_HEADER_SIZE = 20; // (+ up to 40 bytes of options?) -const uint32_t UDP_HEADER_SIZE = 8; -// TODO(?): Make JINGLE_HEADER_SIZE transparent to this code? -const uint32_t JINGLE_HEADER_SIZE = 64; // when relay framing is in use - -// Default size for receive and send buffer. -const uint32_t DEFAULT_RCV_BUF_SIZE = 60 * 1024; -const uint32_t DEFAULT_SND_BUF_SIZE = 90 * 1024; - -////////////////////////////////////////////////////////////////////// -// Global Constants and Functions -////////////////////////////////////////////////////////////////////// -// -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 0 | Conversation Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 4 | Sequence Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 8 | Acknowledgment Number | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | | |U|A|P|R|S|F| | -// 12 | Control | |R|C|S|S|Y|I| Window | -// | | |G|K|H|T|N|N| | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 16 | Timestamp sending | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 20 | Timestamp receiving | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// 24 | data | -// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -////////////////////////////////////////////////////////////////////// - -#define PSEUDO_KEEPALIVE 0 - -const uint32_t HEADER_SIZE = 24; -const uint32_t PACKET_OVERHEAD = - HEADER_SIZE + UDP_HEADER_SIZE + IP_HEADER_SIZE + JINGLE_HEADER_SIZE; - -const uint32_t MIN_RTO = - 250; // 250 ms (RFC1122, Sec 4.2.3.1 "fractions of a second") -const uint32_t DEF_RTO = 3000; // 3 seconds (RFC1122, Sec 4.2.3.1) -const uint32_t MAX_RTO = 60000; // 60 seconds -const uint32_t DEF_ACK_DELAY = 100; // 100 milliseconds - -const uint8_t FLAG_CTL = 0x02; -const uint8_t FLAG_RST = 0x04; - -const uint8_t CTL_CONNECT = 0; - -// TCP options. -const uint8_t TCP_OPT_EOL = 0; // End of list. -const uint8_t TCP_OPT_NOOP = 1; // No-op. -const uint8_t TCP_OPT_MSS = 2; // Maximum segment size. -const uint8_t TCP_OPT_WND_SCALE = 3; // Window scale factor. - -const long DEFAULT_TIMEOUT = - 4000; // If there are no pending clocks, wake up every 4 seconds -const long CLOSED_TIMEOUT = - 60 * 1000; // If the connection is closed, once per minute - -#if PSEUDO_KEEPALIVE -// !?! Rethink these times -const uint32_t IDLE_PING = - 20 * - 1000; // 20 seconds (note: WinXP SP2 firewall udp timeout is 90 seconds) -const uint32_t IDLE_TIMEOUT = 90 * 1000; // 90 seconds; -#endif // PSEUDO_KEEPALIVE - -////////////////////////////////////////////////////////////////////// -// Helper Functions -////////////////////////////////////////////////////////////////////// - -inline void long_to_bytes(uint32_t val, void* buf) { - *static_cast<uint32_t*>(buf) = HostToNetwork32(val); -} - -inline void short_to_bytes(uint16_t val, void* buf) { - *static_cast<uint16_t*>(buf) = HostToNetwork16(val); -} - -inline uint32_t bytes_to_long(const void* buf) { - return NetworkToHost32(*static_cast<const uint32_t*>(buf)); -} - -inline uint16_t bytes_to_short(const void* buf) { - return NetworkToHost16(*static_cast<const uint16_t*>(buf)); -} - -////////////////////////////////////////////////////////////////////// -// Debugging Statistics -////////////////////////////////////////////////////////////////////// - -#if 0 // Not used yet - -enum Stat { - S_SENT_PACKET, // All packet sends - S_RESENT_PACKET, // All packet sends that are retransmits - S_RECV_PACKET, // All packet receives - S_RECV_NEW, // All packet receives that are too new - S_RECV_OLD, // All packet receives that are too old - S_NUM_STATS -}; - -const char* const STAT_NAMES[S_NUM_STATS] = { - "snt", - "snt-r", - "rcv" - "rcv-n", - "rcv-o" -}; - -int g_stats[S_NUM_STATS]; -inline void Incr(Stat s) { ++g_stats[s]; } -void ReportStats() { - char buffer[256]; - size_t len = 0; - for (int i = 0; i < S_NUM_STATS; ++i) { - len += snprintf(buffer, std::size(buffer), "%s%s:%d", - (i == 0) ? "" : ",", STAT_NAMES[i], g_stats[i]); - g_stats[i] = 0; - } - RTC_LOG(LS_INFO) << "Stats[" << buffer << "]"; -} - -#endif - -////////////////////////////////////////////////////////////////////// -// PseudoTcp -////////////////////////////////////////////////////////////////////// - -uint32_t PseudoTcp::Now() { -#if 0 // Use this to synchronize timers with logging timestamps (easier debug) - return static_cast<uint32_t>(TimeSince(StartTime())); -#else - return Time32(); -#endif -} - -PseudoTcp::PseudoTcp(IPseudoTcpNotify* notify, uint32_t conv) - : m_notify(notify), - m_shutdown(SD_NONE), - m_error(0), - m_rbuf_len(DEFAULT_RCV_BUF_SIZE), - m_rbuf(m_rbuf_len), - m_sbuf_len(DEFAULT_SND_BUF_SIZE), - m_sbuf(m_sbuf_len) { - // Sanity check on buffer sizes (needed for OnTcpWriteable notification logic) - RTC_DCHECK(m_rbuf_len + MIN_PACKET < m_sbuf_len); - - uint32_t now = Now(); - - m_state = TCP_LISTEN; - m_conv = conv; - m_rcv_wnd = m_rbuf_len; - m_rwnd_scale = m_swnd_scale = 0; - m_snd_nxt = 0; - m_snd_wnd = 1; - m_snd_una = m_rcv_nxt = 0; - m_bReadEnable = true; - m_bWriteEnable = false; - m_t_ack = 0; - - m_msslevel = 0; - m_largest = 0; - RTC_DCHECK(MIN_PACKET > PACKET_OVERHEAD); - m_mss = MIN_PACKET - PACKET_OVERHEAD; - m_mtu_advise = MAX_PACKET; - - m_rto_base = 0; - - m_cwnd = 2 * m_mss; - m_ssthresh = m_rbuf_len; - m_lastrecv = m_lastsend = m_lasttraffic = now; - m_bOutgoing = false; - - m_dup_acks = 0; - m_recover = 0; - - m_ts_recent = m_ts_lastack = 0; - - m_rx_rto = DEF_RTO; - m_rx_srtt = m_rx_rttvar = 0; - - m_use_nagling = true; - m_ack_delay = DEF_ACK_DELAY; - m_support_wnd_scale = true; -} - -PseudoTcp::~PseudoTcp() {} - -int PseudoTcp::Connect() { - if (m_state != TCP_LISTEN) { - m_error = EINVAL; - return -1; - } - - m_state = TCP_SYN_SENT; - RTC_LOG(LS_INFO) << "State: TCP_SYN_SENT"; - - queueConnectMessage(); - attemptSend(); - - return 0; -} - -void PseudoTcp::NotifyMTU(uint16_t mtu) { - m_mtu_advise = mtu; - if (m_state == TCP_ESTABLISHED) { - adjustMTU(); - } -} - -void PseudoTcp::NotifyClock(uint32_t now) { - if (m_state == TCP_CLOSED) - return; - - // Check if it's time to retransmit a segment - if (m_rto_base && (TimeDiff32(m_rto_base + m_rx_rto, now) <= 0)) { - if (m_slist.empty()) { - RTC_DCHECK_NOTREACHED(); - } else { -// Note: (m_slist.front().xmit == 0)) { -// retransmit segments -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "timeout retransmit (rto: " << m_rx_rto - << ") (rto_base: " << m_rto_base << ") (now: " << now - << ") (dup_acks: " << static_cast<unsigned>(m_dup_acks) - << ")"; -#endif // _DEBUGMSG - if (!transmit(m_slist.begin(), now)) { - closedown(ECONNABORTED); - return; - } - - uint32_t nInFlight = m_snd_nxt - m_snd_una; - m_ssthresh = std::max(nInFlight / 2, 2 * m_mss); - // RTC_LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << " nInFlight: " << - // nInFlight << " m_mss: " << m_mss; - m_cwnd = m_mss; - - // Back off retransmit timer. Note: the limit is lower when connecting. - uint32_t rto_limit = (m_state < TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO; - m_rx_rto = std::min(rto_limit, m_rx_rto * 2); - m_rto_base = now; - } - } - - // Check if it's time to probe closed windows - if ((m_snd_wnd == 0) && (TimeDiff32(m_lastsend + m_rx_rto, now) <= 0)) { - if (TimeDiff32(now, m_lastrecv) >= 15000) { - closedown(ECONNABORTED); - return; - } - - // probe the window - packet(m_snd_nxt - 1, 0, 0, 0); - m_lastsend = now; - - // back off retransmit timer - m_rx_rto = std::min(MAX_RTO, m_rx_rto * 2); - } - - // Check if it's time to send delayed acks - if (m_t_ack && (TimeDiff32(m_t_ack + m_ack_delay, now) <= 0)) { - packet(m_snd_nxt, 0, 0, 0); - } - -#if PSEUDO_KEEPALIVE - // Check for idle timeout - if ((m_state == TCP_ESTABLISHED) && - (TimeDiff32(m_lastrecv + IDLE_TIMEOUT, now) <= 0)) { - closedown(ECONNABORTED); - return; - } - - // Check for ping timeout (to keep udp mapping open) - if ((m_state == TCP_ESTABLISHED) && - (TimeDiff32(m_lasttraffic + (m_bOutgoing ? IDLE_PING * 3 / 2 : IDLE_PING), - now) <= 0)) { - packet(m_snd_nxt, 0, 0, 0); - } -#endif // PSEUDO_KEEPALIVE -} - -bool PseudoTcp::NotifyPacket(const char* buffer, size_t len) { - if (len > MAX_PACKET) { - RTC_LOG_F(LS_WARNING) << "packet too large"; - return false; - } - return parse(reinterpret_cast<const uint8_t*>(buffer), uint32_t(len)); -} - -bool PseudoTcp::GetNextClock(uint32_t now, long& timeout) { - return clock_check(now, timeout); -} - -void PseudoTcp::GetOption(Option opt, int* value) { - if (opt == OPT_NODELAY) { - *value = m_use_nagling ? 0 : 1; - } else if (opt == OPT_ACKDELAY) { - *value = m_ack_delay; - } else if (opt == OPT_SNDBUF) { - *value = m_sbuf_len; - } else if (opt == OPT_RCVBUF) { - *value = m_rbuf_len; - } else { - RTC_DCHECK_NOTREACHED(); - } -} -void PseudoTcp::SetOption(Option opt, int value) { - if (opt == OPT_NODELAY) { - m_use_nagling = value == 0; - } else if (opt == OPT_ACKDELAY) { - m_ack_delay = value; - } else if (opt == OPT_SNDBUF) { - RTC_DCHECK(m_state == TCP_LISTEN); - resizeSendBuffer(value); - } else if (opt == OPT_RCVBUF) { - RTC_DCHECK(m_state == TCP_LISTEN); - resizeReceiveBuffer(value); - } else { - RTC_DCHECK_NOTREACHED(); - } -} - -uint32_t PseudoTcp::GetCongestionWindow() const { - return m_cwnd; -} - -uint32_t PseudoTcp::GetBytesInFlight() const { - return m_snd_nxt - m_snd_una; -} - -uint32_t PseudoTcp::GetBytesBufferedNotSent() const { - return static_cast<uint32_t>(m_snd_una + m_sbuf.GetBuffered() - m_snd_nxt); -} - -uint32_t PseudoTcp::GetRoundTripTimeEstimateMs() const { - return m_rx_srtt; -} - -// -// IPStream Implementation -// - -int PseudoTcp::Recv(char* buffer, size_t len) { - if (m_state != TCP_ESTABLISHED) { - m_error = ENOTCONN; - return SOCKET_ERROR; - } - - size_t read = 0; - if (!m_rbuf.Read(buffer, len, &read)) { - m_bReadEnable = true; - m_error = EWOULDBLOCK; - return SOCKET_ERROR; - } - - size_t available_space = 0; - m_rbuf.GetWriteRemaining(&available_space); - - if (uint32_t(available_space) - m_rcv_wnd >= - std::min<uint32_t>(m_rbuf_len / 2, m_mss)) { - // TODO(jbeda): !?! Not sure about this was closed business - bool bWasClosed = (m_rcv_wnd == 0); - m_rcv_wnd = static_cast<uint32_t>(available_space); - - if (bWasClosed) { - attemptSend(sfImmediateAck); - } - } - - return static_cast<int>(read); -} - -int PseudoTcp::Send(const char* buffer, size_t len) { - if (m_state != TCP_ESTABLISHED) { - m_error = ENOTCONN; - return SOCKET_ERROR; - } - - size_t available_space = 0; - m_sbuf.GetWriteRemaining(&available_space); - - if (!available_space) { - m_bWriteEnable = true; - m_error = EWOULDBLOCK; - return SOCKET_ERROR; - } - - int written = queue(buffer, uint32_t(len), false); - attemptSend(); - return written; -} - -void PseudoTcp::Close(bool force) { - RTC_LOG_F(LS_VERBOSE) << "(" << (force ? "true" : "false") << ")"; - m_shutdown = force ? SD_FORCEFUL : SD_GRACEFUL; -} - -int PseudoTcp::GetError() { - return m_error; -} - -// -// Internal Implementation -// - -uint32_t PseudoTcp::queue(const char* data, uint32_t len, bool bCtrl) { - size_t available_space = 0; - m_sbuf.GetWriteRemaining(&available_space); - - if (len > static_cast<uint32_t>(available_space)) { - RTC_DCHECK(!bCtrl); - len = static_cast<uint32_t>(available_space); - } - - // We can concatenate data if the last segment is the same type - // (control v. regular data), and has not been transmitted yet - if (!m_slist.empty() && (m_slist.back().bCtrl == bCtrl) && - (m_slist.back().xmit == 0)) { - m_slist.back().len += len; - } else { - SSegment sseg(static_cast<uint32_t>(m_snd_una + m_sbuf.GetBuffered()), len, - bCtrl); - m_slist.push_back(sseg); - } - - size_t written = 0; - m_sbuf.Write(data, len, &written); - return static_cast<uint32_t>(written); -} - -IPseudoTcpNotify::WriteResult PseudoTcp::packet(uint32_t seq, - uint8_t flags, - uint32_t offset, - uint32_t len) { - RTC_DCHECK(HEADER_SIZE + len <= MAX_PACKET); - - uint32_t now = Now(); - - std::unique_ptr<uint8_t[]> buffer(new uint8_t[MAX_PACKET]); - long_to_bytes(m_conv, buffer.get()); - long_to_bytes(seq, buffer.get() + 4); - long_to_bytes(m_rcv_nxt, buffer.get() + 8); - buffer[12] = 0; - buffer[13] = flags; - short_to_bytes(static_cast<uint16_t>(m_rcv_wnd >> m_rwnd_scale), - buffer.get() + 14); - - // Timestamp computations - long_to_bytes(now, buffer.get() + 16); - long_to_bytes(m_ts_recent, buffer.get() + 20); - m_ts_lastack = m_rcv_nxt; - - if (len) { - size_t bytes_read = 0; - bool result = - m_sbuf.ReadOffset(buffer.get() + HEADER_SIZE, len, offset, &bytes_read); - RTC_DCHECK(result); - RTC_DCHECK(static_cast<uint32_t>(bytes_read) == len); - } - -#if _DEBUGMSG >= _DBG_VERBOSE - RTC_LOG(LS_INFO) << "<-- <CONV=" << m_conv - << "><FLG=" << static_cast<unsigned>(flags) - << "><SEQ=" << seq << ":" << seq + len - << "><ACK=" << m_rcv_nxt << "><WND=" << m_rcv_wnd - << "><TS=" << (now % 10000) - << "><TSR=" << (m_ts_recent % 10000) << "><LEN=" << len - << ">"; -#endif // _DEBUGMSG - - IPseudoTcpNotify::WriteResult wres = m_notify->TcpWritePacket( - this, reinterpret_cast<char*>(buffer.get()), len + HEADER_SIZE); - // Note: When len is 0, this is an ACK packet. We don't read the return value - // for those, and thus we won't retry. So go ahead and treat the packet as a - // success (basically simulate as if it were dropped), which will prevent our - // timers from being messed up. - if ((wres != IPseudoTcpNotify::WR_SUCCESS) && (0 != len)) - return wres; - - m_t_ack = 0; - if (len > 0) { - m_lastsend = now; - } - m_lasttraffic = now; - m_bOutgoing = true; - - return IPseudoTcpNotify::WR_SUCCESS; -} - -bool PseudoTcp::parse(const uint8_t* buffer, uint32_t size) { - if (size < HEADER_SIZE) - return false; - - Segment seg; - seg.conv = bytes_to_long(buffer); - seg.seq = bytes_to_long(buffer + 4); - seg.ack = bytes_to_long(buffer + 8); - seg.flags = buffer[13]; - seg.wnd = bytes_to_short(buffer + 14); - - seg.tsval = bytes_to_long(buffer + 16); - seg.tsecr = bytes_to_long(buffer + 20); - - seg.data = reinterpret_cast<const char*>(buffer) + HEADER_SIZE; - seg.len = size - HEADER_SIZE; - -#if _DEBUGMSG >= _DBG_VERBOSE - RTC_LOG(LS_INFO) << "--> <CONV=" << seg.conv - << "><FLG=" << static_cast<unsigned>(seg.flags) - << "><SEQ=" << seg.seq << ":" << seg.seq + seg.len - << "><ACK=" << seg.ack << "><WND=" << seg.wnd - << "><TS=" << (seg.tsval % 10000) - << "><TSR=" << (seg.tsecr % 10000) << "><LEN=" << seg.len - << ">"; -#endif // _DEBUGMSG - - return process(seg); -} - -bool PseudoTcp::clock_check(uint32_t now, long& nTimeout) { - if (m_shutdown == SD_FORCEFUL) - return false; - - if ((m_shutdown == SD_GRACEFUL) && - ((m_state != TCP_ESTABLISHED) || - ((m_sbuf.GetBuffered() == 0) && (m_t_ack == 0)))) { - return false; - } - - if (m_state == TCP_CLOSED) { - nTimeout = CLOSED_TIMEOUT; - return true; - } - - nTimeout = DEFAULT_TIMEOUT; - - if (m_t_ack) { - nTimeout = - std::min<int32_t>(nTimeout, TimeDiff32(m_t_ack + m_ack_delay, now)); - } - if (m_rto_base) { - nTimeout = - std::min<int32_t>(nTimeout, TimeDiff32(m_rto_base + m_rx_rto, now)); - } - if (m_snd_wnd == 0) { - nTimeout = - std::min<int32_t>(nTimeout, TimeDiff32(m_lastsend + m_rx_rto, now)); - } -#if PSEUDO_KEEPALIVE - if (m_state == TCP_ESTABLISHED) { - nTimeout = std::min<int32_t>( - nTimeout, TimeDiff32(m_lasttraffic + - (m_bOutgoing ? IDLE_PING * 3 / 2 : IDLE_PING), - now)); - } -#endif // PSEUDO_KEEPALIVE - return true; -} - -bool PseudoTcp::process(Segment& seg) { - // If this is the wrong conversation, send a reset!?! (with the correct - // conversation?) - if (seg.conv != m_conv) { - // if ((seg.flags & FLAG_RST) == 0) { - // packet(tcb, seg.ack, 0, FLAG_RST, 0, 0); - //} - RTC_LOG_F(LS_ERROR) << "wrong conversation"; - return false; - } - - uint32_t now = Now(); - m_lasttraffic = m_lastrecv = now; - m_bOutgoing = false; - - if (m_state == TCP_CLOSED) { - // !?! send reset? - RTC_LOG_F(LS_ERROR) << "closed"; - return false; - } - - // Check if this is a reset segment - if (seg.flags & FLAG_RST) { - closedown(ECONNRESET); - return false; - } - - // Check for control data - bool bConnect = false; - if (seg.flags & FLAG_CTL) { - if (seg.len == 0) { - RTC_LOG_F(LS_ERROR) << "Missing control code"; - return false; - } else if (seg.data[0] == CTL_CONNECT) { - bConnect = true; - - // TCP options are in the remainder of the payload after CTL_CONNECT. - parseOptions(&seg.data[1], seg.len - 1); - - if (m_state == TCP_LISTEN) { - m_state = TCP_SYN_RECEIVED; - RTC_LOG(LS_INFO) << "State: TCP_SYN_RECEIVED"; - // m_notify->associate(addr); - queueConnectMessage(); - } else if (m_state == TCP_SYN_SENT) { - m_state = TCP_ESTABLISHED; - RTC_LOG(LS_INFO) << "State: TCP_ESTABLISHED"; - adjustMTU(); - if (m_notify) { - m_notify->OnTcpOpen(this); - } - // notify(evOpen); - } - } else { - RTC_LOG_F(LS_WARNING) << "Unknown control code: " << seg.data[0]; - return false; - } - } - - // Update timestamp - if ((seg.seq <= m_ts_lastack) && (m_ts_lastack < seg.seq + seg.len)) { - m_ts_recent = seg.tsval; - } - - // Check if this is a valuable ack - if ((seg.ack > m_snd_una) && (seg.ack <= m_snd_nxt)) { - // Calculate round-trip time - if (seg.tsecr) { - int32_t rtt = TimeDiff32(now, seg.tsecr); - if (rtt >= 0) { - if (m_rx_srtt == 0) { - m_rx_srtt = rtt; - m_rx_rttvar = rtt / 2; - } else { - uint32_t unsigned_rtt = static_cast<uint32_t>(rtt); - uint32_t abs_err = unsigned_rtt > m_rx_srtt - ? unsigned_rtt - m_rx_srtt - : m_rx_srtt - unsigned_rtt; - m_rx_rttvar = (3 * m_rx_rttvar + abs_err) / 4; - m_rx_srtt = (7 * m_rx_srtt + rtt) / 8; - } - m_rx_rto = SafeClamp(m_rx_srtt + SafeMax(1, 4 * m_rx_rttvar), MIN_RTO, - MAX_RTO); -#if _DEBUGMSG >= _DBG_VERBOSE - RTC_LOG(LS_INFO) << "rtt: " << rtt << " srtt: " << m_rx_srtt - << " rto: " << m_rx_rto; -#endif // _DEBUGMSG - } else { - RTC_LOG(LS_WARNING) << "rtt < 0"; - } - } - - m_snd_wnd = static_cast<uint32_t>(seg.wnd) << m_swnd_scale; - - uint32_t nAcked = seg.ack - m_snd_una; - m_snd_una = seg.ack; - - m_rto_base = (m_snd_una == m_snd_nxt) ? 0 : now; - - m_sbuf.ConsumeReadData(nAcked); - - for (uint32_t nFree = nAcked; nFree > 0;) { - RTC_DCHECK(!m_slist.empty()); - if (nFree < m_slist.front().len) { - m_slist.front().len -= nFree; - nFree = 0; - } else { - if (m_slist.front().len > m_largest) { - m_largest = m_slist.front().len; - } - nFree -= m_slist.front().len; - m_slist.pop_front(); - } - } - - if (m_dup_acks >= 3) { - if (m_snd_una >= m_recover) { // NewReno - uint32_t nInFlight = m_snd_nxt - m_snd_una; - m_cwnd = std::min(m_ssthresh, nInFlight + m_mss); // (Fast Retransmit) -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "exit recovery"; -#endif // _DEBUGMSG - m_dup_acks = 0; - } else { -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "recovery retransmit"; -#endif // _DEBUGMSG - if (!transmit(m_slist.begin(), now)) { - closedown(ECONNABORTED); - return false; - } - m_cwnd += m_mss - std::min(nAcked, m_cwnd); - } - } else { - m_dup_acks = 0; - // Slow start, congestion avoidance - if (m_cwnd < m_ssthresh) { - m_cwnd += m_mss; - } else { - m_cwnd += std::max<uint32_t>(1, m_mss * m_mss / m_cwnd); - } - } - } else if (seg.ack == m_snd_una) { - // !?! Note, tcp says don't do this... but otherwise how does a closed - // window become open? - m_snd_wnd = static_cast<uint32_t>(seg.wnd) << m_swnd_scale; - - // Check duplicate acks - if (seg.len > 0) { - // it's a dup ack, but with a data payload, so don't modify m_dup_acks - } else if (m_snd_una != m_snd_nxt) { - m_dup_acks += 1; - if (m_dup_acks == 3) { // (Fast Retransmit) -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "enter recovery"; - RTC_LOG(LS_INFO) << "recovery retransmit"; -#endif // _DEBUGMSG - if (!transmit(m_slist.begin(), now)) { - closedown(ECONNABORTED); - return false; - } - m_recover = m_snd_nxt; - uint32_t nInFlight = m_snd_nxt - m_snd_una; - m_ssthresh = std::max(nInFlight / 2, 2 * m_mss); - // RTC_LOG(LS_INFO) << "m_ssthresh: " << m_ssthresh << " nInFlight: " - // << nInFlight << " m_mss: " << m_mss; - m_cwnd = m_ssthresh + 3 * m_mss; - } else if (m_dup_acks > 3) { - m_cwnd += m_mss; - } - } else { - m_dup_acks = 0; - } - } - - // !?! A bit hacky - if ((m_state == TCP_SYN_RECEIVED) && !bConnect) { - m_state = TCP_ESTABLISHED; - RTC_LOG(LS_INFO) << "State: TCP_ESTABLISHED"; - adjustMTU(); - if (m_notify) { - m_notify->OnTcpOpen(this); - } - // notify(evOpen); - } - - // If we make room in the send queue, notify the user - // The goal it to make sure we always have at least enough data to fill the - // window. We'd like to notify the app when we are halfway to that point. - const uint32_t kIdealRefillSize = (m_sbuf_len + m_rbuf_len) / 2; - if (m_bWriteEnable && - static_cast<uint32_t>(m_sbuf.GetBuffered()) < kIdealRefillSize) { - m_bWriteEnable = false; - if (m_notify) { - m_notify->OnTcpWriteable(this); - } - // notify(evWrite); - } - - // Conditions were acks must be sent: - // 1) Segment is too old (they missed an ACK) (immediately) - // 2) Segment is too new (we missed a segment) (immediately) - // 3) Segment has data (so we need to ACK!) (delayed) - // ... so the only time we don't need to ACK, is an empty segment that points - // to rcv_nxt! - - SendFlags sflags = sfNone; - if (seg.seq != m_rcv_nxt) { - sflags = sfImmediateAck; // (Fast Recovery) - } else if (seg.len != 0) { - if (m_ack_delay == 0) { - sflags = sfImmediateAck; - } else { - sflags = sfDelayedAck; - } - } -#if _DEBUGMSG >= _DBG_NORMAL - if (sflags == sfImmediateAck) { - if (seg.seq > m_rcv_nxt) { - RTC_LOG_F(LS_INFO) << "too new"; - } else if (seg.seq + seg.len <= m_rcv_nxt) { - RTC_LOG_F(LS_INFO) << "too old"; - } - } -#endif // _DEBUGMSG - - // Adjust the incoming segment to fit our receive buffer - if (seg.seq < m_rcv_nxt) { - uint32_t nAdjust = m_rcv_nxt - seg.seq; - if (nAdjust < seg.len) { - seg.seq += nAdjust; - seg.data += nAdjust; - seg.len -= nAdjust; - } else { - seg.len = 0; - } - } - - size_t available_space = 0; - m_rbuf.GetWriteRemaining(&available_space); - - if ((seg.seq + seg.len - m_rcv_nxt) > - static_cast<uint32_t>(available_space)) { - uint32_t nAdjust = - seg.seq + seg.len - m_rcv_nxt - static_cast<uint32_t>(available_space); - if (nAdjust < seg.len) { - seg.len -= nAdjust; - } else { - seg.len = 0; - } - } - - bool bIgnoreData = (seg.flags & FLAG_CTL) || (m_shutdown != SD_NONE); - bool bNewData = false; - - if (seg.len > 0) { - bool bRecover = false; - if (bIgnoreData) { - if (seg.seq == m_rcv_nxt) { - m_rcv_nxt += seg.len; - // If we received a data segment out of order relative to a control - // segment, then we wrote it into the receive buffer at an offset (see - // "WriteOffset") below. So we need to advance the position in the - // buffer to avoid corrupting data. See bugs.webrtc.org/9208 - // - // We advance the position in the buffer by N bytes by acting like we - // wrote N bytes and then immediately read them. We can only do this if - // there's not already data ready to read, but this should always be - // true in the problematic scenario, since control frames are always - // sent first in the stream. - if (m_rbuf.GetBuffered() == 0) { - m_rbuf.ConsumeWriteBuffer(seg.len); - m_rbuf.ConsumeReadData(seg.len); - // After shifting the position in the buffer, we may have - // out-of-order packets ready to be recovered. - bRecover = true; - } - } - } else { - uint32_t nOffset = seg.seq - m_rcv_nxt; - - if (!m_rbuf.WriteOffset(seg.data, seg.len, nOffset, nullptr)) { - // Ignore incoming packets outside of the receive window. - return false; - } - - if (seg.seq == m_rcv_nxt) { - m_rbuf.ConsumeWriteBuffer(seg.len); - m_rcv_nxt += seg.len; - m_rcv_wnd -= seg.len; - bNewData = true; - // May be able to recover packets previously received out-of-order - // now. - bRecover = true; - } else { -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "Saving " << seg.len << " bytes (" << seg.seq - << " -> " << seg.seq + seg.len << ")"; -#endif // _DEBUGMSG - RSegment rseg; - rseg.seq = seg.seq; - rseg.len = seg.len; - RList::iterator it = m_rlist.begin(); - while ((it != m_rlist.end()) && (it->seq < rseg.seq)) { - ++it; - } - m_rlist.insert(it, rseg); - } - } - if (bRecover) { - RList::iterator it = m_rlist.begin(); - while ((it != m_rlist.end()) && (it->seq <= m_rcv_nxt)) { - if (it->seq + it->len > m_rcv_nxt) { - sflags = sfImmediateAck; // (Fast Recovery) - uint32_t nAdjust = (it->seq + it->len) - m_rcv_nxt; -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "Recovered " << nAdjust << " bytes (" << m_rcv_nxt - << " -> " << m_rcv_nxt + nAdjust << ")"; -#endif // _DEBUGMSG - m_rbuf.ConsumeWriteBuffer(nAdjust); - m_rcv_nxt += nAdjust; - m_rcv_wnd -= nAdjust; - bNewData = true; - } - it = m_rlist.erase(it); - } - } - } - - attemptSend(sflags); - - // If we have new data, notify the user - if (bNewData && m_bReadEnable) { - m_bReadEnable = false; - if (m_notify) { - m_notify->OnTcpReadable(this); - } - // notify(evRead); - } - - return true; -} - -bool PseudoTcp::transmit(const SList::iterator& seg, uint32_t now) { - if (seg->xmit >= ((m_state == TCP_ESTABLISHED) ? 15 : 30)) { - RTC_LOG_F(LS_VERBOSE) << "too many retransmits"; - return false; - } - - uint32_t nTransmit = std::min(seg->len, m_mss); - - while (true) { - uint32_t seq = seg->seq; - uint8_t flags = (seg->bCtrl ? FLAG_CTL : 0); - IPseudoTcpNotify::WriteResult wres = - packet(seq, flags, seg->seq - m_snd_una, nTransmit); - - if (wres == IPseudoTcpNotify::WR_SUCCESS) - break; - - if (wres == IPseudoTcpNotify::WR_FAIL) { - RTC_LOG_F(LS_VERBOSE) << "packet failed"; - return false; - } - - RTC_DCHECK(wres == IPseudoTcpNotify::WR_TOO_LARGE); - - while (true) { - if (PACKET_MAXIMUMS[m_msslevel + 1] == 0) { - RTC_LOG_F(LS_VERBOSE) << "MTU too small"; - return false; - } - // !?! We need to break up all outstanding and pending packets and then - // retransmit!?! - - m_mss = PACKET_MAXIMUMS[++m_msslevel] - PACKET_OVERHEAD; - m_cwnd = 2 * m_mss; // I added this... haven't researched actual formula - if (m_mss < nTransmit) { - nTransmit = m_mss; - break; - } - } -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes"; -#endif // _DEBUGMSG - } - - if (nTransmit < seg->len) { - RTC_LOG_F(LS_VERBOSE) << "mss reduced to " << m_mss; - - SSegment subseg(seg->seq + nTransmit, seg->len - nTransmit, seg->bCtrl); - // subseg.tstamp = seg->tstamp; - subseg.xmit = seg->xmit; - seg->len = nTransmit; - - SList::iterator next = seg; - m_slist.insert(++next, subseg); - } - - if (seg->xmit == 0) { - m_snd_nxt += seg->len; - } - seg->xmit += 1; - // seg->tstamp = now; - if (m_rto_base == 0) { - m_rto_base = now; - } - - return true; -} - -void PseudoTcp::attemptSend(SendFlags sflags) { - uint32_t now = Now(); - - if (TimeDiff32(now, m_lastsend) > static_cast<long>(m_rx_rto)) { - m_cwnd = m_mss; - } - -#if _DEBUGMSG - bool bFirst = true; -#endif // _DEBUGMSG - - while (true) { - uint32_t cwnd = m_cwnd; - if ((m_dup_acks == 1) || (m_dup_acks == 2)) { // Limited Transmit - cwnd += m_dup_acks * m_mss; - } - uint32_t nWindow = std::min(m_snd_wnd, cwnd); - uint32_t nInFlight = m_snd_nxt - m_snd_una; - uint32_t nUseable = (nInFlight < nWindow) ? (nWindow - nInFlight) : 0; - - size_t snd_buffered = m_sbuf.GetBuffered(); - uint32_t nAvailable = - std::min(static_cast<uint32_t>(snd_buffered) - nInFlight, m_mss); - - if (nAvailable > nUseable) { - if (nUseable * 4 < nWindow) { - // RFC 813 - avoid SWS - nAvailable = 0; - } else { - nAvailable = nUseable; - } - } - -#if _DEBUGMSG >= _DBG_VERBOSE - if (bFirst) { - size_t available_space = 0; - m_sbuf.GetWriteRemaining(&available_space); - - bFirst = false; - RTC_LOG(LS_INFO) << "[cwnd: " << m_cwnd << " nWindow: " << nWindow - << " nInFlight: " << nInFlight - << " nAvailable: " << nAvailable - << " nQueued: " << snd_buffered - << " nEmpty: " << available_space - << " ssthresh: " << m_ssthresh << "]"; - } -#endif // _DEBUGMSG - - if (nAvailable == 0) { - if (sflags == sfNone) - return; - - // If this is an immediate ack, or the second delayed ack - if ((sflags == sfImmediateAck) || m_t_ack) { - packet(m_snd_nxt, 0, 0, 0); - } else { - m_t_ack = Now(); - } - return; - } - - // Nagle's algorithm. - // If there is data already in-flight, and we haven't a full segment of - // data ready to send then hold off until we get more to send, or the - // in-flight data is acknowledged. - if (m_use_nagling && (m_snd_nxt > m_snd_una) && (nAvailable < m_mss)) { - return; - } - - // Find the next segment to transmit - SList::iterator it = m_slist.begin(); - while (it->xmit > 0) { - ++it; - RTC_DCHECK(it != m_slist.end()); - } - SList::iterator seg = it; - - // If the segment is too large, break it into two - if (seg->len > nAvailable) { - SSegment subseg(seg->seq + nAvailable, seg->len - nAvailable, seg->bCtrl); - seg->len = nAvailable; - m_slist.insert(++it, subseg); - } - - if (!transmit(seg, now)) { - RTC_LOG_F(LS_VERBOSE) << "transmit failed"; - // TODO(?): consider closing socket - return; - } - - sflags = sfNone; - } -} - -void PseudoTcp::closedown(uint32_t err) { - RTC_LOG(LS_INFO) << "State: TCP_CLOSED"; - m_state = TCP_CLOSED; - if (m_notify) { - m_notify->OnTcpClosed(this, err); - } - // notify(evClose, err); -} - -void PseudoTcp::adjustMTU() { - // Determine our current mss level, so that we can adjust appropriately later - for (m_msslevel = 0; PACKET_MAXIMUMS[m_msslevel + 1] > 0; ++m_msslevel) { - if (static_cast<uint16_t>(PACKET_MAXIMUMS[m_msslevel]) <= m_mtu_advise) { - break; - } - } - m_mss = m_mtu_advise - PACKET_OVERHEAD; -// !?! Should we reset m_largest here? -#if _DEBUGMSG >= _DBG_NORMAL - RTC_LOG(LS_INFO) << "Adjusting mss to " << m_mss << " bytes"; -#endif // _DEBUGMSG - // Enforce minimums on ssthresh and cwnd - m_ssthresh = std::max(m_ssthresh, 2 * m_mss); - m_cwnd = std::max(m_cwnd, m_mss); -} - -bool PseudoTcp::isReceiveBufferFull() const { - size_t available_space = 0; - m_rbuf.GetWriteRemaining(&available_space); - return !available_space; -} - -void PseudoTcp::disableWindowScale() { - m_support_wnd_scale = false; -} - -void PseudoTcp::queueConnectMessage() { - ByteBufferWriter buf; - - buf.WriteUInt8(CTL_CONNECT); - if (m_support_wnd_scale) { - buf.WriteUInt8(TCP_OPT_WND_SCALE); - buf.WriteUInt8(1); - buf.WriteUInt8(m_rwnd_scale); - } - m_snd_wnd = static_cast<uint32_t>(buf.Length()); - queue(reinterpret_cast<const char*>(buf.Data()), - static_cast<uint32_t>(buf.Length()), true); -} - -void PseudoTcp::parseOptions(const char* data, uint32_t len) { - std::set<uint8_t> options_specified; - - // See http://www.freesoft.org/CIE/Course/Section4/8.htm for - // parsing the options list. - ByteBufferReader buf( - MakeArrayView(reinterpret_cast<const uint8_t*>(data), len)); - while (buf.Length()) { - uint8_t kind = TCP_OPT_EOL; - buf.ReadUInt8(&kind); - - if (kind == TCP_OPT_EOL) { - // End of option list. - break; - } else if (kind == TCP_OPT_NOOP) { - // No op. - continue; - } - - // Length of this option. - RTC_DCHECK(len != 0); - uint8_t opt_len = 0; - buf.ReadUInt8(&opt_len); - - // Content of this option. - if (opt_len <= buf.Length()) { - applyOption(kind, reinterpret_cast<const char*>(buf.Data()), opt_len); - buf.Consume(opt_len); - } else { - RTC_LOG(LS_ERROR) << "Invalid option length received."; - return; - } - options_specified.insert(kind); - } - - if (options_specified.find(TCP_OPT_WND_SCALE) == options_specified.end()) { - RTC_LOG(LS_WARNING) << "Peer doesn't support window scaling"; - - if (m_rwnd_scale > 0) { - // Peer doesn't support TCP options and window scaling. - // Revert receive buffer size to default value. - resizeReceiveBuffer(DEFAULT_RCV_BUF_SIZE); - m_swnd_scale = 0; - } - } -} - -void PseudoTcp::applyOption(char kind, const char* data, uint32_t len) { - if (kind == TCP_OPT_MSS) { - RTC_LOG(LS_WARNING) << "Peer specified MSS option which is not supported."; - // TODO(?): Implement. - } else if (kind == TCP_OPT_WND_SCALE) { - // Window scale factor. - // http://www.ietf.org/rfc/rfc1323.txt - if (len != 1) { - RTC_LOG_F(LS_WARNING) << "Invalid window scale option received."; - return; - } - applyWindowScaleOption(data[0]); - } -} - -void PseudoTcp::applyWindowScaleOption(uint8_t scale_factor) { - m_swnd_scale = scale_factor; -} - -void PseudoTcp::resizeSendBuffer(uint32_t new_size) { - m_sbuf_len = new_size; - m_sbuf.SetCapacity(new_size); -} - -void PseudoTcp::resizeReceiveBuffer(uint32_t new_size) { - uint8_t scale_factor = 0; - - // Determine the scale factor such that the scaled window size can fit - // in a 16-bit unsigned integer. - while (new_size > 0xFFFF) { - ++scale_factor; - new_size >>= 1; - } - - // Determine the proper size of the buffer. - new_size <<= scale_factor; - bool result = m_rbuf.SetCapacity(new_size); - - // Make sure the new buffer is large enough to contain data in the old - // buffer. This should always be true because this method is called either - // before connection is established or when peers are exchanging connect - // messages. - RTC_DCHECK(result); - m_rbuf_len = new_size; - m_rwnd_scale = scale_factor; - m_ssthresh = new_size; - - size_t available_space = 0; - m_rbuf.GetWriteRemaining(&available_space); - m_rcv_wnd = static_cast<uint32_t>(available_space); -} - -PseudoTcp::LockedFifoBuffer::LockedFifoBuffer(size_t size) - : buffer_(new char[size]), - buffer_length_(size), - data_length_(0), - read_position_(0) {} - -PseudoTcp::LockedFifoBuffer::~LockedFifoBuffer() {} - -size_t PseudoTcp::LockedFifoBuffer::GetBuffered() const { - MutexLock lock(&mutex_); - return data_length_; -} - -bool PseudoTcp::LockedFifoBuffer::SetCapacity(size_t size) { - MutexLock lock(&mutex_); - if (data_length_ > size) - return false; - - if (size != buffer_length_) { - char* buffer = new char[size]; - const size_t copy = data_length_; - const size_t tail_copy = std::min(copy, buffer_length_ - read_position_); - memcpy(buffer, &buffer_[read_position_], tail_copy); - memcpy(buffer + tail_copy, &buffer_[0], copy - tail_copy); - buffer_.reset(buffer); - read_position_ = 0; - buffer_length_ = size; - } - - return true; -} - -bool PseudoTcp::LockedFifoBuffer::ReadOffset(void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_read) { - MutexLock lock(&mutex_); - return ReadOffsetLocked(buffer, bytes, offset, bytes_read); -} - -bool PseudoTcp::LockedFifoBuffer::WriteOffset(const void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_written) { - MutexLock lock(&mutex_); - return WriteOffsetLocked(buffer, bytes, offset, bytes_written); -} - -bool PseudoTcp::LockedFifoBuffer::Read(void* buffer, - size_t bytes, - size_t* bytes_read) { - MutexLock lock(&mutex_); - size_t copy = 0; - if (!ReadOffsetLocked(buffer, bytes, 0, &copy)) - return false; - - // If read was successful then adjust the read position and number of - // bytes buffered. - read_position_ = (read_position_ + copy) % buffer_length_; - data_length_ -= copy; - if (bytes_read) - *bytes_read = copy; - - return true; -} - -bool PseudoTcp::LockedFifoBuffer::Write(const void* buffer, - size_t bytes, - size_t* bytes_written) { - MutexLock lock(&mutex_); - size_t copy = 0; - if (!WriteOffsetLocked(buffer, bytes, 0, &copy)) - return false; - - // If write was successful then adjust the number of readable bytes. - data_length_ += copy; - if (bytes_written) { - *bytes_written = copy; - } - - return true; -} - -void PseudoTcp::LockedFifoBuffer::ConsumeReadData(size_t size) { - MutexLock lock(&mutex_); - RTC_DCHECK(size <= data_length_); - read_position_ = (read_position_ + size) % buffer_length_; - data_length_ -= size; -} - -void PseudoTcp::LockedFifoBuffer::ConsumeWriteBuffer(size_t size) { - MutexLock lock(&mutex_); - RTC_DCHECK(size <= buffer_length_ - data_length_); - data_length_ += size; -} - -bool PseudoTcp::LockedFifoBuffer::GetWriteRemaining(size_t* size) const { - MutexLock lock(&mutex_); - *size = buffer_length_ - data_length_; - return true; -} - -bool PseudoTcp::LockedFifoBuffer::ReadOffsetLocked(void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_read) { - if (offset >= data_length_) - return false; - - const size_t available = data_length_ - offset; - const size_t read_position = (read_position_ + offset) % buffer_length_; - const size_t copy = std::min(bytes, available); - const size_t tail_copy = std::min(copy, buffer_length_ - read_position); - char* const p = static_cast<char*>(buffer); - memcpy(p, &buffer_[read_position], tail_copy); - memcpy(p + tail_copy, &buffer_[0], copy - tail_copy); - - if (bytes_read) - *bytes_read = copy; - - return true; -} - -bool PseudoTcp::LockedFifoBuffer::WriteOffsetLocked(const void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_written) { - if (data_length_ + offset >= buffer_length_) - return false; - - const size_t available = buffer_length_ - data_length_ - offset; - const size_t write_position = - (read_position_ + data_length_ + offset) % buffer_length_; - const size_t copy = std::min(bytes, available); - const size_t tail_copy = std::min(copy, buffer_length_ - write_position); - const char* const p = static_cast<const char*>(buffer); - memcpy(&buffer_[write_position], p, tail_copy); - memcpy(&buffer_[0], p + tail_copy, copy - tail_copy); - - if (bytes_written) - *bytes_written = copy; - - return true; -} - -} // namespace webrtc diff --git a/third_party/libwebrtc/p2p/base/pseudo_tcp.h b/third_party/libwebrtc/p2p/base/pseudo_tcp.h @@ -1,296 +0,0 @@ -/* - * Copyright 2004 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. - */ - -#ifndef P2P_BASE_PSEUDO_TCP_H_ -#define P2P_BASE_PSEUDO_TCP_H_ - -#include <cstddef> -#include <cstdint> -#include <list> -#include <memory> - -#include "rtc_base/synchronization/mutex.h" -#include "rtc_base/system/rtc_export.h" -#include "rtc_base/thread_annotations.h" - -namespace webrtc { - -////////////////////////////////////////////////////////////////////// -// IPseudoTcpNotify -////////////////////////////////////////////////////////////////////// - -class PseudoTcp; - -class IPseudoTcpNotify { - public: - // Notification of tcp events - virtual void OnTcpOpen(PseudoTcp* tcp) = 0; - virtual void OnTcpReadable(PseudoTcp* tcp) = 0; - virtual void OnTcpWriteable(PseudoTcp* tcp) = 0; - virtual void OnTcpClosed(PseudoTcp* tcp, uint32_t error) = 0; - - // Write the packet onto the network - enum WriteResult { WR_SUCCESS, WR_TOO_LARGE, WR_FAIL }; - virtual WriteResult TcpWritePacket(PseudoTcp* tcp, - const char* buffer, - size_t len) = 0; - - protected: - virtual ~IPseudoTcpNotify() {} -}; - -////////////////////////////////////////////////////////////////////// -// PseudoTcp -////////////////////////////////////////////////////////////////////// - -class RTC_EXPORT PseudoTcp { - public: - static uint32_t Now(); - - PseudoTcp(IPseudoTcpNotify* notify, uint32_t conv); - virtual ~PseudoTcp(); - - int Connect(); - int Recv(char* buffer, size_t len); - int Send(const char* buffer, size_t len); - void Close(bool force); - int GetError(); - - enum TcpState { - TCP_LISTEN, - TCP_SYN_SENT, - TCP_SYN_RECEIVED, - TCP_ESTABLISHED, - TCP_CLOSED - }; - TcpState State() const { return m_state; } - - // Call this when the PMTU changes. - void NotifyMTU(uint16_t mtu); - - // Call this based on timeout value returned from GetNextClock. - // It's ok to call this too frequently. - void NotifyClock(uint32_t now); - - // Call this whenever a packet arrives. - // Returns true if the packet was processed successfully. - bool NotifyPacket(const char* buffer, size_t len); - - // Call this to determine the next time NotifyClock should be called. - // Returns false if the socket is ready to be destroyed. - bool GetNextClock(uint32_t now, long& timeout); - - // Call these to get/set option values to tailor this PseudoTcp - // instance's behaviour for the kind of data it will carry. - // If an unrecognized option is set or got, an assertion will fire. - // - // Setting options for OPT_RCVBUF or OPT_SNDBUF after Connect() is called - // will result in an assertion. - enum Option { - OPT_NODELAY, // Whether to enable Nagle's algorithm (0 == off) - OPT_ACKDELAY, // The Delayed ACK timeout (0 == off). - OPT_RCVBUF, // Set the receive buffer size, in bytes. - OPT_SNDBUF, // Set the send buffer size, in bytes. - }; - void GetOption(Option opt, int* value); - void SetOption(Option opt, int value); - - // Returns current congestion window in bytes. - uint32_t GetCongestionWindow() const; - - // Returns amount of data in bytes that has been sent, but haven't - // been acknowledged. - uint32_t GetBytesInFlight() const; - - // Returns number of bytes that were written in buffer and haven't - // been sent. - uint32_t GetBytesBufferedNotSent() const; - - // Returns current round-trip time estimate in milliseconds. - uint32_t GetRoundTripTimeEstimateMs() const; - - protected: - enum SendFlags { sfNone, sfDelayedAck, sfImmediateAck }; - - struct Segment { - uint32_t conv, seq, ack; - uint8_t flags; - uint16_t wnd; - const char* data; - uint32_t len; - uint32_t tsval, tsecr; - }; - - struct SSegment { - SSegment(uint32_t s, uint32_t l, bool c) - : seq(s), len(l), /*tstamp(0),*/ xmit(0), bCtrl(c) {} - uint32_t seq, len; - // uint32_t tstamp; - uint8_t xmit; - bool bCtrl; - }; - typedef std::list<SSegment> SList; - - struct RSegment { - uint32_t seq, len; - }; - - uint32_t queue(const char* data, uint32_t len, bool bCtrl); - - // Creates a packet and submits it to the network. This method can either - // send payload or just an ACK packet. - // - // `seq` is the sequence number of this packet. - // `flags` is the flags for sending this packet. - // `offset` is the offset to read from `m_sbuf`. - // `len` is the number of bytes to read from `m_sbuf` as payload. If this - // value is 0 then this is an ACK packet, otherwise this packet has payload. - IPseudoTcpNotify::WriteResult packet(uint32_t seq, - uint8_t flags, - uint32_t offset, - uint32_t len); - bool parse(const uint8_t* buffer, uint32_t size); - - void attemptSend(SendFlags sflags = sfNone); - - void closedown(uint32_t err = 0); - - bool clock_check(uint32_t now, long& nTimeout); - - bool process(Segment& seg); - bool transmit(const SList::iterator& seg, uint32_t now); - - void adjustMTU(); - - protected: - // This method is used in test only to query receive buffer state. - bool isReceiveBufferFull() const; - - // This method is only used in tests, to disable window scaling - // support for testing backward compatibility. - void disableWindowScale(); - - private: - // Queue the connect message with TCP options. - void queueConnectMessage(); - - // Parse TCP options in the header. - void parseOptions(const char* data, uint32_t len); - - // Apply a TCP option that has been read from the header. - void applyOption(char kind, const char* data, uint32_t len); - - // Apply window scale option. - void applyWindowScaleOption(uint8_t scale_factor); - - // Resize the send buffer with `new_size` in bytes. - void resizeSendBuffer(uint32_t new_size); - - // Resize the receive buffer with `new_size` in bytes. This call adjusts - // window scale factor `m_swnd_scale` accordingly. - void resizeReceiveBuffer(uint32_t new_size); - - class LockedFifoBuffer final { - public: - explicit LockedFifoBuffer(size_t size); - ~LockedFifoBuffer(); - - size_t GetBuffered() const; - bool SetCapacity(size_t size); - bool ReadOffset(void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_read); - bool WriteOffset(const void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_written); - bool Read(void* buffer, size_t bytes, size_t* bytes_read); - bool Write(const void* buffer, size_t bytes, size_t* bytes_written); - void ConsumeReadData(size_t size); - void ConsumeWriteBuffer(size_t size); - bool GetWriteRemaining(size_t* size) const; - - private: - bool ReadOffsetLocked(void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_read) - RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - bool WriteOffsetLocked(const void* buffer, - size_t bytes, - size_t offset, - size_t* bytes_written) - RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_); - - // the allocated buffer - std::unique_ptr<char[]> buffer_ RTC_GUARDED_BY(mutex_); - // size of the allocated buffer - size_t buffer_length_ RTC_GUARDED_BY(mutex_); - // amount of readable data in the buffer - size_t data_length_ RTC_GUARDED_BY(mutex_); - // offset to the readable data - size_t read_position_ RTC_GUARDED_BY(mutex_); - mutable Mutex mutex_; - }; - - IPseudoTcpNotify* m_notify; - enum Shutdown { SD_NONE, SD_GRACEFUL, SD_FORCEFUL } m_shutdown; - int m_error; - - // TCB data - TcpState m_state; - uint32_t m_conv; - bool m_bReadEnable, m_bWriteEnable, m_bOutgoing; - uint32_t m_lasttraffic; - - // Incoming data - typedef std::list<RSegment> RList; - RList m_rlist; - uint32_t m_rbuf_len, m_rcv_nxt, m_rcv_wnd, m_lastrecv; - uint8_t m_rwnd_scale; // Window scale factor. - LockedFifoBuffer m_rbuf; - - // Outgoing data - SList m_slist; - uint32_t m_sbuf_len, m_snd_nxt, m_snd_wnd, m_lastsend, m_snd_una; - uint8_t m_swnd_scale; // Window scale factor. - LockedFifoBuffer m_sbuf; - - // Maximum segment size, estimated protocol level, largest segment sent - uint32_t m_mss, m_msslevel, m_largest, m_mtu_advise; - // Retransmit timer - uint32_t m_rto_base; - - // Timestamp tracking - uint32_t m_ts_recent, m_ts_lastack; - - // Round-trip calculation - uint32_t m_rx_rttvar, m_rx_srtt, m_rx_rto; - - // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs - uint32_t m_ssthresh, m_cwnd; - uint8_t m_dup_acks; - uint32_t m_recover; - uint32_t m_t_ack; - - // Configuration options - bool m_use_nagling; - uint32_t m_ack_delay; - - // This is used by unit tests to test backward compatibility of - // PseudoTcp implementations that don't support window scaling. - bool m_support_wnd_scale; -}; - -} // namespace webrtc - - -#endif // P2P_BASE_PSEUDO_TCP_H_ diff --git a/third_party/libwebrtc/p2p/base/pseudo_tcp_unittest.cc b/third_party/libwebrtc/p2p/base/pseudo_tcp_unittest.cc @@ -1,907 +0,0 @@ -/* - * Copyright 2011 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/base/pseudo_tcp.h" - -#include <algorithm> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <string> -#include <utility> -#include <vector> - -#include "api/array_view.h" -#include "api/task_queue/pending_task_safety_flag.h" -#include "api/task_queue/task_queue_base.h" -#include "api/test/rtc_error_matchers.h" -#include "api/units/time_delta.h" -#include "rtc_base/crypto_random.h" -#include "rtc_base/logging.h" -#include "rtc_base/memory_stream.h" -#include "rtc_base/stream.h" -#include "rtc_base/thread.h" -#include "rtc_base/time_utils.h" -#include "test/gmock.h" -#include "test/gtest.h" -#include "test/wait_until.h" - -using ::testing::IsTrue; -using ::webrtc::PseudoTcp; -using ::webrtc::ScopedTaskSafety; -using ::webrtc::TaskQueueBase; -using ::webrtc::TimeDelta; - -static const int kConnectTimeoutMs = 10000; // ~3 * default RTO of 3000ms -static const int kTransferTimeoutMs = 15000; -static const int kBlockSize = 4096; - -class PseudoTcpForTest : public webrtc::PseudoTcp { - public: - PseudoTcpForTest(webrtc::IPseudoTcpNotify* notify, uint32_t conv) - : webrtc::PseudoTcp(notify, conv) {} - - bool isReceiveBufferFull() const { - return webrtc::PseudoTcp::isReceiveBufferFull(); - } - - void disableWindowScale() { webrtc::PseudoTcp::disableWindowScale(); } -}; - -class PseudoTcpTestBase : public ::testing::Test, - public webrtc::IPseudoTcpNotify { - public: - PseudoTcpTestBase() - : local_(this, 1), - remote_(this, 1), - have_connected_(false), - have_disconnected_(false), - local_mtu_(65535), - remote_mtu_(65535), - delay_(0), - loss_(0) { - // Set use of the test RNG to get predictable loss patterns. Otherwise, - // this test would occasionally get really unlucky loss and time out. - webrtc::SetRandomTestMode(true); - } - ~PseudoTcpTestBase() override { - // Put it back for the next test. - webrtc::SetRandomTestMode(false); - } - // If true, both endpoints will send the "connect" segment simultaneously, - // rather than `local_` sending it followed by a response from `remote_`. - // Note that this is what chromoting ends up doing. - void SetSimultaneousOpen(bool enabled) { simultaneous_open_ = enabled; } - void SetLocalMtu(int mtu) { - local_.NotifyMTU(mtu); - local_mtu_ = mtu; - } - void SetRemoteMtu(int mtu) { - remote_.NotifyMTU(mtu); - remote_mtu_ = mtu; - } - void SetDelay(int delay) { delay_ = delay; } - void SetLoss(int percent) { loss_ = percent; } - // Used to cause the initial "connect" segment to be lost, needed for a - // regression test. - void DropNextPacket() { drop_next_packet_ = true; } - void SetOptNagling(bool enable_nagles) { - local_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles); - remote_.SetOption(PseudoTcp::OPT_NODELAY, !enable_nagles); - } - void SetOptAckDelay(int ack_delay) { - local_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay); - remote_.SetOption(PseudoTcp::OPT_ACKDELAY, ack_delay); - } - void SetOptSndBuf(int size) { - local_.SetOption(PseudoTcp::OPT_SNDBUF, size); - remote_.SetOption(PseudoTcp::OPT_SNDBUF, size); - } - void SetRemoteOptRcvBuf(int size) { - remote_.SetOption(PseudoTcp::OPT_RCVBUF, size); - } - void SetLocalOptRcvBuf(int size) { - local_.SetOption(PseudoTcp::OPT_RCVBUF, size); - } - void DisableRemoteWindowScale() { remote_.disableWindowScale(); } - void DisableLocalWindowScale() { local_.disableWindowScale(); } - - protected: - int Connect() { - int ret = local_.Connect(); - if (ret == 0) { - UpdateLocalClock(); - } - if (simultaneous_open_) { - ret = remote_.Connect(); - if (ret == 0) { - UpdateRemoteClock(); - } - } - return ret; - } - void Close() { - local_.Close(false); - UpdateLocalClock(); - } - - void OnTcpOpen(PseudoTcp* tcp) override { - // Consider ourselves connected when the local side gets OnTcpOpen. - // OnTcpWriteable isn't fired at open, so we trigger it now. - RTC_LOG(LS_VERBOSE) << "Opened"; - if (tcp == &local_) { - have_connected_ = true; - OnTcpWriteable(tcp); - } - } - // Test derived from the base should override - // virtual void OnTcpReadable(PseudoTcp* tcp) - // and - // virtual void OnTcpWritable(PseudoTcp* tcp) - void OnTcpClosed(PseudoTcp* tcp, uint32_t error) override { - // Consider ourselves closed when the remote side gets OnTcpClosed. - // TODO(?): OnTcpClosed is only ever notified in case of error in - // the current implementation. Solicited close is not (yet) supported. - RTC_LOG(LS_VERBOSE) << "Closed"; - EXPECT_EQ(0U, error); - if (tcp == &remote_) { - have_disconnected_ = true; - } - } - WriteResult TcpWritePacket(PseudoTcp* tcp, - const char* buffer, - size_t len) override { - // Drop a packet if the test called DropNextPacket. - if (drop_next_packet_) { - drop_next_packet_ = false; - RTC_LOG(LS_VERBOSE) << "Dropping packet due to DropNextPacket, size=" - << len; - return WR_SUCCESS; - } - // Randomly drop the desired percentage of packets. - if (webrtc::CreateRandomId() % 100 < static_cast<uint32_t>(loss_)) { - RTC_LOG(LS_VERBOSE) << "Randomly dropping packet, size=" << len; - return WR_SUCCESS; - } - // Also drop packets that are larger than the configured MTU. - if (len > static_cast<size_t>(std::min(local_mtu_, remote_mtu_))) { - RTC_LOG(LS_VERBOSE) << "Dropping packet that exceeds path MTU, size=" - << len; - return WR_SUCCESS; - } - PseudoTcp* other; - ScopedTaskSafety* timer; - if (tcp == &local_) { - other = &remote_; - timer = &remote_timer_; - } else { - other = &local_; - timer = &local_timer_; - } - std::string packet(buffer, len); - ++packets_in_flight_; - TaskQueueBase::Current()->PostDelayedTask( - [other, timer, packet = std::move(packet), this] { - --packets_in_flight_; - other->NotifyPacket(packet.c_str(), packet.size()); - UpdateClock(*other, *timer); - }, - TimeDelta::Millis(delay_)); - return WR_SUCCESS; - } - - void UpdateLocalClock() { UpdateClock(local_, local_timer_); } - void UpdateRemoteClock() { UpdateClock(remote_, remote_timer_); } - static void UpdateClock(PseudoTcp& tcp, ScopedTaskSafety& timer) { - long interval = 0; // NOLINT - tcp.GetNextClock(PseudoTcp::Now(), interval); - interval = std::max<int>(interval, 0L); // sometimes interval is < 0 - timer.reset(); - TaskQueueBase::Current()->PostDelayedTask( - SafeTask(timer.flag(), - [&tcp, &timer] { - tcp.NotifyClock(PseudoTcp::Now()); - UpdateClock(tcp, timer); - }), - TimeDelta::Millis(interval)); - } - - webrtc::AutoThread main_thread_; - PseudoTcpForTest local_; - PseudoTcpForTest remote_; - ScopedTaskSafety local_timer_; - ScopedTaskSafety remote_timer_; - webrtc::MemoryStream send_stream_; - webrtc::MemoryStream recv_stream_; - bool have_connected_; - bool have_disconnected_; - int local_mtu_; - int remote_mtu_; - int delay_; - int loss_; - bool drop_next_packet_ = false; - bool simultaneous_open_ = false; - int packets_in_flight_ = 0; -}; - -class PseudoTcpTest : public PseudoTcpTestBase { - public: - void TestTransfer(int size) { - uint32_t start; - int32_t elapsed; - size_t received; - // Create some dummy data to send. - send_stream_.ReserveSize(size); - for (int i = 0; i < size; ++i) { - uint8_t ch = static_cast<uint8_t>(i); - size_t written; - int error; - send_stream_.Write(webrtc::MakeArrayView(&ch, 1), written, error); - } - send_stream_.Rewind(); - // Prepare the receive stream. - recv_stream_.ReserveSize(size); - // Connect and wait until connected. - start = webrtc::Time32(); - EXPECT_EQ(0, Connect()); - EXPECT_THAT(webrtc::WaitUntil( - [&] { return have_connected_; }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kConnectTimeoutMs)}), - webrtc::IsRtcOk()); - // Sending will start from OnTcpWriteable and complete when all data has - // been received. - EXPECT_THAT(webrtc::WaitUntil( - [&] { return have_disconnected_; }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kTransferTimeoutMs)}), - webrtc::IsRtcOk()); - elapsed = webrtc::Time32() - start; - recv_stream_.GetSize(&received); - // Ensure we closed down OK and we got the right data. - // TODO(?): Ensure the errors are cleared properly. - // EXPECT_EQ(0, local_.GetError()); - // EXPECT_EQ(0, remote_.GetError()); - EXPECT_EQ(static_cast<size_t>(size), received); - EXPECT_EQ(0, - memcmp(send_stream_.GetBuffer(), recv_stream_.GetBuffer(), size)); - RTC_LOG(LS_INFO) << "Transferred " << received << " bytes in " << elapsed - << " ms (" << size * 8 / elapsed << " Kbps)"; - } - - private: - // IPseudoTcpNotify interface - - void OnTcpReadable(PseudoTcp* tcp) override { - // Stream bytes to the recv stream as they arrive. - if (tcp == &remote_) { - ReadData(); - - // TODO(?): OnTcpClosed() is currently only notified on error - - // there is no on-the-wire equivalent of TCP FIN. - // So we fake the notification when all the data has been read. - size_t received, required; - recv_stream_.GetPosition(&received); - send_stream_.GetSize(&required); - if (received == required) - OnTcpClosed(&remote_, 0); - } - } - void OnTcpWriteable(PseudoTcp* tcp) override { - // Write bytes from the send stream when we can. - // Shut down when we've sent everything. - if (tcp == &local_) { - RTC_LOG(LS_VERBOSE) << "Flow Control Lifted"; - bool done; - WriteData(&done); - if (done) { - Close(); - } - } - } - - void ReadData() { - char block[kBlockSize]; - size_t position; - int received; - do { - received = remote_.Recv(block, sizeof(block)); - if (received != -1) { - size_t written; - int error; - recv_stream_.Write( - webrtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), received), - written, error); - recv_stream_.GetPosition(&position); - RTC_LOG(LS_VERBOSE) << "Received: " << position; - } - } while (received > 0); - } - void WriteData(bool* done) { - size_t position, tosend; - int sent; - char block[kBlockSize]; - do { - send_stream_.GetPosition(&position); - int error; - if (send_stream_.Read(webrtc::MakeArrayView( - reinterpret_cast<uint8_t*>(block), kBlockSize), - tosend, error) != webrtc::SR_EOS) { - sent = local_.Send(block, tosend); - UpdateLocalClock(); - if (sent != -1) { - send_stream_.SetPosition(position + sent); - RTC_LOG(LS_VERBOSE) << "Sent: " << position + sent; - } else { - send_stream_.SetPosition(position); - RTC_LOG(LS_VERBOSE) << "Flow Controlled"; - } - } else { - sent = static_cast<int>(tosend = 0); - } - } while (sent > 0); - *done = (tosend == 0); - } - - private: - webrtc::MemoryStream send_stream_; - webrtc::MemoryStream recv_stream_; -}; - -class PseudoTcpTestPingPong : public PseudoTcpTestBase { - public: - PseudoTcpTestPingPong() - : iterations_remaining_(0), - sender_(nullptr), - receiver_(nullptr), - bytes_per_send_(0) {} - void SetBytesPerSend(int bytes) { bytes_per_send_ = bytes; } - void TestPingPong(int size, int iterations) { - uint32_t start, elapsed; - iterations_remaining_ = iterations; - receiver_ = &remote_; - sender_ = &local_; - // Create some dummy data to send. - send_stream_.ReserveSize(size); - for (int i = 0; i < size; ++i) { - uint8_t ch = static_cast<uint8_t>(i); - size_t written; - int error; - send_stream_.Write(webrtc::MakeArrayView(&ch, 1), written, error); - } - send_stream_.Rewind(); - // Prepare the receive stream. - recv_stream_.ReserveSize(size); - // Connect and wait until connected. - start = webrtc::Time32(); - EXPECT_EQ(0, Connect()); - EXPECT_THAT(webrtc::WaitUntil( - [&] { return have_connected_; }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kConnectTimeoutMs)}), - webrtc::IsRtcOk()); - // Sending will start from OnTcpWriteable and stop when the required - // number of iterations have completed. - EXPECT_THAT(webrtc::WaitUntil( - [&] { return have_disconnected_; }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kTransferTimeoutMs)}), - webrtc::IsRtcOk()); - elapsed = webrtc::TimeSince(start); - RTC_LOG(LS_INFO) << "Performed " << iterations << " pings in " << elapsed - << " ms"; - } - - private: - // IPseudoTcpNotify interface - - void OnTcpReadable(PseudoTcp* tcp) override { - if (tcp != receiver_) { - RTC_LOG_F(LS_ERROR) << "unexpected OnTcpReadable"; - return; - } - // Stream bytes to the recv stream as they arrive. - ReadData(); - // If we've received the desired amount of data, rewind things - // and send it back the other way! - size_t position, desired; - recv_stream_.GetPosition(&position); - send_stream_.GetSize(&desired); - if (position == desired) { - if (receiver_ == &local_ && --iterations_remaining_ == 0) { - Close(); - // TODO(?): Fake OnTcpClosed() on the receiver for now. - OnTcpClosed(&remote_, 0); - return; - } - PseudoTcp* tmp = receiver_; - receiver_ = sender_; - sender_ = tmp; - recv_stream_.Rewind(); - send_stream_.Rewind(); - OnTcpWriteable(sender_); - } - } - void OnTcpWriteable(PseudoTcp* tcp) override { - if (tcp != sender_) - return; - // Write bytes from the send stream when we can. - // Shut down when we've sent everything. - RTC_LOG(LS_VERBOSE) << "Flow Control Lifted"; - WriteData(); - } - - void ReadData() { - char block[kBlockSize]; - size_t position; - int received; - do { - received = receiver_->Recv(block, sizeof(block)); - if (received != -1) { - size_t written; - int error; - recv_stream_.Write( - webrtc::MakeArrayView(reinterpret_cast<const uint8_t*>(block), - received), - written, error); - recv_stream_.GetPosition(&position); - RTC_LOG(LS_VERBOSE) << "Received: " << position; - } - } while (received > 0); - } - void WriteData() { - size_t position, tosend; - int sent; - char block[kBlockSize]; - do { - send_stream_.GetPosition(&position); - tosend = bytes_per_send_ ? bytes_per_send_ : sizeof(block); - int error; - if (send_stream_.Read( - webrtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), tosend), - tosend, error) != webrtc::SR_EOS) { - sent = sender_->Send(block, tosend); - UpdateLocalClock(); - if (sent != -1) { - send_stream_.SetPosition(position + sent); - RTC_LOG(LS_VERBOSE) << "Sent: " << position + sent; - } else { - send_stream_.SetPosition(position); - RTC_LOG(LS_VERBOSE) << "Flow Controlled"; - } - } else { - sent = static_cast<int>(tosend = 0); - } - } while (sent > 0); - } - - private: - int iterations_remaining_; - PseudoTcp* sender_; - PseudoTcp* receiver_; - int bytes_per_send_; -}; - -// Fill the receiver window until it is full, drain it and then -// fill it with the same amount. This is to test that receiver window -// contracts and enlarges correctly. -class PseudoTcpTestReceiveWindow : public PseudoTcpTestBase { - public: - // Not all the data are transfered, `size` just need to be big enough - // to fill up the receiver window twice. - void TestTransfer(int size) { - // Create some dummy data to send. - send_stream_.ReserveSize(size); - for (int i = 0; i < size; ++i) { - uint8_t ch = static_cast<uint8_t>(i); - size_t written; - int error; - send_stream_.Write(webrtc::MakeArrayView(&ch, 1), written, error); - } - send_stream_.Rewind(); - - // Prepare the receive stream. - recv_stream_.ReserveSize(size); - - // Connect and wait until connected. - EXPECT_EQ(0, Connect()); - EXPECT_THAT(webrtc::WaitUntil( - [&] { return have_connected_; }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kConnectTimeoutMs)}), - webrtc::IsRtcOk()); - - TaskQueueBase::Current()->PostTask([this] { WriteData(); }); - EXPECT_THAT(webrtc::WaitUntil( - [&] { return have_disconnected_; }, IsTrue(), - {.timeout = webrtc::TimeDelta::Millis(kTransferTimeoutMs)}), - webrtc::IsRtcOk()); - - ASSERT_EQ(2u, send_position_.size()); - ASSERT_EQ(2u, recv_position_.size()); - - const size_t estimated_recv_window = EstimateReceiveWindowSize(); - - // The difference in consecutive send positions should equal the - // receive window size or match very closely. This verifies that receive - // window is open after receiver drained all the data. - const size_t send_position_diff = send_position_[1] - send_position_[0]; - EXPECT_GE(1024u, estimated_recv_window - send_position_diff); - - // Receiver drained the receive window twice. - EXPECT_EQ(2 * estimated_recv_window, recv_position_[1]); - } - - uint32_t EstimateReceiveWindowSize() const { - return static_cast<uint32_t>(recv_position_[0]); - } - - uint32_t EstimateSendWindowSize() const { - return static_cast<uint32_t>(send_position_[0] - recv_position_[0]); - } - - private: - // IPseudoTcpNotify interface - void OnTcpReadable(PseudoTcp* /* tcp */) override {} - - void OnTcpWriteable(PseudoTcp* /* tcp */) override {} - - void ReadUntilIOPending() { - char block[kBlockSize]; - size_t position; - int received; - - do { - received = remote_.Recv(block, sizeof(block)); - if (received != -1) { - size_t written; - int error; - recv_stream_.Write( - webrtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), received), - written, error); - recv_stream_.GetPosition(&position); - RTC_LOG(LS_VERBOSE) << "Received: " << position; - } - } while (received > 0); - - recv_stream_.GetPosition(&position); - recv_position_.push_back(position); - - // Disconnect if we have done two transfers. - if (recv_position_.size() == 2u) { - Close(); - OnTcpClosed(&remote_, 0); - } else { - WriteData(); - } - } - - void WriteData() { - size_t position, tosend; - int sent; - char block[kBlockSize]; - do { - send_stream_.GetPosition(&position); - int error; - if (send_stream_.Read( - webrtc::MakeArrayView(reinterpret_cast<uint8_t*>(block), - sizeof(block)), - tosend, error) != webrtc::SR_EOS) { - sent = local_.Send(block, tosend); - UpdateLocalClock(); - if (sent != -1) { - send_stream_.SetPosition(position + sent); - RTC_LOG(LS_VERBOSE) << "Sent: " << position + sent; - } else { - send_stream_.SetPosition(position); - RTC_LOG(LS_VERBOSE) << "Flow Controlled"; - } - } else { - sent = static_cast<int>(tosend = 0); - } - } while (sent > 0); - // At this point, we've filled up the available space in the send queue. - - if (packets_in_flight_ > 0) { - // If there are packet tasks, attempt to continue sending after giving - // those packets time to process, which should free up the send buffer. - webrtc::Thread::Current()->PostDelayedTask([this] { WriteData(); }, - TimeDelta::Millis(10)); - } else { - if (!remote_.isReceiveBufferFull()) { - RTC_LOG(LS_ERROR) << "This shouldn't happen - the send buffer is full, " - "the receive buffer is not, and there are no " - "remaining messages to process."; - } - send_stream_.GetPosition(&position); - send_position_.push_back(position); - - // Drain the receiver buffer. - ReadUntilIOPending(); - } - } - - private: - webrtc::MemoryStream send_stream_; - webrtc::MemoryStream recv_stream_; - - std::vector<size_t> send_position_; - std::vector<size_t> recv_position_; -}; - -// Basic end-to-end data transfer tests - -// Test the normal case of sending data from one side to the other. -TEST_F(PseudoTcpTest, TestSend) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - TestTransfer(1000000); -} - -// Test sending data with a 50 ms RTT. Transmission should take longer due -// to a slower ramp-up in send rate. -TEST_F(PseudoTcpTest, TestSendWithDelay) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetDelay(50); - TestTransfer(1000000); -} - -// Test sending data with packet loss. Transmission should take much longer due -// to send back-off when loss occurs. -TEST_F(PseudoTcpTest, TestSendWithLoss) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetLoss(10); - TestTransfer(100000); // less data so test runs faster -} - -// Test sending data with a 50 ms RTT and 10% packet loss. Transmission should -// take much longer due to send back-off and slower detection of loss. -TEST_F(PseudoTcpTest, TestSendWithDelayAndLoss) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetDelay(50); - SetLoss(10); - TestTransfer(100000); // less data so test runs faster -} - -// Test sending data with 10% packet loss and Nagling disabled. Transmission -// should take about the same time as with Nagling enabled. -TEST_F(PseudoTcpTest, TestSendWithLossAndOptNaglingOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetLoss(10); - SetOptNagling(false); - TestTransfer(100000); // less data so test runs faster -} - -// Regression test for bugs.webrtc.org/9208. -// -// This bug resulted in corrupted data if a "connect" segment was received after -// a data segment. This is only possible if: -// -// * The initial "connect" segment is lost, and retransmitted later. -// * Both sides send "connect"s simultaneously, such that the local side thinks -// a connection is established even before its "connect" has been -// acknowledged. -// * Nagle algorithm disabled, allowing a data segment to be sent before the -// "connect" has been acknowledged. -TEST_F(PseudoTcpTest, - TestSendWhenFirstPacketLostWithOptNaglingOffAndSimultaneousOpen) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - DropNextPacket(); - SetOptNagling(false); - SetSimultaneousOpen(true); - TestTransfer(10000); -} - -// Test sending data with 10% packet loss and Delayed ACK disabled. -// Transmission should be slightly faster than with it enabled. -TEST_F(PseudoTcpTest, TestSendWithLossAndOptAckDelayOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetLoss(10); - SetOptAckDelay(0); - TestTransfer(100000); -} - -// Test sending data with 50ms delay and Nagling disabled. -TEST_F(PseudoTcpTest, TestSendWithDelayAndOptNaglingOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetDelay(50); - SetOptNagling(false); - TestTransfer(100000); // less data so test runs faster -} - -// Test sending data with 50ms delay and Delayed ACK disabled. -TEST_F(PseudoTcpTest, TestSendWithDelayAndOptAckDelayOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetDelay(50); - SetOptAckDelay(0); - TestTransfer(100000); // less data so test runs faster -} - -// Test a large receive buffer with a sender that doesn't support scaling. -TEST_F(PseudoTcpTest, TestSendRemoteNoWindowScale) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetLocalOptRcvBuf(100000); - DisableRemoteWindowScale(); - TestTransfer(1000000); -} - -// Test a large sender-side receive buffer with a receiver that doesn't support -// scaling. -TEST_F(PseudoTcpTest, TestSendLocalNoWindowScale) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetRemoteOptRcvBuf(100000); - DisableLocalWindowScale(); - TestTransfer(1000000); -} - -// Test when both sides use window scaling. -TEST_F(PseudoTcpTest, TestSendBothUseWindowScale) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetRemoteOptRcvBuf(100000); - SetLocalOptRcvBuf(100000); - TestTransfer(1000000); -} - -// Test using a large window scale value. -TEST_F(PseudoTcpTest, TestSendLargeInFlight) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetRemoteOptRcvBuf(100000); - SetLocalOptRcvBuf(100000); - SetOptSndBuf(150000); - TestTransfer(1000000); -} - -TEST_F(PseudoTcpTest, TestSendBothUseLargeWindowScale) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetRemoteOptRcvBuf(1000000); - SetLocalOptRcvBuf(1000000); - TestTransfer(10000000); -} - -// Test using a small receive buffer. -TEST_F(PseudoTcpTest, TestSendSmallReceiveBuffer) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetRemoteOptRcvBuf(10000); - SetLocalOptRcvBuf(10000); - TestTransfer(1000000); -} - -// Test using a very small receive buffer. -TEST_F(PseudoTcpTest, TestSendVerySmallReceiveBuffer) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetRemoteOptRcvBuf(100); - SetLocalOptRcvBuf(100); - TestTransfer(100000); -} - -// Ping-pong (request/response) tests - -// Test sending <= 1x MTU of data in each ping/pong. Should take <10ms. -TEST_F(PseudoTcpTestPingPong, TestPingPong1xMtu) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - TestPingPong(100, 100); -} - -// Test sending 2x-3x MTU of data in each ping/pong. Should take <10ms. -TEST_F(PseudoTcpTestPingPong, TestPingPong3xMtu) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - TestPingPong(400, 100); -} - -// Test sending 1x-2x MTU of data in each ping/pong. -// Should take ~1s, due to interaction between Nagling and Delayed ACK. -TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtu) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - TestPingPong(2000, 5); -} - -// Test sending 1x-2x MTU of data in each ping/pong with Delayed ACK off. -// Should take <10ms. -TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithAckDelayOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptAckDelay(0); - TestPingPong(2000, 100); -} - -// Test sending 1x-2x MTU of data in each ping/pong with Nagling off. -// Should take <10ms. -TEST_F(PseudoTcpTestPingPong, TestPingPong2xMtuWithNaglingOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptNagling(false); - TestPingPong(2000, 5); -} - -// Test sending a ping as pair of short (non-full) segments. -// Should take ~1s, due to Delayed ACK interaction with Nagling. -TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegments) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptAckDelay(5000); - SetBytesPerSend(50); // i.e. two Send calls per payload - TestPingPong(100, 5); -} - -// Test sending ping as a pair of short (non-full) segments, with Nagling off. -// Should take <10ms. -TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithNaglingOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptNagling(false); - SetBytesPerSend(50); // i.e. two Send calls per payload - TestPingPong(100, 5); -} - -// Test sending <= 1x MTU of data ping/pong, in two segments, no Delayed ACK. -// Should take ~1s. -TEST_F(PseudoTcpTestPingPong, TestPingPongShortSegmentsWithAckDelayOff) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetBytesPerSend(50); // i.e. two Send calls per payload - SetOptAckDelay(0); - TestPingPong(100, 5); -} - -// Test that receive window expands and contract correctly. -TEST_F(PseudoTcpTestReceiveWindow, TestReceiveWindow) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptNagling(false); - SetOptAckDelay(0); - TestTransfer(1024 * 1000); -} - -// Test setting send window size to a very small value. -TEST_F(PseudoTcpTestReceiveWindow, TestSetVerySmallSendWindowSize) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptNagling(false); - SetOptAckDelay(0); - SetOptSndBuf(900); - TestTransfer(1024 * 1000); - EXPECT_EQ(900u, EstimateSendWindowSize()); -} - -// Test setting receive window size to a value other than default. -TEST_F(PseudoTcpTestReceiveWindow, TestSetReceiveWindowSize) { - SetLocalMtu(1500); - SetRemoteMtu(1500); - SetOptNagling(false); - SetOptAckDelay(0); - SetRemoteOptRcvBuf(100000); - SetLocalOptRcvBuf(100000); - TestTransfer(1024 * 1000); - EXPECT_EQ(100000u, EstimateReceiveWindowSize()); -} - -/* Test sending data with mismatched MTUs. We should detect this and reduce -// our packet size accordingly. -// TODO(?): This doesn't actually work right now. The current code -// doesn't detect if the MTU is set too high on either side. -TEST_F(PseudoTcpTest, TestSendWithMismatchedMtus) { - SetLocalMtu(1500); - SetRemoteMtu(1280); - TestTransfer(1000000); -} -*/ diff --git a/third_party/libwebrtc/test/DEPS b/third_party/libwebrtc/test/DEPS @@ -42,9 +42,6 @@ specific_include_rules = { ".*mdns_parser_fuzzer\.cc": [ "+p2p/base/mdns_message.h", ], - ".*pseudotcp_parser_fuzzer\.cc": [ - "+p2p/base/pseudo_tcp.h", - ], ".*stun_parser_fuzzer\.cc": [ "+p2p/base/stun.h", ], diff --git a/third_party/libwebrtc/test/fuzzers/BUILD.gn b/third_party/libwebrtc/test/fuzzers/BUILD.gn @@ -270,7 +270,7 @@ webrtc_fuzzer_test("rtp_packetizer_av1_fuzzer") { deps = [ "../../api:array_view", "../../api/video:video_frame_type", - "../../modules/rtp_rtcp:rtp_rtcp", + "../../modules/rtp_rtcp", "../../modules/rtp_rtcp:rtp_rtcp_format", "../../rtc_base:checks", ] @@ -281,7 +281,7 @@ webrtc_fuzzer_test("rtp_format_h264_fuzzer") { deps = [ "../../api:array_view", "../../api/video:video_frame_type", - "../../modules/rtp_rtcp:rtp_rtcp", + "../../modules/rtp_rtcp", "../../modules/rtp_rtcp:rtp_rtcp_format", "../../modules/video_coding:codec_globals_headers", "../../rtc_base:checks", @@ -293,7 +293,7 @@ webrtc_fuzzer_test("rtp_format_vp8_fuzzer") { deps = [ "../../api:array_view", "../../api/video:video_frame_type", - "../../modules/rtp_rtcp:rtp_rtcp", + "../../modules/rtp_rtcp", "../../modules/rtp_rtcp:rtp_rtcp_format", "../../modules/video_coding:codec_globals_headers", "../../rtc_base:checks", @@ -305,7 +305,7 @@ webrtc_fuzzer_test("rtp_format_vp9_fuzzer") { deps = [ "../../api:array_view", "../../api/video:video_frame_type", - "../../modules/rtp_rtcp:rtp_rtcp", + "../../modules/rtp_rtcp", "../../modules/rtp_rtcp:rtp_rtcp_format", "../../modules/video_coding:codec_globals_headers", "../../rtc_base:checks", @@ -523,14 +523,6 @@ webrtc_fuzzer_test("stun_validator_fuzzer") { dict = "corpora/stun.tokens" } -webrtc_fuzzer_test("pseudotcp_parser_fuzzer") { - sources = [ "pseudotcp_parser_fuzzer.cc" ] - deps = [ - "../../p2p:pseudo_tcp", - "../../rtc_base:threading", - ] -} - rtc_library("audio_processing_fuzzer_helper") { testonly = true sources = [ @@ -691,8 +683,8 @@ webrtc_fuzzer_test("rtp_frame_reference_finder_fuzzer") { "../../api/video:video_rtp_headers", "../../modules/rtp_rtcp", "../../modules/rtp_rtcp:rtp_video_header", + "../../modules/video_coding", "../../modules/video_coding:codec_globals_headers", - "../../modules/video_coding:video_coding", "../../system_wrappers", ] } @@ -854,7 +846,6 @@ group("fuzzers") { ":h264_depacketizer_fuzzer", ":neteq_rtp_fuzzer", ":neteq_signal_fuzzer", - ":pseudotcp_parser_fuzzer", ":receive_side_congestion_controller_fuzzer", ":residual_echo_detector_fuzzer", ":rtcp_receiver_fuzzer", diff --git a/third_party/libwebrtc/test/fuzzers/corpora/README b/third_party/libwebrtc/test/fuzzers/corpora/README @@ -30,8 +30,6 @@ prefixed by the byte 0xff. Some of the rtp fuzzers need to decide which header extensions to enable, and the first byte of the fuzz data is used for this. -### PseudoTCP ### -Very small corpus minimised from the unit tests. ### SCTP ### This corpus was extracted from a few manually recorder wireshark dumps. diff --git a/third_party/libwebrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc b/third_party/libwebrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016 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 <stddef.h> -#include <stdint.h> - -#include "p2p/base/pseudo_tcp.h" -#include "rtc_base/thread.h" - -namespace webrtc { -class FakeIPseudoTcpNotify : public webrtc::IPseudoTcpNotify { - public: - void OnTcpOpen(webrtc::PseudoTcp* tcp) {} - void OnTcpReadable(webrtc::PseudoTcp* tcp) {} - void OnTcpWriteable(webrtc::PseudoTcp* tcp) {} - void OnTcpClosed(webrtc::PseudoTcp* tcp, uint32_t error) {} - - webrtc::IPseudoTcpNotify::WriteResult TcpWritePacket(webrtc::PseudoTcp* tcp, - const char* buffer, - size_t len) { - return webrtc::IPseudoTcpNotify::WriteResult::WR_SUCCESS; - } -}; - -struct Environment { - explicit Environment(webrtc::IPseudoTcpNotify* notifier) - : ptcp(notifier, 0) {} - - // We need the thread to avoid some uninteresting crashes, since the - // production code expects there to be a thread object available. - webrtc::AutoThread thread; - webrtc::PseudoTcp ptcp; -}; - -Environment* env = new Environment(new FakeIPseudoTcpNotify()); - -void FuzzOneInput(const uint8_t* data, size_t size) { - env->ptcp.NotifyPacket(reinterpret_cast<const char*>(data), size); -} -} // namespace webrtc