Fixes #142: a new socket is created when a https connection is reconnected, since a second SSL handshake cannot be made on the same socket. Also now removing failed connections from the connections collection.

This commit is contained in:
eidheim 2017-07-15 07:30:27 +02:00
commit eeaf66cf2c
3 changed files with 57 additions and 71 deletions

View file

@ -2,9 +2,9 @@
#define CLIENT_HTTP_HPP #define CLIENT_HTTP_HPP
#include "utility.hpp" #include "utility.hpp"
#include <condition_variable>
#include <mutex> #include <mutex>
#include <random> #include <random>
#include <unordered_set>
#include <vector> #include <vector>
#ifdef USE_STANDALONE_ASIO #ifdef USE_STANDALONE_ASIO
@ -384,7 +384,7 @@ namespace SimpleWeb {
std::unique_ptr<asio::ip::tcp::resolver::query> query; std::unique_ptr<asio::ip::tcp::resolver::query> query;
std::vector<std::shared_ptr<Connection>> connections; std::unordered_set<std::shared_ptr<Connection>> connections;
std::mutex connections_mutex; std::mutex connections_mutex;
std::shared_ptr<bool> cancel_handlers; std::shared_ptr<bool> cancel_handlers;
@ -418,7 +418,7 @@ namespace SimpleWeb {
} }
if(!connection) { if(!connection) {
connection = create_connection(); connection = create_connection();
connections.emplace_back(connection); connections.emplace(connection);
} }
connection->attempt_reconnect = true; connection->attempt_reconnect = true;
connection->in_use = true; connection->in_use = true;
@ -477,10 +477,8 @@ namespace SimpleWeb {
return; return;
if(!ec) if(!ec)
this->read(session); this->read(session);
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
@ -510,10 +508,8 @@ namespace SimpleWeb {
return; return;
if(!ec) if(!ec)
session->callback(ec); session->callback(ec);
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else else
@ -532,15 +528,8 @@ namespace SimpleWeb {
return; return;
if(!ec) if(!ec)
session->callback(ec); session->callback(ec);
else { else
session->connection->close(); close(session, ec == asio::error::eof ? error_code() : ec);
if(ec == asio::error::eof) {
error_code ec;
session->callback(ec);
}
else
session->callback(ec);
}
}); });
} }
else else
@ -548,14 +537,22 @@ namespace SimpleWeb {
} }
else { else {
if(session->connection->attempt_reconnect) { if(session->connection->attempt_reconnect) {
session->connection->attempt_reconnect = false; std::unique_lock<std::mutex> lock(connections_mutex);
session->connection->close(); auto it = connections.find(session->connection);
this->connect(session); if(it != connections.end()) {
} connections.erase(it);
else { session->connection->close();
session->connection->close(); session->connection = create_connection();
session->callback(ec); session->connection->attempt_reconnect = false;
session->connection->in_use = true;
connections.emplace(session->connection);
this->connect(session);
}
else
this->close(session, ec);
} }
else
this->close(session, ec);
} }
}); });
} }
@ -607,21 +604,26 @@ namespace SimpleWeb {
return; return;
if(!ec) if(!ec)
post_process(); post_process();
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else else
post_process(); post_process();
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
void close(const std::shared_ptr<Session> &session, const error_code &ec) {
session->connection->close();
{
std::lock_guard<std::mutex> lock(connections_mutex);
connections.erase(session->connection);
}
session->callback(ec);
}
}; };
template <class socket_type> template <class socket_type>
@ -661,16 +663,12 @@ namespace SimpleWeb {
session->connection->socket->set_option(option, ec); session->connection->socket->set_option(option, ec);
this->write(session); this->write(session);
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else else

View file

@ -85,38 +85,28 @@ namespace SimpleWeb {
return; return;
if(!ec) { if(!ec) {
response->parse_header(); response->parse_header();
if(response->status_code.empty() || response->status_code.compare(0, 3, "200") != 0) { if(response->status_code.empty() || response->status_code.compare(0, 3, "200") != 0)
session->connection->close(); this->close(session, make_error_code::make_error_code(errc::permission_denied));
session->callback(make_error_code::make_error_code(errc::permission_denied));
}
else else
this->handshake(session); this->handshake(session);
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else else
this->handshake(session); this->handshake(session);
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
else else
@ -132,10 +122,8 @@ namespace SimpleWeb {
return; return;
if(!ec) if(!ec)
this->write(session); this->write(session);
else { else
session->connection->close(); this->close(session, ec);
session->callback(ec);
}
}); });
} }
}; };

View file

@ -206,7 +206,7 @@ int main() {
output << r->content.rdbuf(); output << r->content.rdbuf();
assert(output.str() == "A string"); assert(output.str() == "A string");
assert(client.connections.size() == 1); assert(client.connections.size() == 1);
connection = client.connections.front().get(); connection = client.connections.begin()->get();
} }
{ {
@ -215,7 +215,7 @@ int main() {
output << r->content.rdbuf(); output << r->content.rdbuf();
assert(output.str() == "A string"); assert(output.str() == "A string");
assert(client.connections.size() == 1); assert(client.connections.size() == 1);
assert(connection == client.connections.front().get()); assert(connection == client.connections.begin()->get());
} }
{ {
@ -224,7 +224,7 @@ int main() {
output << r->content.rdbuf(); output << r->content.rdbuf();
assert(output.str() == "testing"); assert(output.str() == "testing");
assert(client.connections.size() == 1); assert(client.connections.size() == 1);
assert(connection == client.connections.front().get()); assert(connection == client.connections.begin()->get());
} }
{ {
@ -232,7 +232,7 @@ int main() {
auto r = client.request("GET", "/query_string?testing"); auto r = client.request("GET", "/query_string?testing");
assert(r->content.string() == "testing"); assert(r->content.string() == "testing");
assert(client.connections.size() == 1); assert(client.connections.size() == 1);
assert(connection == client.connections.front().get()); assert(connection == client.connections.begin()->get());
} }
} }