// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef P2P_HTTP_SERVER_CONNECTION_DELEGATE_H_
#define P2P_HTTP_SERVER_CONNECTION_DELEGATE_H_

#include <glib.h>

#include <map>
#include <string>

#include <base/command_line.h>
#include <base/threading/simple_thread.h>

#include "p2p/common/server_message.h"
#include "p2p/http_server/connection_delegate_interface.h"

namespace p2p {

namespace http_server {

class ServerInterface;

// Class used for handling a single HTTP connection.
class ConnectionDelegate : public ConnectionDelegateInterface {
 public:
  // Constructs a new ConnectionDelegate object.
  //
  // Use base::DelegateSimpleThreadPool()'s AddWork() method to start
  // handling the connection.
  ConnectionDelegate(int dirfd,
                     int fd,
                     const std::string& pretty_addr,
                     ServerInterface* server,
                     int64_t max_download_rate);
  ConnectionDelegate(const ConnectionDelegate&) = delete;
  ConnectionDelegate& operator=(const ConnectionDelegate&) = delete;

  ~ConnectionDelegate() override;

  // A ConnectionDelegate factory.
  static ConnectionDelegateInterface* Construct(int dirfd,
                                                int fd,
                                                const std::string& pretty_addr,
                                                ServerInterface* server,
                                                int64_t max_download_rate);

  // Overrides DelegateSimpleThread::Delegate
  // Run() handles the connection passed on Construct() and deletes
  // itself when the work is done.
  void Run() override;

 private:
  // Reads from the socket until a '\n' character is encountered
  // and appends the data to |str| (including the '\n' character)
  // and returns true on success.
  //
  // Fails if the line is longer than kMaxLineLength or no complete
  // line was read and the socket is closed.
  bool ReadLine(std::string* str);

  // Reads data from the other peer and - if the data is a valid HTTP 1.1
  // request - send a response. As for what is a valid HTTP/1.1 request,
  // see RFC 2616
  //
  //  http://www.ietf.org/rfc/rfc2616.txt
  //
  // For reference, a typical HTTP 1.1 request is shown here
  //
  //  GET / HTTP/1.1\r\n
  //  User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0
  //   OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3\r\n
  //  Host: localhost:16725\r\n
  //  Accept: */*\r\n
  //  \r\n
  //
  // where \r\n is represents the two byte sequence 0x0d 0x0a.
  // Returns the result of the served request.
  p2p::util::P2PServerRequestResult ParseHttpRequest();

  // Handles a HTTP request - called by ParseHttpRequest() if the data
  // read from the other peer is a valid HTTP 1.1 request.
  // Returns the result of the served request.
  p2p::util::P2PServerRequestResult ServiceHttpRequest(
      const std::string& method,
      const std::string& uri,
      const std::string& http_version,
      const std::map<std::string, std::string>& headers);

  // Sends |num_bytes_to_send_bytes| from the file represented by the
  // file descriptor |file_fd|. Returns false if an error occurs while
  // doing this.
  //
  // The implementation will read |kPayloadBufferSize| at once (except
  // for at the end where it is clipped accordingly) and send this
  // to the other end.
  //
  // If read(2) returns EOF, will sleep for one second and then retry.
  // This is for situations where the final file size is known in
  // advance (e.g. read from the user.cros-p2p-filesize xattr) but
  // all content has not yet been downloaded.
  //
  // The implementation will limit download speed by sleeping after
  // sending each chunk, if necessary. See the |max_download_rate_|
  // instance variable.
  bool SendFile(int file_fd, size_t num_bytes_to_send);

  // Sends the metrics associated with the last SendFile() call.
  void ReportSendFileMetrics(bool send_file_result);

  // Sends a HTTP response.
  bool SendResponse(int http_response_code,
                    const std::string& http_response_status,
                    const std::map<std::string, std::string>& headers,
                    const std::string& body);

  // Sends a simple HTTP response.
  bool SendSimpleResponse(int http_response_code,
                          const std::string& http_response_status);

  // Checks if the other end-point is still connected.
  bool IsStillConnected();

  // Generates a HTML document with a directory listing of the
  // .p2p files available.
  std::string GenerateIndexDotHtml();

  // The passed-in file descriptor for the directory we're serving
  // files from.
  int dirfd_;

  // The file descriptor for the socket.
  int fd_;

  // A textual representation (e.g. literal IPv4 or IPv6 address) of the
  // other endpoint of the socket.
  std::string pretty_addr_;

  // A pointer to the Server object to call ConenectionTerminated()
  // on when done serving.
  ServerInterface* server_;

  // The maximum allowed download rate (in bytes/second) or 0 if there
  // is no limit.
  int64_t max_download_rate_;

  // The total number of bytes sent by this connection delegate. Used to
  // report metrics.
  size_t total_bytes_sent_;

  // The total time spent to send |total_bytes_send_| during the last
  // call to SendFile(). Used to report metrics.
  base::TimeDelta total_time_spent_;

  // Maximum number of headers support in HTTP request.
  static const unsigned int kMaxHeaders = 100;

  // Maximum length of the request line and header lines.
  static const unsigned int kMaxLineLength = 1000;

  // Number of bytes to read at once when processing HTTP headers.
  static const unsigned int kLineBufSize = 256;

  // Number of bytes to read/send at once. With a max speed of 125
  // kB/s - see common/constants.h - 64 KiB works out to sending
  // approximately twice a second.
  //
  // TODO(zeuthen): Verify this is a good buffer size e.g. that it's a
  // good tradeoff between wakeups and smooth streaming. Many factors to
  // consider here. This is tracked in
  //
  // https://code.google.com/p/chromium/issues/detail?id=246325
  static const unsigned int kPayloadBufferSize = 65536;
};

}  // namespace http_server

}  // namespace p2p

#endif  // P2P_HTTP_SERVER_CONNECTION_DELEGATE_H_
