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()
{
assert(this->initialized_);
this->disconnect();
if (this->hasSeparateWriteConnection())

View file

@ -21,6 +21,10 @@ public:
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
void connect();
void disconnect();
@ -45,8 +49,15 @@ public:
protected:
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,
ConnectionType type) = 0;
virtual std::shared_ptr<Channel> createChannel(
const QString &channelName) = 0;
@ -83,6 +94,8 @@ private:
// bool autoReconnect_ = false;
pajlada::Signals::SignalHolder connections_;
bool initialized_{false};
};
} // namespace chatterino

View file

@ -15,6 +15,8 @@ namespace chatterino {
IrcServer::IrcServer(const IrcServerData &data)
: data_(new IrcServerData(data))
{
this->initializeIrc();
this->connect();
}
@ -51,6 +53,57 @@ const QString &IrcServer::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,
ConnectionType type)
{
@ -90,47 +143,6 @@ void IrcServer::initializeConnection(IrcConnection *connection,
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)

View file

@ -21,6 +21,8 @@ public:
// AbstractIrcServer interface
protected:
void initializeConnectionSignals(IrcConnection *connection,
ConnectionType type) override;
void initializeConnection(IrcConnection *connection,
ConnectionType type) 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))
, watchingChannel(Channel::getEmpty(), Channel::Type::TwitchWatching)
{
this->initializeIrc();
this->pubsub = new PubSub;
// getSettings()->twitchSeperateWriteConnection.connect([this](auto, auto) {