rework client using async api
This commit is contained in:
+89
-43
@@ -1,8 +1,9 @@
|
||||
#ifndef WEBCC_CLIENT_H_
|
||||
#define WEBCC_CLIENT_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -19,18 +20,22 @@
|
||||
namespace webcc {
|
||||
|
||||
// Synchronous HTTP & HTTPS client.
|
||||
// In synchronous mode, a request won't return until the response is received
|
||||
// or timeout occurs.
|
||||
// Please don't use the same client object in multiple threads.
|
||||
// A request won't return until the response is received or timeout occurs.
|
||||
class Client {
|
||||
public:
|
||||
Client();
|
||||
|
||||
~Client() = default;
|
||||
// TODO
|
||||
#if WEBCC_ENABLE_SSL
|
||||
Client(boost::asio::io_context& io_context,
|
||||
boost::asio::ssl::context& ssl_context);
|
||||
#else
|
||||
explicit Client(boost::asio::io_context& io_context);
|
||||
#endif
|
||||
|
||||
Client(const Client&) = delete;
|
||||
Client& operator=(const Client&) = delete;
|
||||
|
||||
~Client() = default;
|
||||
|
||||
void set_ssl_verify(bool ssl_verify) {
|
||||
ssl_verify_ = ssl_verify;
|
||||
}
|
||||
@@ -41,19 +46,35 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// Set the timeout (in seconds) for reading response.
|
||||
void set_timeout(int timeout) {
|
||||
void set_connect_timeout(int timeout) {
|
||||
if (timeout > 0) {
|
||||
timeout_ = timeout;
|
||||
connect_timeout_ = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to server, send request, wait until response is received.
|
||||
Error Request(RequestPtr request, bool connect = true, bool stream = false);
|
||||
void set_read_timeout(int timeout) {
|
||||
if (timeout > 0) {
|
||||
read_timeout_ = timeout;
|
||||
}
|
||||
}
|
||||
|
||||
// Set progress callback to be informed about the read progress.
|
||||
// TODO: What about write?
|
||||
// TODO: std::move?
|
||||
void set_progress_callback(ProgressCallback callback) {
|
||||
progress_callback_ = callback;
|
||||
}
|
||||
|
||||
// Connect, send request, wait until response is received.
|
||||
Error Request(RequestPtr request, bool stream = false);
|
||||
|
||||
// Close the socket.
|
||||
void Close();
|
||||
|
||||
bool connected() const {
|
||||
return connected_;
|
||||
}
|
||||
|
||||
ResponsePtr response() const {
|
||||
return response_;
|
||||
}
|
||||
@@ -66,57 +87,82 @@ public:
|
||||
response_parser_.Init(nullptr, false);
|
||||
}
|
||||
|
||||
bool closed() const {
|
||||
return closed_;
|
||||
}
|
||||
private:
|
||||
void AsyncConnect();
|
||||
|
||||
void AsyncResolve(const std::string& default_port);
|
||||
|
||||
void OnResolve(boost::system::error_code ec,
|
||||
boost::asio::ip::tcp::resolver::results_type endpoints);
|
||||
|
||||
void OnConnect(boost::system::error_code ec, boost::asio::ip::tcp::endpoint);
|
||||
|
||||
void AsyncWrite();
|
||||
void OnWrite(boost::system::error_code ec, std::size_t length);
|
||||
|
||||
void AsyncWriteBody();
|
||||
void OnWriteBody(boost::system::error_code ec, std::size_t length);
|
||||
|
||||
void HandleWriteError(boost::system::error_code ec);
|
||||
|
||||
void AsyncRead();
|
||||
void OnRead(boost::system::error_code ec, std::size_t length);
|
||||
|
||||
void AsyncWaitDeadlineTimer(int seconds);
|
||||
void OnDeadlineTimer(boost::system::error_code ec);
|
||||
void StopDeadlineTimer();
|
||||
|
||||
void FinishRequest();
|
||||
|
||||
private:
|
||||
void Connect(RequestPtr request);
|
||||
boost::asio::io_context& io_context_;
|
||||
|
||||
void DoConnect(RequestPtr request, const std::string& default_port);
|
||||
#if WEBCC_ENABLE_SSL
|
||||
boost::asio::ssl::context& ssl_context_;
|
||||
#endif
|
||||
|
||||
void WriteRequest(RequestPtr request);
|
||||
|
||||
void ReadResponse();
|
||||
|
||||
void DoReadResponse();
|
||||
|
||||
void DoWaitTimer();
|
||||
void OnTimer(boost::system::error_code ec);
|
||||
|
||||
// Cancel any async-operations waiting on the timer.
|
||||
void CancelTimer();
|
||||
|
||||
private:
|
||||
boost::asio::io_context io_context_;
|
||||
|
||||
// Socket connection.
|
||||
std::unique_ptr<SocketBase> socket_;
|
||||
|
||||
boost::asio::ip::tcp::resolver resolver_;
|
||||
|
||||
bool request_finished_ = true;
|
||||
std::condition_variable request_cv_;
|
||||
std::mutex request_mutex_;
|
||||
|
||||
RequestPtr request_;
|
||||
|
||||
ResponsePtr response_;
|
||||
ResponseParser response_parser_;
|
||||
|
||||
// Timer for the timeout control.
|
||||
boost::asio::steady_timer timer_;
|
||||
// The length already read.
|
||||
std::size_t length_read_ = 0;
|
||||
|
||||
// The buffer for reading response.
|
||||
std::vector<char> buffer_;
|
||||
|
||||
// Verify the certificate of the peer or not (for HTTPS).
|
||||
bool ssl_verify_;
|
||||
bool ssl_verify_ = true;
|
||||
|
||||
// The size of the buffer for reading response.
|
||||
// 0 means default value will be used.
|
||||
std::size_t buffer_size_;
|
||||
std::size_t buffer_size_ = kBufferSize;
|
||||
|
||||
// Timeout (seconds) for receiving response.
|
||||
int timeout_;
|
||||
// Timeout (seconds) for connecting to server.
|
||||
// Default as 0 to disable our own control (i.e., deadline_timer_).
|
||||
int connect_timeout_ = 0;
|
||||
|
||||
// Connection closed.
|
||||
bool closed_;
|
||||
// Timeout (seconds) for reading response.
|
||||
int read_timeout_ = kMaxReadSeconds;
|
||||
|
||||
// Deadline timer canceled.
|
||||
bool timer_canceled_;
|
||||
// Deadline timer for connecting to server.
|
||||
boost::asio::steady_timer deadline_timer_;
|
||||
bool deadline_timer_stopped_ = true;
|
||||
|
||||
// Socket connected or not.
|
||||
bool connected_ = false;
|
||||
|
||||
// Progress callback (optional).
|
||||
ProgressCallback progress_callback_;
|
||||
|
||||
Error error_;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user