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