Skip to content

Commit

Permalink
added code to handle a single connection
Browse files Browse the repository at this point in the history
  • Loading branch information
fourtf committed Jul 16, 2018
1 parent e51c5c6 commit 3b3c5d8
Show file tree
Hide file tree
Showing 18 changed files with 116 additions and 86 deletions.
4 changes: 2 additions & 2 deletions src/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class Application

friend void test();

[[deprecated("use getSettings() instead")]] Settings *settings = nullptr;
[[deprecated("use getPaths() instead")]] Paths *paths = nullptr;
Settings *settings = nullptr;
Paths *paths = nullptr;

Theme *themes = nullptr;
WindowManager *windows = nullptr;
Expand Down
11 changes: 11 additions & 0 deletions src/common/NetworkData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@

#include "Application.hpp"
#include "singletons/Paths.hpp"
#include "util/DebugCount.hpp"

#include <QCryptographicHash>
#include <QFile>

namespace chatterino {

NetworkData::NetworkData()
{
DebugCount::increase("NetworkData");
}

NetworkData::~NetworkData()
{
DebugCount::decrease("NetworkData");
}

QString NetworkData::getHash()
{
if (this->hash_.isEmpty()) {
Expand Down
3 changes: 3 additions & 0 deletions src/common/NetworkData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ namespace chatterino {
class NetworkResult;

struct NetworkData {
NetworkData();
~NetworkData();

QNetworkRequest request_;
const QObject *caller_ = nullptr;
bool useQuickLoadCache_{};
Expand Down
36 changes: 17 additions & 19 deletions src/common/NetworkRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,21 @@ void NetworkRequest::doRequest()
this->timer->start();

auto onUrlRequested = [data = this->data, timer = this->timer, worker]() mutable {
QNetworkReply *reply = nullptr;
switch (data->requestType_) {
case NetworkRequestType::Get: {
reply = NetworkManager::NaM.get(data->request_);
} break;

case NetworkRequestType::Put: {
reply = NetworkManager::NaM.put(data->request_, data->payload_);
} break;

case NetworkRequestType::Delete: {
reply = NetworkManager::NaM.deleteResource(data->request_);
} break;
}
auto reply = [&]() -> QNetworkReply * {
switch (data->requestType_) {
case NetworkRequestType::Get:
return NetworkManager::NaM.get(data->request_);

case NetworkRequestType::Put:
return NetworkManager::NaM.put(data->request_, data->payload_);

case NetworkRequestType::Delete:
return NetworkManager::NaM.deleteResource(data->request_);

default:
return nullptr;
}
}();

if (reply == nullptr) {
Log("Unhandled request type");
Expand All @@ -201,8 +202,6 @@ void NetworkRequest::doRequest()
data->onReplyCreated_(reply);
}

bool directAction = (data->caller_ == nullptr);

auto handleReply = [data, timer, reply]() mutable {
// TODO(pajlada): A reply was received, kill the timeout timer
if (reply->error() != QNetworkReply::NetworkError::NoError) {
Expand All @@ -222,16 +221,15 @@ void NetworkRequest::doRequest()
};

if (data->caller_ != nullptr) {
QObject::connect(worker, &NetworkWorker::doneUrl, data->caller_,
std::move(handleReply));
QObject::connect(worker, &NetworkWorker::doneUrl, data->caller_, handleReply);
QObject::connect(reply, &QNetworkReply::finished, worker, [worker]() mutable {
emit worker->doneUrl();

delete worker;
});
} else {
QObject::connect(reply, &QNetworkReply::finished, worker,
[handleReply = std::move(handleReply), worker]() mutable {
[handleReply, worker]() mutable {
handleReply();

delete worker;
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/commands/CommandController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ QString CommandController::execCommand(const QString &text, ChannelPtr channel,

app->twitch.server->whispersChannel->addMessage(b.getMessage());

app->twitch.server->getWriteConnection()->sendRaw("PRIVMSG #jtv :" + text + "\r\n");
app->twitch.server->sendMessage("jtv", text);

if (getSettings()->inlineWhispers) {
app->twitch.server->forEachChannel(
Expand Down
38 changes: 17 additions & 21 deletions src/providers/irc/AbstractIrcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,18 @@ AbstractIrcServer::AbstractIrcServer()
// this->writeConnection->reconnectRequested.connect([this] { this->connect(); });
}

IrcConnection *AbstractIrcServer::getReadConnection() const
{
return this->readConnection_.get();
}

IrcConnection *AbstractIrcServer::getWriteConnection() const
{
return this->writeConnection_.get();
}

void AbstractIrcServer::connect()
{
this->disconnect();

// if (this->hasSeparateWriteConnection()) {
this->initializeConnection(this->writeConnection_.get(), false, true);
this->initializeConnection(this->readConnection_.get(), true, false);
// } else {
// this->initializeConnection(this->readConnection.get(), true, true);
// }
bool separateWriteConnection = this->hasSeparateWriteConnection();

if (separateWriteConnection) {
this->initializeConnection(this->writeConnection_.get(), false, true);
this->initializeConnection(this->readConnection_.get(), true, false);
} else {
this->initializeConnection(this->readConnection_.get(), true, true);
}

// fourtf: this should be asynchronous
{
Expand All @@ -67,7 +59,6 @@ void AbstractIrcServer::connect()
continue;
}

this->writeConnection_->sendRaw("JOIN #" + chan->name);
this->readConnection_->sendRaw("JOIN #" + chan->name);
}

Expand All @@ -89,12 +80,17 @@ void AbstractIrcServer::disconnect()

void AbstractIrcServer::sendMessage(const QString &channelName, const QString &message)
{
std::lock_guard<std::mutex> locker(this->connectionMutex_);
this->sendRawMessage("PRIVMSG #" + channelName + " :" + message);
}

// fourtf: trim the message if it's sent from twitch chat
void AbstractIrcServer::sendRawMessage(const QString &rawMessage)
{
std::lock_guard<std::mutex> locker(this->connectionMutex_);

if (this->writeConnection_) {
this->writeConnection_->sendRaw("PRIVMSG #" + channelName + " :" + message);
if (this->hasSeparateWriteConnection()) {
this->writeConnection_->sendRaw(rawMessage);
} else {
this->readConnection_->sendRaw(rawMessage);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/providers/irc/AbstractIrcServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ class AbstractIrcServer
virtual ~AbstractIrcServer() = default;

// connection
IrcConnection *getReadConnection() const;
IrcConnection *getWriteConnection() const;

void connect();
void disconnect();

void sendMessage(const QString &channelName, const QString &message);
void sendRawMessage(const QString &rawMessage);

// channels
std::shared_ptr<Channel> getOrAddChannel(const QString &dirtyChannelName);
Expand Down Expand Up @@ -54,6 +52,7 @@ class AbstractIrcServer

virtual std::shared_ptr<Channel> getCustomChannel(const QString &channelName);

virtual bool hasSeparateWriteConnection() const = 0;
virtual QString cleanChannelName(const QString &dirtyChannelName);

QMap<QString, std::weak_ptr<Channel>> channels;
Expand Down
17 changes: 11 additions & 6 deletions src/providers/irc/IrcConnection2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ IrcConnection::IrcConnection(QObject *parent)
this->pingTimer_.setInterval(5000);
this->pingTimer_.start();
QObject::connect(&this->pingTimer_, &QTimer::timeout, [this] {
if (!this->recentlyReceivedMessage_.load()) {
this->sendRaw("PING");
this->reconnectTimer_.start();
if (this->isConnected()) {
if (!this->recentlyReceivedMessage_.load()) {
this->sendRaw("PING");
this->reconnectTimer_.start();
}
this->recentlyReceivedMessage_ = false;
}
this->recentlyReceivedMessage_ = false;
});

// reconnect after x seconds without receiving a message
this->reconnectTimer_.setInterval(5000);
this->reconnectTimer_.setSingleShot(true);
QObject::connect(&this->reconnectTimer_, &QTimer::timeout,
[this] { reconnectRequested.invoke(); });
QObject::connect(&this->reconnectTimer_, &QTimer::timeout, [this] {
if (this->isConnected()) {
reconnectRequested.invoke();
}
});

QObject::connect(this, &Communi::IrcConnection::messageReceived, [this](Communi::IrcMessage *) {
this->recentlyReceivedMessage_ = true;
Expand Down
7 changes: 4 additions & 3 deletions src/providers/twitch/TwitchChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@

namespace chatterino {

TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection)
TwitchChannel::TwitchChannel(const QString &channelName)
: Channel(channelName, Channel::Type::Twitch)
, bttvEmotes_(new EmoteMap)
, ffzEmotes_(new EmoteMap)
, subscriptionUrl_("https://www.twitch.tv/subs/" + name)
, channelUrl_("https://twitch.tv/" + name)
, popoutPlayerUrl_("https://player.twitch.tv/?channel=" + name)
, mod_(false)
, readConnection_(readConnection)
{
Log("[TwitchChannel:{}] Opened", this->name);

Expand Down Expand Up @@ -420,7 +419,9 @@ bool TwitchChannel::parseRecentMessages(const QJsonObject &jsonRoot)

for (const auto jsonMessage : jsonMessages) {
auto content = jsonMessage.toString().toUtf8();
auto message = Communi::IrcMessage::fromData(content, this->readConnection_);
// passing nullptr as the channel makes the message invalid but we don't check for that
// anyways
auto message = Communi::IrcMessage::fromData(content, nullptr);
auto privMsg = dynamic_cast<Communi::IrcPrivateMessage *>(message);
assert(privMsg);

Expand Down
3 changes: 1 addition & 2 deletions src/providers/twitch/TwitchChannel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class TwitchChannel final : public Channel, pajlada::Signals::SignalHolder
QString localizedName;
};

explicit TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection);
explicit TwitchChannel(const QString &channelName);

// Methods
void refreshLiveStatus();
Expand Down Expand Up @@ -124,7 +124,6 @@ class TwitchChannel final : public Channel, pajlada::Signals::SignalHolder
QObject lifetimeGuard_;
QTimer liveStatusTimer_;
QTimer chattersListTimer_;
Communi::IrcConnection *readConnection_ = nullptr;

friend class TwitchServer;
};
Expand Down
19 changes: 14 additions & 5 deletions src/providers/twitch/TwitchServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ TwitchServer::TwitchServer()
qDebug() << "init TwitchServer";

this->pubsub = new PubSub;

getSettings()->twitchSeperateWriteConnection.connect([this](auto, auto) { this->connect(); },
this->signalHolder_, false);
}

void TwitchServer::initialize(Application &app)
Expand All @@ -42,12 +45,13 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,
{
assert(this->app);

this->singleConnection_ = isRead == isWrite;

std::shared_ptr<TwitchAccount> account = getApp()->accounts->twitch.getCurrent();

qDebug() << "logging in as" << account->getUserName();

QString username = account->getUserName();
// QString oauthClient = account->getOAuthClient();
QString oauthToken = account->getOAuthToken();

if (!oauthToken.startsWith("oauth:")) {
Expand All @@ -60,9 +64,6 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,

if (!account->isAnon()) {
connection->setPassword(oauthToken);

// fourtf: ignored users
// this->refreshIgnoredUsers(username, oauthClient, oauthToken);
}

connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
Expand All @@ -75,7 +76,7 @@ void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead,

std::shared_ptr<Channel> TwitchServer::createChannel(const QString &channelName)
{
TwitchChannel *channel = new TwitchChannel(channelName, this->getReadConnection());
TwitchChannel *channel = new TwitchChannel(channelName);

channel->sendMessageSignal.connect([this, channel](auto &chan, auto &msg, bool &sent) {
this->onMessageSendRequested(channel, msg, sent);
Expand All @@ -91,6 +92,8 @@ void TwitchServer::privateMessageReceived(Communi::IrcPrivateMessage *message)

void TwitchServer::messageReceived(Communi::IrcMessage *message)
{
qDebug() << message->toData();

// this->readConnection
if (message->type() == Communi::IrcMessage::Type::Private) {
// We already have a handler for private messages
Expand Down Expand Up @@ -179,6 +182,12 @@ QString TwitchServer::cleanChannelName(const QString &dirtyChannelName)
return dirtyChannelName.toLower();
}

bool TwitchServer::hasSeparateWriteConnection() const
{
return true;
// return getSettings()->twitchSeperateWriteConnection;
}

void TwitchServer::onMessageSendRequested(TwitchChannel *channel, const QString &message,
bool &sent)
{
Expand Down
21 changes: 13 additions & 8 deletions src/providers/twitch/TwitchServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class TwitchServer : public AbstractIrcServer, public Singleton

virtual void initialize(Application &app) override;

// fourtf: ugh
void forEachChannelAndSpecialChannels(std::function<void(ChannelPtr)> func);

std::shared_ptr<Channel> getChannelOrEmptyByID(const QString &channelID);
Expand All @@ -36,16 +35,18 @@ class TwitchServer : public AbstractIrcServer, public Singleton
PubSub *pubsub;

protected:
void initializeConnection(IrcConnection *connection, bool isRead, bool isWrite) override;
std::shared_ptr<Channel> createChannel(const QString &channelName) override;
virtual void initializeConnection(IrcConnection *connection, bool isRead,
bool isWrite) override;
virtual std::shared_ptr<Channel> createChannel(const QString &channelName) override;

void privateMessageReceived(Communi::IrcPrivateMessage *message) override;
void messageReceived(Communi::IrcMessage *message) override;
void writeConnectionMessageReceived(Communi::IrcMessage *message) override;
virtual void privateMessageReceived(Communi::IrcPrivateMessage *message) override;
virtual void messageReceived(Communi::IrcMessage *message) override;
virtual void writeConnectionMessageReceived(Communi::IrcMessage *message) override;

std::shared_ptr<Channel> getCustomChannel(const QString &channelname) override;
virtual std::shared_ptr<Channel> getCustomChannel(const QString &channelname) override;

QString cleanChannelName(const QString &dirtyChannelName) override;
virtual QString cleanChannelName(const QString &dirtyChannelName) override;
virtual bool hasSeparateWriteConnection() const override;

private:
void onMessageSendRequested(TwitchChannel *channel, const QString &message, bool &sent);
Expand All @@ -57,6 +58,10 @@ class TwitchServer : public AbstractIrcServer, public Singleton
std::queue<std::chrono::steady_clock::time_point> lastMessageMod_;
std::chrono::steady_clock::time_point lastErrorTimeSpeed_;
std::chrono::steady_clock::time_point lastErrorTimeAmount_;

bool singleConnection_ = false;

pajlada::Signals::SignalHolder signalHolder_;
};

} // namespace chatterino
Loading

0 comments on commit 3b3c5d8

Please sign in to comment.