master
Chunting Gu 6 years ago
commit 7e3da65e73

@ -158,9 +158,6 @@ void Client::WriteRequest(RequestPtr request) {
void Client::ReadResponse() {
LOG_VERB("Read response (timeout: %ds)...", timeout_);
timer_.expires_after(std::chrono::seconds(timeout_));
DoWaitTimer();
DoReadResponse();
if (!error_) {
@ -179,26 +176,25 @@ void Client::DoReadResponse() {
length = inner_length;
};
// Read the first piece of data asynchronously so that the timer could also
// be async-waited.
socket_->AsyncReadSome(std::move(handler), &buffer_);
while (true) {
ec = boost::asio::error::would_block;
length = 0;
socket_->AsyncReadSome(std::move(handler), &buffer_);
// Block until the asynchronous operation has completed.
do {
io_context_.run_one();
} while (ec == boost::asio::error::would_block);
// Start the timer.
DoWaitTimer();
// Now we have read the first piece of data.
// The left data will be read synchronously to void stack overflow because of
// too many recursive calls.
// Block until the asynchronous operation has completed.
do {
io_context_.run_one();
} while (ec == boost::asio::error::would_block);
// Stop the timer.
CancelTimer();
// Stop the timer.
CancelTimer();
do {
// The error normally is caused by timeout. See OnTimer().
if (ec || length == 0) {
// For the first async-read, the error normally is caused by timeout.
// See OnTimer().
Close();
error_.Set(Error::kSocketReadError, "Socket read error");
LOG_ERRO("Socket read error (%s).", ec.message().c_str());
@ -230,15 +226,12 @@ void Client::DoReadResponse() {
LOG_INFO("Finished to read the HTTP response.");
break;
}
// Read next piece of data synchronously.
socket_->ReadSome(&buffer_, &length, &ec);
} while (true);
}
}
void Client::DoWaitTimer() {
LOG_VERB("Wait timer asynchronously.");
timer_.expires_after(std::chrono::seconds(timeout_));
timer_.async_wait(std::bind(&Client::OnTimer, this, std::placeholders::_1));
}

@ -19,6 +19,13 @@ Connection::Connection(tcp::socket socket, ConnectionPool* pool,
void Connection::Start() {
request_.reset(new Request{});
boost::system::error_code ec;
auto endpoint = socket_.remote_endpoint(ec);
if (!ec) {
request_->set_ip(endpoint.address().to_string());
}
request_parser_.Init(request_.get(), view_matcher_);
DoRead();
}

@ -55,6 +55,14 @@ public:
args_ = args;
}
const std::string& ip() const {
return ip_;
}
void set_ip(const std::string& ip) {
ip_ = ip;
}
// Check if the body is a multi-part form data.
bool IsForm() const;
@ -73,6 +81,9 @@ private:
// The URL regex matched arguments (usually resource ID's).
// Used by server only.
UrlArgs args_;
// Client IP address.
std::string ip_;
};
using RequestPtr = std::shared_ptr<Request>;

@ -98,12 +98,17 @@ std::string EncodeImpl(const std::string& raw, // UTF8
return encoded;
}
// Our own implementation of alpha numeric instead of std::isalnum to avoid
// taking locale into account.
inline bool IsAlNum(int c) {
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
// Characters that are allowed in a URI but do not have a reserved purpose are
// are called unreserved. These include uppercase and lowercase letters, decimal
// digits, hyphen, period, underscore, and tilde.
inline bool IsUnreserved(int c) {
return std::isalnum((unsigned char)c) || c == '-' || c == '.' || c == '_' ||
c == '~';
return IsAlNum((unsigned char)c) || c == '-' || c == '.' || c == '_' || c == '~';
}
// General delimiters serve as the delimiters between different uri components.

Loading…
Cancel
Save