You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
4.0 KiB
C++
166 lines
4.0 KiB
C++
#ifndef WEBCC_CLIENT_BASE_H_
|
|
#define WEBCC_CLIENT_BASE_H_
|
|
|
|
#include <condition_variable>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "boost/asio/io_context.hpp"
|
|
#include "boost/asio/ip/tcp.hpp"
|
|
#include "boost/asio/steady_timer.hpp"
|
|
|
|
#include "webcc/globals.h"
|
|
#include "webcc/request.h"
|
|
#include "webcc/response.h"
|
|
#include "webcc/response_parser.h"
|
|
#include "webcc/socket_base.h"
|
|
|
|
namespace webcc {
|
|
|
|
class ClientBase {
|
|
public:
|
|
explicit ClientBase(boost::asio::io_context& io_context);
|
|
|
|
ClientBase(const ClientBase&) = delete;
|
|
ClientBase& operator=(const ClientBase&) = delete;
|
|
|
|
~ClientBase() = default;
|
|
|
|
void set_buffer_size(std::size_t buffer_size) {
|
|
if (buffer_size > 0) {
|
|
buffer_size_ = buffer_size;
|
|
}
|
|
}
|
|
|
|
void set_connect_timeout(int timeout) {
|
|
if (timeout > 0) {
|
|
connect_timeout_ = timeout;
|
|
}
|
|
}
|
|
|
|
void set_read_timeout(int timeout) {
|
|
if (timeout > 0) {
|
|
read_timeout_ = timeout;
|
|
}
|
|
}
|
|
|
|
// Set progress callback to be informed about the read progress.
|
|
// NOTE: Don't use move semantics because in practice, there is no difference
|
|
// between copying and moving an object of a closure type.
|
|
// TODO: Support write progress
|
|
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 connection.
|
|
// The async operation on the socket will be canceled.
|
|
void Close();
|
|
|
|
bool connected() const {
|
|
return connected_;
|
|
}
|
|
|
|
ResponsePtr response() const {
|
|
return response_;
|
|
}
|
|
|
|
// Reset response object.
|
|
// Used to make sure the response object will released even the client object
|
|
// itself will be cached for keep-alive purpose.
|
|
void Reset() {
|
|
response_.reset();
|
|
response_parser_.Init(nullptr, false);
|
|
}
|
|
|
|
protected:
|
|
// Create Socket or SslSocket.
|
|
virtual void CreateSocket() = 0;
|
|
|
|
// Resolve host.
|
|
virtual void Resolve() = 0;
|
|
|
|
void CloseSocket();
|
|
|
|
void AsyncResolve(string_view 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 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();
|
|
|
|
protected:
|
|
boost::asio::io_context& io_context_;
|
|
|
|
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_;
|
|
|
|
// The length already read.
|
|
std::size_t length_read_ = 0;
|
|
|
|
// The buffer for reading response.
|
|
std::vector<char> buffer_;
|
|
|
|
// The size of the buffer for reading response.
|
|
// 0 means default value will be used.
|
|
std::size_t buffer_size_ = kBufferSize;
|
|
|
|
// Timeout (seconds) for connecting to server.
|
|
// Default as 0 to disable our own control (i.e., deadline_timer_).
|
|
int connect_timeout_ = 0;
|
|
|
|
// Timeout (seconds) for reading response.
|
|
int read_timeout_ = kMaxReadSeconds;
|
|
|
|
// 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_;
|
|
|
|
// Current error.
|
|
Error error_;
|
|
};
|
|
|
|
using ClientPtr = std::shared_ptr<ClientBase>;
|
|
|
|
} // namespace webcc
|
|
|
|
#endif // WEBCC_CLIENT_BASE_H_
|