| // 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_ |