// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// The QuicHttpProxyBackendStream instance manages an instance of
// net::URLRequest to initiate a single HTTP call to the backend. It also
// implements the callbacks of net::URLRequest to receive the response. It is
// instantiated by a delegate (for instance, the QuicSimpleServerStream class)
// when a complete HTTP request is received within a single QUIC stream.
// However, the instance is owned by QuicHttpProxyBackend, that destroys it
// safely on the quic proxy thread. Upon receiving a response (success or
// failed), the response headers and body are posted back to the main thread. In
// the main thread, the QuicHttpProxyBackendStream instance calls the interface,
// that is implemented by the delegate to return the response headers and body.
// In addition to managing the HTTP request/response to the backend, it
// translates the quic_spdy headers to/from HTTP headers for the backend.
//

#ifndef NET_TOOLS_QUIC_QUIC_HTTP_PROXY_BACKEND_STREAM_H_
#define NET_TOOLS_QUIC_QUIC_HTTP_PROXY_BACKEND_STREAM_H_

#include <memory>

#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "net/base/request_priority.h"
#include "net/base/upload_data_stream.h"
#include "net/url_request/url_request.h"

#include "net/third_party/quic/tools/quic_backend_response.h"
#include "net/third_party/quic/tools/quic_simple_server_backend.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
#include "net/tools/quic/quic_http_proxy_backend.h"

namespace base {
class SequencedTaskRunner;
class SingleThreadTaskRunner;
}  // namespace base

namespace quic {
class QuicBackendResponse;
class QuicSimpleServerBackend;
}  // namespace quic

namespace net {

class HttpRequestHeaders;
class SSLCertRequestInfo;
class SSLInfo;
class UploadDataStream;

class QuicHttpProxyBackend;

// An adapter for making HTTP requests to net::URLRequest.
class QuicHttpProxyBackendStream : public net::URLRequest::Delegate {
 public:
  QuicHttpProxyBackendStream(QuicHttpProxyBackend* context);
  ~QuicHttpProxyBackendStream() override;

  static const std::set<std::string> kHopHeaders;
  static const int kBufferSize;
  static const int kProxyHttpBackendError;
  static const std::string kDefaultQuicPeerIP;

  // Set callbacks to be called from this to the main (quic) thread.
  // A |delegate| may be NULL.
  // If set_delegate() is called multiple times, only the last delegate will be
  // used.
  void set_delegate(quic::QuicSimpleServerBackend::RequestHandler* delegate);
  void reset_delegate() { delegate_ = nullptr; }

  void Initialize(quic::QuicConnectionId quic_connection_id,
                  quic::QuicStreamId quic_stream_id,
                  std::string quic_peer_ip);

  virtual bool SendRequestToBackend(
      const spdy::SpdyHeaderBlock* incoming_request_headers,
      const std::string& incoming_body);

  quic::QuicConnectionId quic_connection_id() const {
    return quic_connection_id_;
  }
  quic::QuicStreamId quic_stream_id() const { return quic_stream_id_; }

  const net::HttpRequestHeaders& request_headers() const {
    return request_headers_;
  }
  // Releases all resources for the request and deletes the object itself.
  virtual void CancelRequest();

  // net::URLRequest::Delegate implementations:
  void OnReceivedRedirect(net::URLRequest* request,
                          const net::RedirectInfo& redirect_info,
                          bool* defer_redirect) override;
  void OnCertificateRequested(
      net::URLRequest* request,
      net::SSLCertRequestInfo* cert_request_info) override;
  void OnSSLCertificateError(net::URLRequest* request,
                             const net::SSLInfo& ssl_info,
                             bool fatal) override;
  void OnResponseStarted(net::URLRequest* request, int net_error) override;
  void OnReadCompleted(net::URLRequest* request, int bytes_read) override;

  bool ResponseIsCompleted() const { return response_completed_; }
  quic::QuicBackendResponse* GetBackendResponse() const;

 private:
  void StartOnBackendThread();
  void SendRequestOnBackendThread();
  void ReadOnceTask();
  void OnResponseCompleted();
  void CopyHeaders(const spdy::SpdyHeaderBlock* incoming_request_headers);
  bool ValidateHttpMethod(std::string method);
  bool AddRequestHeader(std::string name, std::string value);
  // Adds a request body to the request before it starts.
  void SetUpload(std::unique_ptr<net::UploadDataStream> upload);
  void SendResponseOnDelegateThread();
  void ReleaseRequest();
  spdy::SpdyHeaderBlock getAsQuicHeaders(net::HttpResponseHeaders* resp_headers,
                                         int response_code,
                                         uint64_t response_decoded_body_size);

  // The quic proxy backend context
  QuicHttpProxyBackend* proxy_context_;
  // Send back the response from the backend to |delegate_|
  quic::QuicSimpleServerBackend::RequestHandler* delegate_;
  // Task runner for interacting with the delegate
  scoped_refptr<base::SequencedTaskRunner> delegate_task_runner_;
  // Task runner for the proxy network operations.
  scoped_refptr<base::SingleThreadTaskRunner> quic_proxy_task_runner_;

  // The corresponding QUIC conn/client/stream
  quic::QuicConnectionId quic_connection_id_;
  quic::QuicStreamId quic_stream_id_;
  std::string quic_peer_ip_;

  // Url, method and spec for making a http request to the Backend
  GURL url_;
  std::string method_type_;
  net::HttpRequestHeaders request_headers_;
  std::unique_ptr<net::UploadDataStream> upload_;
  std::unique_ptr<net::URLRequest> url_request_;

  // Buffers that holds the response body
  scoped_refptr<IOBuffer> buf_;
  std::string data_received_;
  bool response_completed_;
  // Response and push resources received from the backend
  bool headers_set_;
  std::unique_ptr<quic::QuicBackendResponse> quic_response_;

  base::WeakPtrFactory<QuicHttpProxyBackendStream> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(QuicHttpProxyBackendStream);
};

}  // namespace net

#endif  // NET_TOOLS_QUIC_QUIC_HTTP_PROXY_BACKEND_STREAM_H_
