// 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() 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;

  DISALLOW_COPY_AND_ASSIGN(ConnectionDelegate);
};

}  // namespace http_server

}  // namespace p2p

#endif  // P2P_HTTP_SERVER_CONNECTION_DELEGATE_H_
