2013-01-10 21:21:55 +01:00
|
|
|
/* This file is part of Clementine.
|
|
|
|
Copyright 2013, Andreas Muttscheller <asfa194@gmail.com>
|
|
|
|
|
|
|
|
Clementine is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Clementine is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "core/logging.h"
|
|
|
|
|
|
|
|
#include "remoteclient.h"
|
2013-01-23 20:02:12 +01:00
|
|
|
#include "networkremote.h"
|
2013-01-10 21:21:55 +01:00
|
|
|
|
|
|
|
#include <QDataStream>
|
2013-01-23 20:02:12 +01:00
|
|
|
#include <QSettings>
|
2013-01-10 21:21:55 +01:00
|
|
|
|
|
|
|
RemoteClient::RemoteClient(Application* app, QTcpSocket* client)
|
|
|
|
: app_(app),
|
|
|
|
client_(client)
|
|
|
|
{
|
|
|
|
// Open the buffer
|
|
|
|
buffer_.setData(QByteArray());
|
|
|
|
buffer_.open(QIODevice::ReadWrite);
|
|
|
|
reading_protobuf_ = false;
|
|
|
|
|
|
|
|
// Connect to the slot IncomingData when receiving data
|
|
|
|
connect(client, SIGNAL(readyRead()), this, SLOT(IncomingData()));
|
2013-01-28 14:39:31 +01:00
|
|
|
|
2013-01-23 20:02:12 +01:00
|
|
|
// Check if we use auth code
|
|
|
|
QSettings s;
|
|
|
|
|
|
|
|
s.beginGroup(NetworkRemote::kSettingsGroup);
|
|
|
|
use_auth_code_ = s.value("use_auth_code", false).toBool();
|
|
|
|
auth_code_ = s.value("auth_code", 0).toInt();
|
|
|
|
|
|
|
|
s.endGroup();
|
2013-03-21 10:57:52 +01:00
|
|
|
|
|
|
|
// If we don't use an auth code, we don't need to authenticate the client.
|
|
|
|
authenticated_ = !use_auth_code_;
|
2013-01-10 21:21:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
RemoteClient::~RemoteClient() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void RemoteClient::IncomingData() {
|
|
|
|
while (client_->bytesAvailable()) {
|
|
|
|
if (!reading_protobuf_) {
|
|
|
|
// Read the length of the next message
|
|
|
|
QDataStream s(client_);
|
|
|
|
s >> expected_length_;
|
2013-03-12 12:12:04 +01:00
|
|
|
|
|
|
|
// Receiving more than 128mb is very unlikely
|
|
|
|
// Flush the data and disconnect the client
|
|
|
|
if (expected_length_ > 134217728) {
|
|
|
|
qLog(Debug) << "Received invalid data, disconnect client";
|
|
|
|
qLog(Debug) << "expected_length_ =" << expected_length_;
|
|
|
|
client_->close();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-10 21:21:55 +01:00
|
|
|
reading_protobuf_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read some of the message
|
|
|
|
buffer_.write(
|
|
|
|
client_->read(expected_length_ - buffer_.size()));
|
|
|
|
|
|
|
|
// Did we get everything?
|
|
|
|
if (buffer_.size() == expected_length_) {
|
|
|
|
// Parse the message
|
2013-01-23 20:02:12 +01:00
|
|
|
ParseMessage(buffer_.data());
|
2013-01-10 21:21:55 +01:00
|
|
|
|
|
|
|
// Clear the buffer
|
|
|
|
buffer_.close();
|
|
|
|
buffer_.setData(QByteArray());
|
|
|
|
buffer_.open(QIODevice::ReadWrite);
|
|
|
|
reading_protobuf_ = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-23 20:02:12 +01:00
|
|
|
void RemoteClient::ParseMessage(const QByteArray &data) {
|
|
|
|
pb::remote::Message msg;
|
|
|
|
if (!msg.ParseFromArray(data.constData(), data.size())) {
|
|
|
|
qLog(Info) << "Couldn't parse data";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg.type() == pb::remote::CONNECT && use_auth_code_) {
|
|
|
|
if (msg.request_connect().auth_code() != auth_code_) {
|
2013-03-21 10:57:52 +01:00
|
|
|
DisconnectClient(pb::remote::Wrong_Auth_Code);
|
2013-01-23 20:02:12 +01:00
|
|
|
return;
|
2013-03-21 10:57:52 +01:00
|
|
|
} else {
|
|
|
|
authenticated_ = true;
|
2013-01-23 20:02:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-21 10:57:52 +01:00
|
|
|
// Check if the client has sent the correct auth code
|
|
|
|
if (!authenticated_) {
|
|
|
|
DisconnectClient(pb::remote::Not_Authenticated);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-23 20:02:12 +01:00
|
|
|
// Now parse the other data
|
|
|
|
emit Parse(msg);
|
|
|
|
}
|
|
|
|
|
2013-03-21 10:57:52 +01:00
|
|
|
void RemoteClient::DisconnectClient(pb::remote::ReasonDisconnect reason) {
|
2013-01-23 20:02:12 +01:00
|
|
|
pb::remote::Message msg;
|
|
|
|
msg.set_type(pb::remote::DISCONNECT);
|
2013-02-08 19:27:56 +01:00
|
|
|
|
|
|
|
// Send the default version
|
2013-02-08 19:42:46 +01:00
|
|
|
msg.set_version(msg.default_instance().version());
|
2013-02-08 19:27:56 +01:00
|
|
|
|
2013-03-21 10:57:52 +01:00
|
|
|
msg.mutable_response_disconnect()->set_reason_disconnect(reason);
|
2013-01-23 20:02:12 +01:00
|
|
|
SendData(&msg);
|
|
|
|
|
|
|
|
// Just close the connection. The next time the outgoing data creator
|
|
|
|
// sends a keep alive, the client will be deleted
|
|
|
|
client_->close();
|
|
|
|
}
|
|
|
|
|
2013-01-10 21:21:55 +01:00
|
|
|
void RemoteClient::SendData(pb::remote::Message *msg) {
|
2013-03-23 16:59:24 +01:00
|
|
|
if (authenticated_) {
|
|
|
|
// Serialize the message
|
|
|
|
std::string data = msg->SerializeAsString();
|
|
|
|
|
|
|
|
// Check if we are still connected
|
|
|
|
if (client_->state() == QTcpSocket::ConnectedState) {
|
|
|
|
// write the length of the data first
|
|
|
|
QDataStream s(client_);
|
|
|
|
s << qint32(data.length());
|
|
|
|
s.writeRawData(data.data(), data.length());
|
|
|
|
|
|
|
|
// Do NOT flush data here! If the client is already disconnected, it
|
|
|
|
// causes a SIGPIPE termination!!!
|
|
|
|
} else {
|
|
|
|
client_->close();
|
|
|
|
}
|
2013-01-28 14:21:04 +01:00
|
|
|
}
|
2013-01-10 21:21:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
QAbstractSocket::SocketState RemoteClient::State() {
|
|
|
|
return client_->state();
|
|
|
|
}
|