Implement Wakeup

This commit is contained in:
Florian Märkl 2019-08-16 22:32:41 +02:00
commit 4fadc02947
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
9 changed files with 132 additions and 8 deletions

View file

@ -59,6 +59,8 @@ class DiscoveryManager : public QObject
void SetActive(bool active);
void SendWakeup(const QString &host, const QByteArray &regist_key);
const QList<DiscoveryHost> GetHosts() const { return hosts; }
signals:

View file

@ -56,6 +56,7 @@ class MainWindow : public QMainWindow
QList<DisplayServer> display_servers;
DisplayServer *DisplayServerFromSender();
void SendWakeup(const DisplayServer *server);
private slots:
void ServerItemWidgetSelected();

View file

@ -37,6 +37,7 @@ class ServerItemWidget : public QFrame
ServerIconWidget *icon_widget;
QAction *delete_action;
QAction *wake_action;
protected:
void mousePressEvent(QMouseEvent *event) override;

View file

@ -1,5 +1,3 @@
#include <utility>
/*
* This file is part of Chiaki.
*
@ -18,7 +16,9 @@
*/
#include <discoverymanager.h>
#include <exception.h>
#include <cstring>
#include <netinet/in.h>
#define PING_MS 500
@ -86,6 +86,78 @@ void DiscoveryManager::SetActive(bool active)
}
void DiscoveryManager::SendWakeup(const QString &host, const QByteArray &regist_key)
{
addrinfo *addrinfos;
int r = getaddrinfo(host.toLocal8Bit().constData(), nullptr, nullptr, &addrinfos);
if(r != 0)
{
CHIAKI_LOGE(&log, "DiscoveryManager failed to getaddrinfo for wakeup");
throw Exception("Failed to getaddrinfo");
}
sockaddr addr = {};
socklen_t addr_len = 0;
for(addrinfo *ai=addrinfos; ai; ai=ai->ai_next)
{
if(ai->ai_family != AF_INET)
continue;
if(ai->ai_protocol != IPPROTO_UDP)
continue;
if(ai->ai_addrlen > sizeof(addr))
continue;
std::memcpy(&addr, ai->ai_addr, ai->ai_addrlen);
addr_len = ai->ai_addrlen;
break;
}
freeaddrinfo(addrinfos);
if(!addr_len)
{
CHIAKI_LOGE(&log, "DiscoveryManager failed to get suitable address from getaddrinfo for wakeup");
throw Exception("Failed to get addr from getaddrinfo");
}
((sockaddr_in *)&addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT);
QByteArray key = regist_key;
for(size_t i=0; i<key.size(); i++)
{
if(!key.at(i))
{
key.resize(i);
break;
}
}
bool ok;
uint64_t credential = (uint64_t)QString::fromUtf8(key).toULongLong(&ok, 16);
if(key.size() > 8 || !ok)
{
CHIAKI_LOGE(&log, "DiscoveryManager got invalid regist key for wakeup");
throw Exception("Invalid regist key");
}
ChiakiDiscoveryPacket packet = {};
packet.cmd = CHIAKI_DISCOVERY_CMD_WAKEUP;
packet.user_credential = credential;
ChiakiErrorCode err;
if(service_active)
err = chiaki_discovery_send(&service.discovery, &packet, &addr, addr_len);
else
{
ChiakiDiscovery discovery;
err = chiaki_discovery_init(&discovery, &log, AF_INET);
if(err != CHIAKI_ERR_SUCCESS)
throw Exception(QString("Failed to init Discovery: %1").arg(chiaki_error_string(err)));
err = chiaki_discovery_send(&discovery, &packet, &addr, addr_len);
chiaki_discovery_fini(&discovery);
}
if(err != CHIAKI_ERR_SUCCESS)
throw Exception(QString("Failed to send Packet: %1").arg(chiaki_error_string(err)));
}
void DiscoveryManager::DiscoveryServiceHosts(QList<DiscoveryHost> hosts)
{
this->hosts = std::move(hosts);

View file

@ -121,6 +121,24 @@ DisplayServer *MainWindow::DisplayServerFromSender()
return &display_servers[index];
}
void MainWindow::SendWakeup(const DisplayServer *server)
{
if(!server->registered)
return;
try
{
discovery_manager.SendWakeup(server->GetHostAddr(), server->registered_host.GetRPRegistKey());
}
catch(const Exception &e)
{
QMessageBox::critical(this, tr("Wakeup failed"), tr("Failed to send Wakeup packet:\n%1").arg(e.what()));
return;
}
QMessageBox::information(this, tr("Wakeup"), tr("Wakeup packet sent."));
}
void MainWindow::ServerItemWidgetTriggered()
{
auto server = DisplayServerFromSender();
@ -129,6 +147,21 @@ void MainWindow::ServerItemWidgetTriggered()
if(server->registered)
{
if(server->discovered && server->discovery_host.state == CHIAKI_DISCOVERY_HOST_STATE_STANDBY)
{
int r = QMessageBox::question(this,
tr("Start Stream"),
tr("The Console is currently in standby mode.\nShould we send a Wakeup packet instead of trying to connect immediately?"),
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if(r == QMessageBox::Yes)
{
SendWakeup(server);
return;
}
else if(r == QMessageBox::Cancel)
return;
}
QString host = server->GetHostAddr();
StreamSessionConnectInfo info(settings, host, server->registered_host.GetRPRegistKey(), server->registered_host.GetRPKey());
try
@ -165,9 +198,7 @@ void MainWindow::ServerItemWidgetWakeTriggered()
auto server = DisplayServerFromSender();
if(!server)
return;
// TODO
printf("TODO: Wakeup\n");
SendWakeup(server);
}
void MainWindow::UpdateDiscoveryEnabled()

View file

@ -51,7 +51,7 @@ ServerItemWidget::ServerItemWidget(QWidget *parent) : QFrame(parent)
addAction(delete_action);
connect(delete_action, &QAction::triggered, this, [this]{ emit DeleteTriggered(); });
auto wake_action = new QAction(tr("Send Wakeup Packet"), this);
wake_action = new QAction(tr("Send Wakeup Packet"), this);
addAction(wake_action);
connect(wake_action, &QAction::triggered, this, [this]{ emit WakeTriggered(); });
@ -83,6 +83,7 @@ void ServerItemWidget::SetSelected(bool selected)
void ServerItemWidget::Update(const DisplayServer &display_server)
{
delete_action->setEnabled(!display_server.discovered);
wake_action->setEnabled(display_server.registered);
icon_widget->SetState(display_server.discovered ? display_server.discovery_host.state : CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN);