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_REQUEST_H_
18 #define SHILL_HTTP_REQUEST_H_
19 
20 #include <memory>
21 #include <string>
22 #include <vector>
23 
24 #include <base/callback.h>
25 #include <base/cancelable_callback.h>
26 #include <base/memory/ref_counted.h>
27 #include <base/memory/weak_ptr.h>
28 
29 #include "shill/net/byte_string.h"
30 #include "shill/net/shill_time.h"
31 #include "shill/refptr_types.h"
32 
33 namespace shill {
34 
35 class AsyncConnection;
36 class DNSClient;
37 class Error;
38 class EventDispatcher;
39 class HTTPURL;
40 struct InputData;
41 class IOHandler;
42 class IPAddress;
43 class Sockets;
44 
45 // The HTTPRequest class implements facilities for performing
46 // a simple "GET" request and returning the contents via a
47 // callback.
48 class HTTPRequest {
49  public:
50   enum Result {
51     kResultUnknown,
52     kResultInProgress,
53     kResultDNSFailure,
54     kResultDNSTimeout,
55     kResultConnectionFailure,
56     kResultConnectionTimeout,
57     kResultRequestFailure,
58     kResultRequestTimeout,
59     kResultResponseFailure,
60     kResultResponseTimeout,
61     kResultSuccess
62   };
63 
64   HTTPRequest(ConnectionRefPtr connection,
65               EventDispatcher* dispatcher,
66               Sockets* sockets);
67   virtual ~HTTPRequest();
68 
69   // Start an http GET request to the URL |url|.  Whenever any data is
70   // read from the server, |read_event_callback| is called with the
71   // current contents of the response data coming from the server.
72   // This callback could be called more than once as data arrives.
73   //
74   // When the transaction completes, |result_callback| will be called with
75   // the final status from the transaction.  It is valid for the callback
76   // function to destroy this HTTPRequest object, because at this time all
77   // object state has already been cleaned up.  |result_callback| will not be
78   // called if either the Start() call fails or if Stop() is called before
79   // the transaction completes.
80   //
81   // This (Start) function returns a failure result if the request
82   // failed during initialization, or kResultInProgress if the request
83   // has started successfully and is now in progress.
84   virtual Result Start(
85       const HTTPURL& url,
86       const base::Callback<void(const ByteString&)>& read_event_callback,
87       const base::Callback<void(Result, const ByteString&)>& result_callback);
88 
89   // Stop the current HTTPRequest.  No callback is called as a side
90   // effect of this function.
91   virtual void Stop();
92 
93   // Returns the data received so far from the server in the current
94   // request.  This data is available only while the request is active,
95   // and before the result callback is called.
response_data()96   virtual const ByteString& response_data() const { return response_data_; }
97 
98  private:
99   friend class HTTPRequestTest;
100 
101   // Time to wait for connection to remote server.
102   static const int kConnectTimeoutSeconds;
103   // Time to wait for DNS server.
104   static const int kDNSTimeoutSeconds;
105   // Time to wait for any input from server.
106   static const int kInputTimeoutSeconds;
107 
108   static const char kHTTPRequestTemplate[];
109 
110   bool ConnectServer(const IPAddress& address, int port);
111   void GetDNSResult(const Error& error, const IPAddress& address);
112   void OnConnectCompletion(bool success, int fd);
113   void OnServerReadError(const std::string& error_msg);
114   void ReadFromServer(InputData* data);
115   void SendStatus(Result result);
116   void StartIdleTimeout(int timeout_seconds, Result timeout_result);
117   void TimeoutTask();
118   void WriteToServer(int fd);
119 
120   ConnectionRefPtr connection_;
121   EventDispatcher* dispatcher_;
122   Sockets* sockets_;
123 
124   base::WeakPtrFactory<HTTPRequest> weak_ptr_factory_;
125   base::Callback<void(bool, int)> connect_completion_callback_;
126   base::Callback<void(const Error&, const IPAddress&)> dns_client_callback_;
127   base::Callback<void(InputData*)> read_server_callback_;
128   base::Callback<void(int)> write_server_callback_;
129   base::Callback<void(Result, const ByteString&)> result_callback_;
130   base::Callback<void(const ByteString&)> read_event_callback_;
131   std::unique_ptr<IOHandler> read_server_handler_;
132   std::unique_ptr<IOHandler> write_server_handler_;
133   std::unique_ptr<DNSClient> dns_client_;
134   std::unique_ptr<AsyncConnection> server_async_connection_;
135   std::string server_hostname_;
136   int server_port_;
137   int server_socket_;
138   base::CancelableClosure timeout_closure_;
139   Result timeout_result_;
140   ByteString request_data_;
141   ByteString response_data_;
142   bool is_running_;
143 
144   DISALLOW_COPY_AND_ASSIGN(HTTPRequest);
145 };
146 
147 }  // namespace shill
148 
149 #endif  // SHILL_HTTP_REQUEST_H_
150