rework client using async api

This commit is contained in:
Chunting Gu
2021-04-16 19:07:31 +08:00
parent 7f345b7a4e
commit f5210ba1a2
27 changed files with 855 additions and 522 deletions
+89 -43
View File
@@ -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_;
};