diff options
Diffstat (limited to 'third_party/libwebrtc/p2p/base/pseudo_tcp.h')
-rw-r--r-- | third_party/libwebrtc/p2p/base/pseudo_tcp.h | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/third_party/libwebrtc/p2p/base/pseudo_tcp.h b/third_party/libwebrtc/p2p/base/pseudo_tcp.h new file mode 100644 index 0000000000..65b54ba125 --- /dev/null +++ b/third_party/libwebrtc/p2p/base/pseudo_tcp.h @@ -0,0 +1,295 @@ +/* + * 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 <stddef.h> +#include <stdint.h> + +#include <list> +#include <memory> + +#include "rtc_base/synchronization/mutex.h" +#include "rtc_base/system/rtc_export.h" + +namespace cricket { + +////////////////////////////////////////////////////////////////////// +// 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 webrtc::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 cricket + +#endif // P2P_BASE_PSEUDO_TCP_H_ |