Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #ifndef __HTTP_CLIENT_H__
6 : #define __HTTP_CLIENT_H__
7 :
8 : #include <mutex>
9 : #include <string>
10 :
11 : #include <boost/asio/ip/tcp.hpp>
12 : #include <boost/function.hpp>
13 : #include <boost/ptr_container/ptr_map.hpp>
14 : #include <boost/system/error_code.hpp>
15 : #include <curl/curl.h>
16 : #include "base/queue_task.h"
17 : #include "base/timer.h"
18 : #include "io/tcp_server.h"
19 : #include "io/tcp_session.h"
20 : #include "http_parser/http_parser.h"
21 :
22 : class LifetimeActor;
23 : class LifetimeManager;
24 : class HttpClient;
25 : class HttpConnection;
26 : struct _ConnInfo;
27 : struct _GlobalInfo;
28 :
29 : enum Event {
30 : EVENT_NONE,
31 : ACCEPT,
32 : CONNECT_COMPLETE,
33 : CONNECT_FAILED,
34 : CLOSE
35 : };
36 :
37 : typedef boost::function<void()> EnqueuedCb;
38 : class HttpClientSession : public TcpSession {
39 : public:
40 : typedef boost::function<void(HttpClientSession *session,
41 : TcpSession::Event event)> SessionEventCb;
42 : typedef boost::intrusive_ptr<TcpSession> TcpSessionPtr;
43 :
44 : HttpClientSession(HttpClient *client, Socket *socket);
45 0 : virtual ~HttpClientSession() { assert(delete_called_ != 0xdeadbeaf); delete_called_ = 0xdeadbeaf; }
46 : virtual void OnRead(Buffer buffer);
47 : void RegisterEventCb(SessionEventCb cb);
48 :
49 0 : void SetConnection(HttpConnection *conn) { connection_ = conn; }
50 46 : HttpConnection *Connection() { return connection_; }
51 0 : std::mutex &mutex() { return mutex_; }
52 :
53 : private:
54 : void OnEvent(TcpSession *session, Event event);
55 : void OnEventInternal(TcpSessionPtr session, Event event);
56 : HttpConnection *connection_;
57 : uint32_t delete_called_;
58 : std::mutex mutex_;
59 : SessionEventCb event_cb_;
60 :
61 : DISALLOW_COPY_AND_ASSIGN(HttpClientSession);
62 : };
63 :
64 : class HttpConnection {
65 : public:
66 : HttpConnection(boost::asio::ip::tcp::endpoint, size_t id, HttpClient *client);
67 : HttpConnection(const std::string& host, int port, size_t id, HttpClient *client);
68 : ~HttpConnection();
69 :
70 : int Initialize();
71 :
72 : typedef boost::function<void(std::string &, boost::system::error_code &)> HttpCb;
73 :
74 : int HttpPut(const std::string &put_string, const std::string &path, HttpCb);
75 : int HttpPut(const std::string &put_string, const std::string &path,
76 : bool header, bool short_timeout, bool reuse,
77 : std::vector<std::string> &hdr_options, HttpCb cb);
78 : int HttpPost(const std::string &post_string, const std::string &path,
79 : HttpCb);
80 : int HttpPost(const std::string &post_string, const std::string &path,
81 : bool header, bool short_timeout, bool reuse,
82 : std::vector<std::string> &hdr_options, HttpCb cb);
83 : int HttpGet(const std::string &path, HttpCb);
84 : int HttpGet(const std::string &path, bool header, bool short_timeout,
85 : bool reuse, std::vector<std::string> &hdr_options, HttpCb cb);
86 : int HttpHead(const std::string &path, bool header, bool short_timeout,
87 : bool reuse, std::vector<std::string> &hdr_options, HttpCb cb);
88 : int HttpDelete(const std::string &path, HttpCb);
89 : int HttpDelete(const std::string &path, bool header, bool short_timeout,
90 : bool reuse, std::vector<std::string> &hdr_options,
91 : HttpCb cb);
92 : int Status() { return status_; }
93 : std::string Version() { return version_; }
94 : std::string Reason() { return reason_; }
95 : std::map<std::string, std::string> *Headers() { return &headers_; }
96 : void ClearCallback();
97 :
98 0 : struct _ConnInfo *curl_handle() { return curl_handle_; }
99 0 : std::map<CURLoption, int> *curl_options() { return &curl_options_; }
100 92 : HttpClient *client() { return client_; }
101 0 : HttpClientSession *session() { return session_; }
102 : std::mutex &mutex() { return mutex_; }
103 0 : boost::asio::ip::tcp::endpoint endpoint() { return endpoint_; }
104 0 : size_t id() { return id_; }
105 :
106 : const std::string &GetData();
107 0 : void set_curl_handle(struct _ConnInfo *handle) { curl_handle_ = handle; }
108 : HttpClientSession *CreateSession();
109 : void set_session(HttpClientSession *session);
110 : void delete_session();
111 : void AssignData(const char *ptr, size_t size);
112 : void AssignHeader(const char *ptr, size_t size);
113 : void UpdateOffset(size_t bytes);
114 : size_t GetOffset();
115 0 : HttpCb HttpClientCb() { return cb_; }
116 16 : void RegisterEventCb(HttpClientSession::SessionEventCb cb) { event_cb_ = cb; }
117 0 : void set_use_ssl(bool ssl_flag) { use_ssl_ = ssl_flag; }
118 0 : bool use_ssl() { return use_ssl_; }
119 0 : void set_client_cert(const std::string &client_cert) {
120 0 : client_cert_.assign(client_cert);
121 0 : }
122 0 : void set_client_cert_type(const std::string &client_cert_type) {
123 0 : client_cert_type_.assign(client_cert_type);
124 0 : }
125 0 : void set_client_key(const std::string &client_key) {
126 0 : client_key_.assign(client_key);
127 0 : }
128 0 : void set_ca_cert(const std::string &ca_cert) {
129 0 : ca_cert_.assign(ca_cert);
130 0 : }
131 :
132 : private:
133 : std::string make_url(std::string &path);
134 :
135 0 : unsigned short bool2bf(bool header, bool short_timeout, bool reuse) {
136 0 : return (header ? 1 << 2 : 0) | (short_timeout ? 1 << 1 : 0) |
137 0 : (reuse ? 1 : 0);
138 : }
139 0 : void bf2bool(unsigned short bf, bool &header, bool &short_timeout,
140 : bool &reuse) {
141 0 : header = (bf & 4u) != 0;
142 0 : short_timeout = (bf & 2u) != 0;
143 0 : reuse = (bf & 1u) != 0;
144 0 : }
145 : void HttpProcessInternal(const std::string body, std::string path,
146 : //bool header, bool short_timeout, bool reuse,
147 : unsigned short header_shortTimeout_reuse,
148 : std::vector<std::string> hdr_options,
149 : HttpCb cb, http_method m);
150 :
151 : // key = endpoint_ + id_
152 : const std::string host_;
153 : boost::asio::ip::tcp::endpoint endpoint_;
154 : size_t id_;
155 : HttpCb cb_;
156 : size_t offset_;
157 : std::string buf_;
158 : struct _ConnInfo *curl_handle_;
159 : std::map<CURLoption, int> curl_options_;
160 : HttpClientSession *session_;
161 : HttpClient *client_;
162 : mutable std::mutex mutex_;
163 : HttpClientSession::SessionEventCb event_cb_;
164 : int status_;
165 : std::string version_;
166 : std::string reason_;
167 : std::map<std::string, std::string> headers_;
168 : bool sent_hdr_; // backward compatibility
169 : bool use_ssl_; // ssl flag
170 : std::string client_cert_; // client certificate path
171 : std::string client_cert_type_; // certificate type
172 : std::string client_key_; // client key path
173 : std::string ca_cert_; // ca certificate path
174 : enum HTTPHeaderDataState {
175 : STATUS = 142,
176 : HEADER,
177 : } state_;
178 :
179 : DISALLOW_COPY_AND_ASSIGN(HttpConnection);
180 : };
181 :
182 : // Http Client class
183 : class HttpClient : public TcpServer {
184 : public:
185 : static const uint32_t kDefaultTimeout = 1; // one millisec
186 :
187 : explicit HttpClient(EventManager *evm, std::string task_name=std::string(
188 : "http client"));
189 : virtual ~HttpClient();
190 :
191 : void Init();
192 : void Shutdown();
193 : void SessionShutdown();
194 :
195 : virtual TcpSession *CreateSession();
196 : HttpConnection *CreateConnection(boost::asio::ip::tcp::endpoint);
197 : HttpConnection *CreateConnection(const std::string& host, int port);
198 :
199 : bool AddConnection(HttpConnection *);
200 : void RemoveConnection(HttpConnection *);
201 :
202 :
203 : void ProcessEvent(EnqueuedCb cb);
204 1 : struct _GlobalInfo *GlobalInfo() { return gi_; }
205 : boost::asio::io_context *io_service();
206 :
207 : void StartTimer(long);
208 : void CancelTimer();
209 :
210 : bool IsErrorHard(const boost::system::error_code &ec);
211 :
212 : protected:
213 : virtual TcpSession *AllocSession(Socket *socket);
214 :
215 : private:
216 : void TimerErrorHandler(std::string name, std::string error);
217 : void RemoveConnectionInternal(HttpConnection *);
218 : bool DequeueEvent(EnqueuedCb);
219 : void ShutdownInternal();
220 :
221 : typedef boost::asio::ip::tcp::endpoint endpoint;
222 : typedef std::pair<endpoint, size_t> Key;
223 : typedef boost::ptr_map<Key, HttpConnection> HttpConnectionMap;
224 :
225 : bool TimerCb();
226 : struct _GlobalInfo *gi_;
227 : Timer *curl_timer_;
228 : HttpConnectionMap map_;
229 : size_t id_;
230 :
231 : WorkQueue<EnqueuedCb> work_queue_;
232 :
233 : DISALLOW_COPY_AND_ASSIGN(HttpClient);
234 : };
235 :
236 : #endif
|