Ensure disconnect() method always disconnect the underlying sockets.

Added additional checks after weak pointer locks.
This commit is contained in:
Jacek Piszczek 2021-03-24 11:08:40 -04:00
parent 47c6f35f5a
commit 68f8eb0d39
7 changed files with 96 additions and 24 deletions

View File

@ -51,14 +51,13 @@
#include <sstream>
// Helpers for service properties
#define GET_PROPERTY(type, prop) \
(m_store.lock()->getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
(getStoreOrThrow()->getInfos().getPropertyValue <type>(getSession(), \
dynamic_cast <const IMAPServiceInfos&>(getStoreOrThrow()->getInfos()).getProperties().prop))
#define HAS_PROPERTY(prop) \
(m_store.lock()->getInfos().hasProperty(getSession(), \
dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
(getStoreOrThrow()->getInfos().hasProperty(getSession(), \
dynamic_cast <const IMAPServiceInfos&>(getStoreOrThrow()->getInfos()).getProperties().prop))
namespace vmime {
@ -127,6 +126,10 @@ void IMAPConnection::connect() {
shared_ptr <IMAPStore> store = m_store.lock();
if (!store) {
throw exceptions::illegal_state("Store not found");
}
// Create the time-out handler
if (store->getTimeoutHandlerFactory()) {
m_timeoutHandler = store->getTimeoutHandlerFactory()->create();
@ -244,6 +247,17 @@ void IMAPConnection::connect() {
setState(STATE_AUTHENTICATED);
}
shared_ptr <IMAPStore> IMAPConnection::getStoreOrThrow() {
auto store = m_store.lock();
if (!store) {
throw exceptions::illegal_state("Store not found");
}
return store;
}
void IMAPConnection::authenticate() {
@ -529,9 +543,15 @@ void IMAPConnection::startTLS() {
throw exceptions::command_error("STARTTLS", resp->getErrorLog(), "bad response");
}
auto store = m_store.lock();
if (!store) {
throw exceptions::illegal_state("Store not found");
}
shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create(
m_store.lock()->getCertificateVerifier(),
m_store.lock()->getSession()->getTLSProperties()
store->getCertificateVerifier(),
store->getSession()->getTLSProperties()
);
shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket);
@ -701,11 +721,11 @@ shared_ptr <connectionInfos> IMAPConnection::getConnectionInfos() const {
void IMAPConnection::disconnect() {
if (!isConnected()) {
bool wasConnected = isConnected();
internalDisconnect();
if (!wasConnected) {
throw exceptions::not_connected();
}
internalDisconnect();
}
@ -714,7 +734,9 @@ void IMAPConnection::internalDisconnect() {
if (isConnected()) {
IMAPCommand::LOGOUT()->send(dynamicCast <IMAPConnection>(shared_from_this()));
}
if (m_socket) {
m_socket->disconnect();
m_socket = null;
}
@ -836,7 +858,13 @@ shared_ptr <IMAPStore> IMAPConnection::getStore() {
shared_ptr <session> IMAPConnection::getSession() {
return m_store.lock()->getSession();
auto store = m_store.lock();
if (!store) {
throw exceptions::illegal_state("Store not found");
}
return store->getSession();
}

View File

@ -114,6 +114,8 @@ public:
private:
shared_ptr <IMAPStore> getStoreOrThrow();
void authenticate();
#if VMIME_HAVE_SASL_SUPPORT
void authenticateSASL();

View File

@ -290,9 +290,17 @@ void IMAPFolder::close(const bool expunge) {
shared_ptr <IMAPStore> store = m_store.lock();
if (!store) {
if (m_connection && m_connection->isConnected())
m_connection->disconnect();
m_connection = nullptr;
m_open = false;
throw exceptions::illegal_state("Store disconnected");
}
if (!m_connection || !m_connection->isConnected()) {
throw exceptions::illegal_state("Folder not connected");
}
if (!isOpen()) {
throw exceptions::illegal_state("Folder not open");
}
@ -314,7 +322,7 @@ void IMAPFolder::close(const bool expunge) {
oldConnection->disconnect();
// Now use default store connection
m_connection = m_store.lock()->connection();
m_connection = store->connection();
m_open = false;
m_mode = -1;
@ -546,7 +554,6 @@ bool IMAPFolder::isOpen() const {
return m_open;
}
shared_ptr <message> IMAPFolder::getMessage(const size_t num) {
if (!isOpen()) {
@ -1421,6 +1428,10 @@ void IMAPFolder::noop() {
throw exceptions::illegal_state("Store disconnected");
}
if (!m_connection || !m_connection->isConnected()) {
throw exceptions::illegal_state("Store disconnected");
}
IMAPCommand::NOOP()->send(m_connection);
scoped_ptr <IMAPParser::response> resp(m_connection->readResponse());

View File

@ -243,7 +243,7 @@ void IMAPMessage::extract(
shared_ptr <const IMAPFolder> folder = m_folder.lock();
if (!folder) {
throw exceptions::folder_not_found();
throw exceptions::illegal_state("Folder not open");
}
extractImpl(
@ -318,6 +318,14 @@ size_t IMAPMessage::extractImpl(
shared_ptr <const IMAPFolder> folder = m_folder.lock();
if (!folder) {
throw exceptions::folder_not_found();
}
if (!folder->isOpen()) {
throw exceptions::illegal_state("Folder not open");
}
IMAPMessage_literalHandler literalHandler(os, progress);
if (length == 0) {
@ -474,7 +482,6 @@ size_t IMAPMessage::extractImpl(
return literalHandler.getTarget()->getBytesWritten();
}
int IMAPMessage::processFetchResponse(
const fetchAttributes& options,
const IMAPParser::message_data& msgData
@ -717,10 +724,16 @@ shared_ptr <vmime::message> IMAPMessage::getParsedMessage() {
} catch (exceptions::unfetched_object&) {
auto folder = m_folder.lock();
if (!folder) {
throw exceptions::folder_not_found();
}
std::vector <shared_ptr <message> > msgs;
msgs.push_back(dynamicCast <IMAPMessage>(shared_from_this()));
m_folder.lock()->fetchMessages(
folder->fetchMessages(
msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL
);

View File

@ -36,7 +36,6 @@
#include "vmime/utility/outputStreamAdapter.hpp"
#include "vmime/utility/inputStreamStringAdapter.hpp"
namespace vmime {
namespace net {
namespace imap {
@ -71,6 +70,9 @@ void IMAPMessagePartContentHandler::generate(
shared_ptr <IMAPMessage> msg = m_message.lock();
shared_ptr <messagePart> part = m_part.lock();
if (!msg || !part)
throw exceptions::message_not_found();
// Data is already encoded
if (isEncoded()) {
@ -140,6 +142,9 @@ void IMAPMessagePartContentHandler::extract(
shared_ptr <IMAPMessage> msg = m_message.lock();
shared_ptr <messagePart> part = m_part.lock();
if (!msg || !part)
throw exceptions::message_not_found();
// No decoding to perform
if (!isEncoded()) {
@ -172,12 +177,17 @@ void IMAPMessagePartContentHandler::extractRaw(
shared_ptr <IMAPMessage> msg = m_message.lock();
shared_ptr <messagePart> part = m_part.lock();
if (!msg || !part)
throw exceptions::message_not_found();
msg->extractPart(part, os, progress);
}
size_t IMAPMessagePartContentHandler::getLength() const {
shared_ptr <messagePart> part = m_part.lock();
if (!part)
throw exceptions::message_not_found();
return m_part.lock()->getSize();
}

View File

@ -4912,6 +4912,9 @@ public:
shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock();
shared_ptr <socket> sok = m_socket.lock();
if (!sok)
throw exceptions::illegal_state("Store disconnected");
if (toh) {
toh->resetTimeOut();
}
@ -4957,6 +4960,9 @@ public:
shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock();
shared_ptr <socket> sok = m_socket.lock();
if (!sok)
throw exceptions::illegal_state("Store disconnected");
if (m_progress) {
m_progress->start(count);
}

View File

@ -179,9 +179,7 @@ shared_ptr <IMAPConnection> IMAPStore::getConnection() {
void IMAPStore::disconnect() {
if (!isConnected()) {
throw exceptions::not_connected();
}
bool wasConnected = isConnected();
for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ;
it != m_folders.end() ; ++it) {
@ -191,12 +189,16 @@ void IMAPStore::disconnect() {
m_folders.clear();
if (m_connection) {
m_connection->disconnect();
m_connection = null;
}
if (!wasConnected) {
throw exceptions::not_connected();
}
}
void IMAPStore::noop() {