Home | History | Annotate | Download | only in shill
      1 //
      2 // Copyright (C) 2012 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #ifndef SHILL_HTTP_PROXY_H_
     18 #define SHILL_HTTP_PROXY_H_
     19 
     20 #include <memory>
     21 #include <string>
     22 #include <vector>
     23 
     24 #include <base/cancelable_callback.h>
     25 #include <base/memory/ref_counted.h>
     26 #include <base/memory/weak_ptr.h>
     27 
     28 #include "shill/net/byte_string.h"
     29 #include "shill/refptr_types.h"
     30 
     31 namespace shill {
     32 
     33 class AsyncConnection;
     34 class DNSClient;
     35 class Error;
     36 class EventDispatcher;
     37 struct InputData;
     38 class IOHandler;
     39 class IPAddress;
     40 class Sockets;
     41 
     42 // The HTTPProxy class implements a simple web proxy that
     43 // is bound to a specific interface and name server.  This
     44 // allows us to specify which connection a URL should be
     45 // fetched through, even though many connections
     46 // could be active at the same time.
     47 //
     48 // This service is meant to be low-performance, since we
     49 // do not want to divert resources from the rest of the
     50 // connection manager.  As such, we serve one client request
     51 // at a time.  This is probably okay since the use case is
     52 // limited -- only portal detection, activation and Cashew
     53 // are planned to be full-time users.
     54 class HTTPProxy {
     55  public:
     56   enum State {
     57     kStateIdle,
     58     kStateWaitConnection,
     59     kStateReadClientHeader,
     60     kStateLookupServer,
     61     kStateConnectServer,
     62     kStateTunnelData,
     63     kStateFlushResponse,
     64   };
     65 
     66   explicit HTTPProxy(ConnectionRefPtr connection);
     67   virtual ~HTTPProxy();
     68 
     69   // Start HTTP proxy.
     70   bool Start(EventDispatcher* dispatcher, Sockets* sockets);
     71 
     72   // Shutdown.
     73   void Stop();
     74 
     75   int proxy_port() const { return proxy_port_; }
     76 
     77  private:
     78   friend class HTTPProxyTest;
     79 
     80   // Time to wait for initial headers from client.
     81   static const int kClientHeaderTimeoutSeconds;
     82   // Time to wait for connection to remote server.
     83   static const int kConnectTimeoutSeconds;
     84   // Time to wait for DNS server.
     85   static const int kDNSTimeoutSeconds;
     86   // Default port on remote server to connect to.
     87   static const int kDefaultServerPort;
     88   // Time to wait for any input from either server or client.
     89   static const int kInputTimeoutSeconds;
     90   // Maximum clients to be kept waiting.
     91   static const size_t kMaxClientQueue;
     92   // Maximum number of header lines to accept.
     93   static const size_t kMaxHeaderCount;
     94   // Maximum length of an individual header line.
     95   static const size_t kMaxHeaderSize;
     96   // Timeout for whole transaction.
     97   static const int kTransactionTimeoutSeconds;
     98 
     99   static const char kHTTPMethodConnect[];
    100   static const char kHTTPMethodTerminator[];
    101   static const char kHTTPURLDelimiters[];
    102   static const char kHTTPURLPrefix[];
    103   static const char kHTTPVersionPrefix[];
    104   static const char kHTTPVersionErrorMsg[];
    105   static const char kInternalErrorMsg[];  // Message to send on failure.
    106 
    107   void AcceptClient(int fd);
    108   bool ConnectServer(const IPAddress& address, int port);
    109   void GetDNSResult(const Error& error, const IPAddress& address);
    110   void OnReadError(const std::string& error_msg);
    111   void OnConnectCompletion(bool success, int fd);
    112   bool ParseClientRequest();
    113   bool ProcessLastHeaderLine();
    114   bool ReadClientHeaders(InputData* data);
    115   bool ReadClientHostname(std::string* header);
    116   bool ReadClientHTTPMethod(std::string* header);
    117   bool ReadClientHTTPVersion(std::string* header);
    118   void ReadFromClient(InputData* data);
    119   void ReadFromServer(InputData* data);
    120   void SetClientResponse(int code, const std::string& type,
    121                          const std::string& content_type,
    122                          const std::string& message);
    123   void SendClientError(int code, const std::string& error);
    124   void StartIdleTimeout();
    125   void StartReceive();
    126   void StartTransmit();
    127   void StopClient();
    128   void WriteToClient(int fd);
    129   void WriteToServer(int fd);
    130 
    131   // State held for the lifetime of the proxy.
    132   State state_;
    133   ConnectionRefPtr connection_;
    134   base::WeakPtrFactory<HTTPProxy> weak_ptr_factory_;
    135   base::Callback<void(int)> accept_callback_;
    136   base::Callback<void(bool, int)> connect_completion_callback_;
    137   base::Callback<void(const Error&, const IPAddress&)> dns_client_callback_;
    138   base::Callback<void(InputData*)> read_client_callback_;
    139   base::Callback<void(InputData*)> read_server_callback_;
    140   base::Callback<void(int)> write_client_callback_;
    141   base::Callback<void(int)> write_server_callback_;
    142 
    143   // State held while proxy is started (even if no transaction is active).
    144   std::unique_ptr<IOHandler> accept_handler_;
    145   EventDispatcher* dispatcher_;
    146   std::unique_ptr<DNSClient> dns_client_;
    147   int proxy_port_;
    148   int proxy_socket_;
    149   std::unique_ptr<AsyncConnection> server_async_connection_;
    150   Sockets* sockets_;
    151 
    152   // State held while proxy is started and a transaction is active.
    153   int client_socket_;
    154   std::string client_method_;
    155   std::string client_version_;
    156   int server_port_;
    157   int server_socket_;
    158   bool is_route_requested_;
    159   base::CancelableClosure idle_timeout_;
    160   base::CancelableClosure transaction_timeout_;
    161   std::vector<std::string> client_headers_;
    162   std::string server_hostname_;
    163   ByteString client_data_;
    164   ByteString server_data_;
    165   std::unique_ptr<IOHandler> read_client_handler_;
    166   std::unique_ptr<IOHandler> write_client_handler_;
    167   std::unique_ptr<IOHandler> read_server_handler_;
    168   std::unique_ptr<IOHandler> write_server_handler_;
    169 
    170   DISALLOW_COPY_AND_ASSIGN(HTTPProxy);
    171 };
    172 
    173 }  // namespace shill
    174 
    175 #endif  // SHILL_HTTP_PROXY_H_
    176