mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-20 21:43:12 -07:00
Implement Wakeup
This commit is contained in:
parent
52cacecaa0
commit
4fadc02947
9 changed files with 132 additions and 8 deletions
|
@ -59,6 +59,8 @@ class DiscoveryManager : public QObject
|
||||||
|
|
||||||
void SetActive(bool active);
|
void SetActive(bool active);
|
||||||
|
|
||||||
|
void SendWakeup(const QString &host, const QByteArray ®ist_key);
|
||||||
|
|
||||||
const QList<DiscoveryHost> GetHosts() const { return hosts; }
|
const QList<DiscoveryHost> GetHosts() const { return hosts; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
|
@ -56,6 +56,7 @@ class MainWindow : public QMainWindow
|
||||||
QList<DisplayServer> display_servers;
|
QList<DisplayServer> display_servers;
|
||||||
|
|
||||||
DisplayServer *DisplayServerFromSender();
|
DisplayServer *DisplayServerFromSender();
|
||||||
|
void SendWakeup(const DisplayServer *server);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ServerItemWidgetSelected();
|
void ServerItemWidgetSelected();
|
||||||
|
|
|
@ -37,6 +37,7 @@ class ServerItemWidget : public QFrame
|
||||||
ServerIconWidget *icon_widget;
|
ServerIconWidget *icon_widget;
|
||||||
|
|
||||||
QAction *delete_action;
|
QAction *delete_action;
|
||||||
|
QAction *wake_action;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is part of Chiaki.
|
* This file is part of Chiaki.
|
||||||
*
|
*
|
||||||
|
@ -18,7 +16,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <discoverymanager.h>
|
#include <discoverymanager.h>
|
||||||
|
#include <exception.h>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#define PING_MS 500
|
#define PING_MS 500
|
||||||
|
@ -86,6 +86,78 @@ void DiscoveryManager::SetActive(bool active)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscoveryManager::SendWakeup(const QString &host, const QByteArray ®ist_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)
|
void DiscoveryManager::DiscoveryServiceHosts(QList<DiscoveryHost> hosts)
|
||||||
{
|
{
|
||||||
this->hosts = std::move(hosts);
|
this->hosts = std::move(hosts);
|
||||||
|
|
|
@ -121,6 +121,24 @@ DisplayServer *MainWindow::DisplayServerFromSender()
|
||||||
return &display_servers[index];
|
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()
|
void MainWindow::ServerItemWidgetTriggered()
|
||||||
{
|
{
|
||||||
auto server = DisplayServerFromSender();
|
auto server = DisplayServerFromSender();
|
||||||
|
@ -129,6 +147,21 @@ void MainWindow::ServerItemWidgetTriggered()
|
||||||
|
|
||||||
if(server->registered)
|
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();
|
QString host = server->GetHostAddr();
|
||||||
StreamSessionConnectInfo info(settings, host, server->registered_host.GetRPRegistKey(), server->registered_host.GetRPKey());
|
StreamSessionConnectInfo info(settings, host, server->registered_host.GetRPRegistKey(), server->registered_host.GetRPKey());
|
||||||
try
|
try
|
||||||
|
@ -165,9 +198,7 @@ void MainWindow::ServerItemWidgetWakeTriggered()
|
||||||
auto server = DisplayServerFromSender();
|
auto server = DisplayServerFromSender();
|
||||||
if(!server)
|
if(!server)
|
||||||
return;
|
return;
|
||||||
|
SendWakeup(server);
|
||||||
// TODO
|
|
||||||
printf("TODO: Wakeup\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::UpdateDiscoveryEnabled()
|
void MainWindow::UpdateDiscoveryEnabled()
|
||||||
|
|
|
@ -51,7 +51,7 @@ ServerItemWidget::ServerItemWidget(QWidget *parent) : QFrame(parent)
|
||||||
addAction(delete_action);
|
addAction(delete_action);
|
||||||
connect(delete_action, &QAction::triggered, this, [this]{ emit DeleteTriggered(); });
|
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);
|
addAction(wake_action);
|
||||||
connect(wake_action, &QAction::triggered, this, [this]{ emit WakeTriggered(); });
|
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)
|
void ServerItemWidget::Update(const DisplayServer &display_server)
|
||||||
{
|
{
|
||||||
delete_action->setEnabled(!display_server.discovered);
|
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);
|
icon_widget->SetState(display_server.discovered ? display_server.discovery_host.state : CHIAKI_DISCOVERY_HOST_STATE_UNKNOWN);
|
||||||
|
|
||||||
|
|
|
@ -35,13 +35,15 @@ extern "C" {
|
||||||
|
|
||||||
typedef enum chiaki_discovery_cmd_t
|
typedef enum chiaki_discovery_cmd_t
|
||||||
{
|
{
|
||||||
CHIAKI_DISCOVERY_CMD_SRCH
|
CHIAKI_DISCOVERY_CMD_SRCH,
|
||||||
|
CHIAKI_DISCOVERY_CMD_WAKEUP
|
||||||
} ChiakiDiscoveryCmd;
|
} ChiakiDiscoveryCmd;
|
||||||
|
|
||||||
typedef struct chiaki_discovery_packet_t
|
typedef struct chiaki_discovery_packet_t
|
||||||
{
|
{
|
||||||
ChiakiDiscoveryCmd cmd;
|
ChiakiDiscoveryCmd cmd;
|
||||||
char *protocol_version;
|
char *protocol_version;
|
||||||
|
uint64_t user_credential; // for wakeup, this is just the regist key interpreted as hex
|
||||||
} ChiakiDiscoveryPacket;
|
} ChiakiDiscoveryPacket;
|
||||||
|
|
||||||
typedef enum chiaki_discovery_host_state_t
|
typedef enum chiaki_discovery_host_state_t
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
const char *chiaki_discovery_host_state_string(ChiakiDiscoveryHostState state)
|
const char *chiaki_discovery_host_state_string(ChiakiDiscoveryHostState state)
|
||||||
|
@ -49,6 +50,16 @@ CHIAKI_EXPORT int chiaki_discovery_packet_fmt(char *buf, size_t buf_size, Chiaki
|
||||||
case CHIAKI_DISCOVERY_CMD_SRCH:
|
case CHIAKI_DISCOVERY_CMD_SRCH:
|
||||||
return snprintf(buf, buf_size, "SRCH * HTTP/1.1\ndevice-discovery-protocol-version:%s\n",
|
return snprintf(buf, buf_size, "SRCH * HTTP/1.1\ndevice-discovery-protocol-version:%s\n",
|
||||||
version_str);
|
version_str);
|
||||||
|
case CHIAKI_DISCOVERY_CMD_WAKEUP:
|
||||||
|
return snprintf(buf, buf_size,
|
||||||
|
"WAKEUP * HTTP/1.1\n"
|
||||||
|
"client-type:vr\n"
|
||||||
|
"auth-type:R\n"
|
||||||
|
"model:w\n"
|
||||||
|
"app-type:r\n"
|
||||||
|
"user-credential:%llu\n"
|
||||||
|
"device-discovery-protocol-version:%s\n",
|
||||||
|
(unsigned long long)packet->user_credential, version_str);
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +180,10 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_discovery_send(ChiakiDiscovery *discovery,
|
||||||
|
|
||||||
ssize_t rc = sendto(discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size);
|
ssize_t rc = sendto(discovery->socket, buf, (size_t)len + 1, 0, addr, addr_size);
|
||||||
if(rc < 0)
|
if(rc < 0)
|
||||||
|
{
|
||||||
|
CHIAKI_LOGE(discovery->log, "Discovery failed to send: %s", strerror(errno));
|
||||||
return CHIAKI_ERR_NETWORK;
|
return CHIAKI_ERR_NETWORK;
|
||||||
|
}
|
||||||
|
|
||||||
return CHIAKI_ERR_SUCCESS;
|
return CHIAKI_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,7 @@ static int regist_search_connect(ChiakiRegist *regist, struct addrinfo *addrinfo
|
||||||
}
|
}
|
||||||
|
|
||||||
in_addr_t ip = ((struct sockaddr_in *)send_addr)->sin_addr.s_addr;
|
in_addr_t ip = ((struct sockaddr_in *)send_addr)->sin_addr.s_addr;
|
||||||
((struct sockaddr_in *)send_addr)->sin_addr.s_addr = INADDR_ANY;
|
((struct sockaddr_in *)send_addr)->sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
r = bind(sock, send_addr, *send_addr_len);
|
r = bind(sock, send_addr, *send_addr_len);
|
||||||
((struct sockaddr_in *)send_addr)->sin_addr.s_addr = ip;
|
((struct sockaddr_in *)send_addr)->sin_addr.s_addr = ip;
|
||||||
if(r < 0)
|
if(r < 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue