Fix repeated signal connects on reconnect in irc server (#1576)

This commit is contained in:
pajlada 2020-03-01 06:05:08 -05:00 committed by GitHub
parent 26d3078def
commit 20612a1381
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 41 deletions

View file

@ -71,8 +71,30 @@ AbstractIrcServer::AbstractIrcServer()
}); });
} }
void AbstractIrcServer::initializeIrc()
{
assert(!this->initialized_);
if (this->hasSeparateWriteConnection())
{
this->initializeConnectionSignals(this->writeConnection_.get(),
ConnectionType::Write);
this->initializeConnectionSignals(this->readConnection_.get(),
ConnectionType::Read);
}
else
{
this->initializeConnectionSignals(this->readConnection_.get(),
ConnectionType::Both);
}
this->initialized_ = true;
}
void AbstractIrcServer::connect() void AbstractIrcServer::connect()
{ {
assert(this->initialized_);
this->disconnect(); this->disconnect();
if (this->hasSeparateWriteConnection()) if (this->hasSeparateWriteConnection())

View file

@ -21,6 +21,10 @@ public:
virtual ~AbstractIrcServer() = default; virtual ~AbstractIrcServer() = default;
// initializeIrc must be called from the derived class
// this allows us to initialize the abstract irc server based on the derived class's parameters
void initializeIrc();
// connection // connection
void connect(); void connect();
void disconnect(); void disconnect();
@ -45,8 +49,15 @@ public:
protected: protected:
AbstractIrcServer(); AbstractIrcServer();
// initializeConnectionSignals is called on a connection once in its lifetime.
// it can be used to connect signals to your class
virtual void initializeConnectionSignals(IrcConnection *connection,
ConnectionType type){};
// initializeConnection is called every time before we try to connect to the irc server
virtual void initializeConnection(IrcConnection *connection, virtual void initializeConnection(IrcConnection *connection,
ConnectionType type) = 0; ConnectionType type) = 0;
virtual std::shared_ptr<Channel> createChannel( virtual std::shared_ptr<Channel> createChannel(
const QString &channelName) = 0; const QString &channelName) = 0;
@ -83,6 +94,8 @@ private:
// bool autoReconnect_ = false; // bool autoReconnect_ = false;
pajlada::Signals::SignalHolder connections_; pajlada::Signals::SignalHolder connections_;
bool initialized_{false};
}; };
} // namespace chatterino } // namespace chatterino

View file

@ -15,6 +15,8 @@ namespace chatterino {
IrcServer::IrcServer(const IrcServerData &data) IrcServer::IrcServer(const IrcServerData &data)
: data_(new IrcServerData(data)) : data_(new IrcServerData(data))
{ {
this->initializeIrc();
this->connect(); this->connect();
} }
@ -51,6 +53,57 @@ const QString &IrcServer::nick()
return this->data_->nick.isEmpty() ? this->data_->user : this->data_->nick; return this->data_->nick.isEmpty() ? this->data_->user : this->data_->nick;
} }
void IrcServer::initializeConnectionSignals(IrcConnection *connection,
ConnectionType type)
{
assert(type == Both);
QObject::connect(
connection, &Communi::IrcConnection::socketError, this,
[this](QAbstractSocket::SocketError error) {
static int index =
QAbstractSocket::staticMetaObject.indexOfEnumerator(
"SocketError");
std::lock_guard lock(this->channelMutex);
for (auto &&weak : this->channels)
{
if (auto shared = weak.lock())
{
shared->addMessage(makeSystemMessage(
QStringLiteral("Socket error: ") +
QAbstractSocket::staticMetaObject.enumerator(index)
.valueToKey(error)));
}
}
});
QObject::connect(connection, &Communi::IrcConnection::nickNameRequired,
this, [](const QString &reserved, QString *result) {
*result = reserved + (std::rand() % 100);
});
QObject::connect(connection, &Communi::IrcConnection::noticeMessageReceived,
this, [this](Communi::IrcNoticeMessage *message) {
MessageBuilder builder;
builder.emplace<TimestampElement>();
builder.emplace<TextElement>(
message->nick(), MessageElementFlag::Username);
builder.emplace<TextElement>(
"-> you:", MessageElementFlag::Username);
builder.emplace<TextElement>(message->content(),
MessageElementFlag::Text);
auto msg = builder.release();
for (auto &&weak : this->channels)
if (auto shared = weak.lock())
shared->addMessage(msg);
});
}
void IrcServer::initializeConnection(IrcConnection *connection, void IrcServer::initializeConnection(IrcConnection *connection,
ConnectionType type) ConnectionType type)
{ {
@ -90,47 +143,6 @@ void IrcServer::initializeConnection(IrcConnection *connection,
this->open(Both); this->open(Both);
} }
} }
QObject::connect(
connection, &Communi::IrcConnection::socketError, this,
[this](QAbstractSocket::SocketError error) {
static int index =
QAbstractSocket::staticMetaObject.indexOfEnumerator(
"SocketError");
std::lock_guard lock(this->channelMutex);
for (auto &&weak : this->channels)
if (auto shared = weak.lock())
shared->addMessage(makeSystemMessage(
QStringLiteral("Socket error: ") +
QAbstractSocket::staticMetaObject.enumerator(index)
.valueToKey(error)));
});
QObject::connect(connection, &Communi::IrcConnection::nickNameRequired,
this, [](const QString &reserved, QString *result) {
*result = reserved + (std::rand() % 100);
});
QObject::connect(connection, &Communi::IrcConnection::noticeMessageReceived,
this, [this](Communi::IrcNoticeMessage *message) {
MessageBuilder builder;
builder.emplace<TimestampElement>();
builder.emplace<TextElement>(
message->nick(), MessageElementFlag::Username);
builder.emplace<TextElement>(
"-> you:", MessageElementFlag::Username);
builder.emplace<TextElement>(message->content(),
MessageElementFlag::Text);
auto msg = builder.release();
for (auto &&weak : this->channels)
if (auto shared = weak.lock())
shared->addMessage(msg);
});
} }
std::shared_ptr<Channel> IrcServer::createChannel(const QString &channelName) std::shared_ptr<Channel> IrcServer::createChannel(const QString &channelName)

View file

@ -21,6 +21,8 @@ public:
// AbstractIrcServer interface // AbstractIrcServer interface
protected: protected:
void initializeConnectionSignals(IrcConnection *connection,
ConnectionType type) override;
void initializeConnection(IrcConnection *connection, void initializeConnection(IrcConnection *connection,
ConnectionType type) override; ConnectionType type) override;
std::shared_ptr<Channel> createChannel(const QString &channelName) override; std::shared_ptr<Channel> createChannel(const QString &channelName) override;

View file

@ -27,6 +27,8 @@ TwitchIrcServer::TwitchIrcServer()
, mentionsChannel(new Channel("/mentions", Channel::Type::TwitchMentions)) , mentionsChannel(new Channel("/mentions", Channel::Type::TwitchMentions))
, watchingChannel(Channel::getEmpty(), Channel::Type::TwitchWatching) , watchingChannel(Channel::getEmpty(), Channel::Type::TwitchWatching)
{ {
this->initializeIrc();
this->pubsub = new PubSub; this->pubsub = new PubSub;
// getSettings()->twitchSeperateWriteConnection.connect([this](auto, auto) { // getSettings()->twitchSeperateWriteConnection.connect([this](auto, auto) {