text: /*
   *  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 RTC_BASE_SOCKETADAPTERS_H_
  #define RTC_BASE_SOCKETADAPTERS_H_
  
  #include <string>
  
  #include "rtc_base/asyncsocket.h"
  #include "rtc_base/constructormagic.h"
  #include "rtc_base/cryptstring.h"
  
  namespace rtc {
  
  struct HttpAuthContext;
  class ByteBufferReader;
  class ByteBufferWriter;
  
  ///////////////////////////////////////////////////////////////////////////////
  
  // Implements a socket adapter that can buffer and process data internally,
  // as in the case of connecting to a proxy, where you must speak the proxy
  // protocol before commencing normal socket behavior.
  class BufferedReadAdapter : public AsyncSocketAdapter {
   public:
    BufferedReadAdapter(AsyncSocket* socket, size_t buffer_size);
    ~BufferedReadAdapter() override;
  
    int Send(const void* pv, size_t cb) override;
    int Recv(void* pv, size_t cb, int64_t* timestamp) override;
  
   protected:
    int DirectSend(const void* pv, size_t cb) {
      return AsyncSocketAdapter::Send(pv, cb);
    }
  
    void BufferInput(bool on = true);
    virtual void ProcessInput(char* data, size_t* len) = 0;
  
    void OnReadEvent(AsyncSocket* socket) override;
  
   private:
    char* buffer_;
    size_t buffer_size_, data_len_;
    bool buffering_;
    RTC_DISALLOW_COPY_AND_ASSIGN(BufferedReadAdapter);
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  
  // Interface for implementing proxy server sockets.
  class AsyncProxyServerSocket : public BufferedReadAdapter {
   public:
    AsyncProxyServerSocket(AsyncSocket* socket, size_t buffer_size);
    ~AsyncProxyServerSocket() override;
    sigslot::signal2<AsyncProxyServerSocket*, const SocketAddress&>
        SignalConnectRequest;
    virtual void SendConnectResult(int err, const SocketAddress& addr) = 0;
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  
  // Implements a socket adapter that performs the client side of a
  // fake SSL handshake. Used for "ssltcp" P2P functionality.
  class AsyncSSLSocket : public BufferedReadAdapter {
   public:
    explicit AsyncSSLSocket(AsyncSocket* socket);
  
    int Connect(const SocketAddress& addr) override;
  
   protected:
    void OnConnectEvent(AsyncSocket* socket) override;
    void ProcessInput(char* data, size_t* len) override;
    RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLSocket);
  };
  
  // Implements a socket adapter that performs the server side of a
  // fake SSL handshake. Used when implementing a relay server that does "ssltcp".
  class AsyncSSLServerSocket : public BufferedReadAdapter {
   public:
    explicit AsyncSSLServerSocket(AsyncSocket* socket);
  
   protected:
    void ProcessInput(char* data, size_t* len) override;
    RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSSLServerSocket);
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  
  // Implements a socket adapter that speaks the HTTP/S proxy protocol.
  class AsyncHttpsProxySocket : public BufferedReadAdapter {
   public:
    AsyncHttpsProxySocket(AsyncSocket* socket,
                          const std::string& user_agent,
                          const SocketAddress& proxy,
                          const std::string& username,
                          const CryptString& password);
    ~AsyncHttpsProxySocket() override;
  
    // If connect is forced, the adapter will always issue an HTTP CONNECT to the
    // target address.  Otherwise, it will connect only if the destination port
    // is not port 80.
    void SetForceConnect(bool force) { force_connect_ = force; }
  
    int Connect(const SocketAddress& addr) override;
    SocketAddress GetRemoteAddress() const override;
    int Close() override;
    ConnState GetState() const override;
  
   protected:
    void OnConnectEvent(AsyncSocket* socket) override;
    void OnCloseEvent(AsyncSocket* socket, int err) override;
    void ProcessInput(char* data, size_t* len) override;
  
    bool ShouldIssueConnect() const;
    void SendRequest();
    void ProcessLine(char* data, size_t len);
    void EndResponse();
    void Error(int error);
  
   private:
    SocketAddress proxy_, dest_;
    std::string agent_, user_, headers_;
    CryptString pass_;
    bool force_connect_;
    size_t content_length_;
    int defer_error_;
    bool expect_close_;
    enum ProxyState {
      PS_INIT,
      PS_LEADER,
      PS_AUTHENTICATE,
      PS_SKIP_HEADERS,
      PS_ERROR_HEADERS,
      PS_TUNNEL_HEADERS,
      PS_SKIP_BODY,
      PS_TUNNEL,
      PS_WAIT_CLOSE,
      PS_ERROR
    } state_;
    HttpAuthContext* context_;
    std::string unknown_mechanisms_;
    RTC_DISALLOW_COPY_AND_ASSIGN(AsyncHttpsProxySocket);
  };
  
  ///////////////////////////////////////////////////////////////////////////////
  
  // Implements a socket adapter that speaks the SOCKS proxy protocol.
  class AsyncSocksProxySocket : public BufferedReadAdapter {
   public:
    AsyncSocksProxySocket(AsyncSocket* socket,
                          const SocketAddress& proxy,
                          const std::string& username,
                          const CryptString& password);
    ~AsyncSocksProxySocket() override;
  
    int Connect(const SocketAddress& addr) override;
    SocketAddress GetRemoteAddress() const override;
    int Close() override;
    ConnState GetState() const override;
  
   protected:
    void OnConnectEvent(AsyncSocket* socket) override;
    void ProcessInput(char* data, size_t* len) override;
  
    void SendHello();
    void SendConnect();
    void SendAuth();
    void Error(int error);
  
   private:
    enum State { SS_INIT, SS_HELLO, SS_AUTH, SS_CONNECT, SS_TUNNEL, SS_ERROR };
    State state_;
    SocketAddress proxy_, dest_;
    std::string user_;
    CryptString pass_;
    RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxySocket);
  };
  
  // Implements a proxy server socket for the SOCKS protocol.
  class AsyncSocksProxyServerSocket : public AsyncProxyServerSocket {
   public:
    explicit AsyncSocksProxyServerSocket(AsyncSocket* socket);
  
   private:
    void ProcessInput(char* data, size_t* len) override;
    void DirectSend(const ByteBufferWriter& buf);
  
    void HandleHello(ByteBufferReader* request);
    void SendHelloReply(uint8_t method);
    void HandleAuth(ByteBufferReader* request);
    void SendAuthReply(uint8_t result);
    void HandleConnect(ByteBufferReader* request);
    void SendConnectResult(int result, const SocketAddress& addr) override;
  
    void Error(int error);
  
    static const int kBufferSize = 1024;
    enum State {
      SS_HELLO,
      SS_AUTH,
      SS_CONNECT,
      SS_CONNECT_PENDING,
      SS_TUNNEL,
      SS_ERROR
    };
    State state_;
    RTC_DISALLOW_COPY_AND_ASSIGN(AsyncSocksProxyServerSocket);
  };
  
  }  // namespace rtc
  
  #endif  // RTC_BASE_SOCKETADAPTERS_H_
  