diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index c54b4af..dfb41bd 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -40,7 +40,9 @@ add_executable(chiaki
include/settings.h
src/settings.cpp
include/registdialog.h
- src/registdialog.cpp)
+ src/registdialog.cpp
+ include/host.h
+ src/host.cpp)
target_include_directories(chiaki PRIVATE include)
target_link_libraries(chiaki chiaki-lib chiaki-cli-lib)
diff --git a/gui/include/host.h b/gui/include/host.h
new file mode 100644
index 0000000..4abd3ae
--- /dev/null
+++ b/gui/include/host.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki 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.
+ *
+ * Chiaki 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 Chiaki. If not, see .
+ */
+
+#ifndef CHIAKI_HOST_H
+#define CHIAKI_HOST_H
+
+#include
+#include
+
+#include
+
+class HostMAC
+{
+ private:
+ uint8_t mac[6];
+
+ public:
+ HostMAC() { memset(mac, 0, sizeof(mac)); }
+ explicit HostMAC(const uint8_t mac[6]) { memcpy(this->mac, mac, sizeof(this->mac)); }
+ const uint8_t *GetMAC() const { return mac; }
+};
+
+static bool operator==(const HostMAC &a, const HostMAC &b) { return memcmp(a.GetMAC(), b.GetMAC(), 6) == 0; }
+
+class RegisteredHost
+{
+ private:
+ QString ap_ssid;
+ QString ap_bssid;
+ QString ap_key;
+ QString ap_name;
+ HostMAC ps4_mac;
+ QString ps4_nickname;
+ char rp_regist_key[CHIAKI_SESSION_AUTH_SIZE];
+ uint32_t rp_key_type;
+ uint8_t rp_key[0x10];
+
+ public:
+ RegisteredHost();
+ RegisteredHost(const ChiakiRegisteredHost &chiaki_host);
+
+ const QString &GetPS4Nickname() const { return ps4_nickname; }
+};
+
+Q_DECLARE_METATYPE(RegisteredHost)
+
+#endif //CHIAKI_HOST_H
diff --git a/gui/include/registdialog.h b/gui/include/registdialog.h
index b31a95c..3f10235 100644
--- a/gui/include/registdialog.h
+++ b/gui/include/registdialog.h
@@ -18,6 +18,8 @@
#ifndef CHIAKI_REGISTDIALOG_H
#define CHIAKI_REGISTDIALOG_H
+#include "host.h"
+
#include
#include
@@ -69,7 +71,7 @@ class RegistExecuteDialog: public QDialog
private slots:
void Log(ChiakiLogLevel level, QString msg);
- void Success();
+ void Success(RegisteredHost host);
void Failed();
public:
diff --git a/gui/src/host.cpp b/gui/src/host.cpp
new file mode 100644
index 0000000..141bb9a
--- /dev/null
+++ b/gui/src/host.cpp
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Chiaki.
+ *
+ * Chiaki 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.
+ *
+ * Chiaki 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 Chiaki. If not, see .
+ */
+
+#include
+
+RegisteredHost::RegisteredHost()
+{
+ memset(rp_regist_key, 0, sizeof(rp_regist_key));
+ memset(rp_key, 0, sizeof(rp_key));
+}
+
+RegisteredHost::RegisteredHost(const ChiakiRegisteredHost &chiaki_host)
+ : ps4_mac(chiaki_host.ps4_mac)
+{
+ ap_ssid = chiaki_host.ap_ssid;
+ ap_bssid = chiaki_host.ap_bssid;
+ ap_key = chiaki_host.ap_key;
+ ap_name = chiaki_host.ap_name;
+ ps4_nickname = chiaki_host.ps4_nickname;
+ memcpy(rp_regist_key, chiaki_host.rp_regist_key, sizeof(rp_regist_key));
+ rp_key_type = chiaki_host.rp_key_type;
+ memcpy(rp_key, chiaki_host.rp_key, sizeof(rp_key));
+}
\ No newline at end of file
diff --git a/gui/src/main.cpp b/gui/src/main.cpp
index 2e31bd4..0a7496b 100644
--- a/gui/src/main.cpp
+++ b/gui/src/main.cpp
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
@@ -38,6 +39,7 @@ int RunMain(QApplication &app, Settings *settings);
int main(int argc, char *argv[])
{
qRegisterMetaType();
+ qRegisterMetaType();
qRegisterMetaType();
qRegisterMetaType();
qRegisterMetaType();
diff --git a/gui/src/registdialog.cpp b/gui/src/registdialog.cpp
index ae549d6..f1d23be 100644
--- a/gui/src/registdialog.cpp
+++ b/gui/src/registdialog.cpp
@@ -141,9 +141,9 @@ void RegistExecuteDialog::Finished()
button_box->addButton(QDialogButtonBox::Close);
}
-void RegistExecuteDialog::Success()
+void RegistExecuteDialog::Success(RegisteredHost host)
{
- printf("finished\n");
+ CHIAKI_LOGI(&log, "Successfully registered %s", host.GetPS4Nickname().toLocal8Bit().constData());
Finished();
}
@@ -164,7 +164,7 @@ class RegistExecuteDialogPrivate
switch(event->type)
{
case CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS:
- QMetaObject::invokeMethod(dialog, "Success", Qt::ConnectionType::QueuedConnection);
+ QMetaObject::invokeMethod(dialog, "Success", Qt::ConnectionType::QueuedConnection, Q_ARG(RegisteredHost, *event->registered_host));
break;
case CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED:
QMetaObject::invokeMethod(dialog, "Failed", Qt::ConnectionType::QueuedConnection);
diff --git a/lib/include/chiaki/regist.h b/lib/include/chiaki/regist.h
index 1c821b2..5351625 100644
--- a/lib/include/chiaki/regist.h
+++ b/lib/include/chiaki/regist.h
@@ -23,6 +23,7 @@
#include "thread.h"
#include "stoppipe.h"
#include "rpcrypt.h"
+#include "session.h"
#ifdef __cplusplus
extern "C" {
@@ -35,6 +36,19 @@ typedef struct chiaki_regist_info_t
uint32_t pin;
} ChiakiRegistInfo;
+typedef struct chiaki_registered_host_t
+{
+ char ap_ssid[0x30];
+ char ap_bssid[0x20];
+ char ap_key[0x50];
+ char ap_name[0x20];
+ uint8_t ps4_mac[6];
+ char ps4_nickname[0x20];
+ char rp_regist_key[CHIAKI_SESSION_AUTH_SIZE]; // must be completely filled (pad with \0)
+ uint32_t rp_key_type;
+ uint8_t rp_key[0x10];
+} ChiakiRegisteredHost;
+
typedef enum chiaki_regist_event_type_t {
CHIAKI_REGIST_EVENT_TYPE_CONNECTED,
CHIAKI_REGIST_EVENT_TYPE_FINISHED_CANCELED,
@@ -45,6 +59,7 @@ typedef enum chiaki_regist_event_type_t {
typedef struct chiaki_regist_event_t
{
ChiakiRegistEventType type;
+ ChiakiRegisteredHost *registered_host;
} ChiakiRegistEvent;
typedef void (*ChiakiRegistCb)(ChiakiRegistEvent *event, void *user);
diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h
index f096e58..5292630 100644
--- a/lib/include/chiaki/session.h
+++ b/lib/include/chiaki/session.h
@@ -65,12 +65,14 @@ typedef enum {
CHIAKI_EXPORT void chiaki_connect_video_profile_preset(ChiakiConnectVideoProfile *profile, ChiakiVideoResolutionPreset resolution, ChiakiVideoFPSPreset fps);
+#define CHIAKI_SESSION_AUTH_SIZE 0x10
+
typedef struct chiaki_connect_info_t
{
const char *host; // null terminated
const char *regist_key; // null terminated
const char *ostype; // null terminated
- char auth[0x10]; // must be completely filled (pad with \0)
+ char auth[CHIAKI_SESSION_AUTH_SIZE]; // must be completely filled (pad with \0)
uint8_t morning[0x10];
uint8_t did[CHIAKI_RP_DID_SIZE];
ChiakiConnectVideoProfile video_profile;
diff --git a/lib/src/discovery.c b/lib/src/discovery.c
index 6ffa6c1..0f84faf 100644
--- a/lib/src/discovery.c
+++ b/lib/src/discovery.c
@@ -258,7 +258,7 @@ static void *discovery_thread_func(void *user)
buf[n] = '\00';
- CHIAKI_LOGV(discovery->log, "Discovery received:\n%s", buf);
+ //CHIAKI_LOGV(discovery->log, "Discovery received:\n%s", buf);
//chiaki_log_hexdump_raw(discovery->log, CHIAKI_LOG_VERBOSE, (const uint8_t *)buf, n);
char addr_buf[64];
diff --git a/lib/src/regist.c b/lib/src/regist.c
index 2a4b0bf..5ade981 100644
--- a/lib/src/regist.c
+++ b/lib/src/regist.c
@@ -36,7 +36,8 @@
static void *regist_thread_func(void *user);
static ChiakiErrorCode regist_search(ChiakiRegist *regist, struct addrinfo *addrinfos);
static int regist_connect(ChiakiRegist *regist, struct addrinfo *addrinfos, int protocol);
-static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, int sock, ChiakiRPCrypt *rpcrypt);
+static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, ChiakiRegisteredHost *host, int sock, ChiakiRPCrypt *rpcrypt);
+static ChiakiErrorCode regist_parse_response_payload(ChiakiRegist *regist, ChiakiRegisteredHost *host, char *buf, size_t buf_size);
CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, const ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user)
{
@@ -200,7 +201,8 @@ static void *regist_thread_func(void *user)
CHIAKI_LOGI(regist->log, "Regist waiting for response");
- err = regist_recv_response(regist, sock, &crypt);
+ ChiakiRegisteredHost host;
+ err = regist_recv_response(regist, &host, sock, &crypt);
if(err != CHIAKI_ERR_SUCCESS)
{
CHIAKI_LOGE(regist->log, "Regist eventually failed");
@@ -210,7 +212,6 @@ static void *regist_thread_func(void *user)
CHIAKI_LOGI(regist->log, "Regist successfully received response");
success = true;
- // TODO: params
fail_socket:
close(sock);
@@ -220,7 +221,12 @@ fail:
if(canceled)
regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_CANCELED);
else if(success)
- regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS);
+ {
+ ChiakiRegistEvent event = { 0 };
+ event.type = CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS;
+ event.registered_host = &host;
+ regist->cb(&event, regist->cb_user);
+ }
else
regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED);
return NULL;
@@ -320,7 +326,7 @@ static int regist_connect(ChiakiRegist *regist, struct addrinfo *addrinfos, int
return sock;
}
-static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, int sock, ChiakiRPCrypt *rpcrypt)
+static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, ChiakiRegisteredHost *host, int sock, ChiakiRPCrypt *rpcrypt)
{
uint8_t buf[0x200];
size_t buf_filled_size;
@@ -394,7 +400,126 @@ static ChiakiErrorCode regist_recv_response(ChiakiRegist *regist, int sock, Chia
CHIAKI_LOGI(regist->log, "Regist response payload (decrypted):");
chiaki_log_hexdump(regist->log, CHIAKI_LOG_VERBOSE, payload, payload_size);
- // TODO: parse content
+ err = regist_parse_response_payload(regist, host, (char *)payload, payload_size);
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to parse response payload");
+ return err;
+ }
+
+ return CHIAKI_ERR_SUCCESS;
+}
+
+static ChiakiErrorCode regist_parse_response_payload(ChiakiRegist *regist, ChiakiRegisteredHost *host, char *buf, size_t buf_size)
+{
+ ChiakiHttpHeader *headers;
+ ChiakiErrorCode err = chiaki_http_header_parse(&headers, buf, buf_size);
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ CHIAKI_LOGE(regist->log, "Regist failed to parse response payload HTTP header");
+ return err;
+ }
+
+ memset(host, 0, sizeof(*host));
+
+ bool mac_found = false;
+ bool regist_key_found = false;
+ bool key_found = false;
+
+ for(ChiakiHttpHeader *header=headers; header; header=header->next)
+ {
+#define COPY_STRING(name, key_str) \
+ if(strcmp(header->key, key_str) == 0) \
+ { \
+ size_t len = strlen(header->value); \
+ if(len >= sizeof(host->name)) \
+ { \
+ CHIAKI_LOGE(regist->log, "Regist value for " key_str " in response is too long"); \
+ continue; \
+ } \
+ memcpy(host->name, header->value, len); \
+ host->name[len] = 0; \
+ continue; \
+ }
+ COPY_STRING(ap_ssid, "AP-Ssid")
+ COPY_STRING(ap_bssid, "AP-Bssid")
+ COPY_STRING(ap_key, "AP-Key")
+ COPY_STRING(ap_name, "AP-Name")
+ COPY_STRING(ps4_nickname, "PS4-Nickname")
+#undef COPY_STRING
+
+ if(strcmp(header->key, "PS4-RegistKey") == 0)
+ {
+ memset(host->rp_regist_key, 0, sizeof(host->rp_regist_key));
+ size_t buf_size = sizeof(host->rp_regist_key);
+ err = parse_hex((uint8_t *)host->rp_regist_key, &buf_size, header->value, strlen(header->value));
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ CHIAKI_LOGE(regist->log, "Regist received invalid RegistKey in response");
+ memset(host->rp_regist_key, 0, sizeof(host->rp_regist_key));
+ }
+ else
+ {
+ regist_key_found = true;
+ }
+ }
+ else if(strcmp(header->key, "RP-KeyType") == 0)
+ {
+ host->rp_key_type = (uint32_t)strtoul(header->value, NULL, 0);
+ }
+ else if(strcmp(header->key, "RP-Key") == 0)
+ {
+ size_t buf_size = sizeof(host->rp_key);
+ err = parse_hex((uint8_t *)host->rp_key, &buf_size, header->value, strlen(header->value));
+ if(err != CHIAKI_ERR_SUCCESS || buf_size != sizeof(host->rp_key))
+ {
+ CHIAKI_LOGE(regist->log, "Regist received invalid key in response");
+ memset(host->rp_key, 0, sizeof(host->rp_key));
+ }
+ else
+ {
+ key_found = true;
+ }
+ }
+ else if(strcmp(header->key, "PS4-Mac") == 0)
+ {
+ size_t buf_size = sizeof(host->ps4_mac);
+ err = parse_hex((uint8_t *)host->ps4_mac, &buf_size, header->value, strlen(header->value));
+ if(err != CHIAKI_ERR_SUCCESS || buf_size != sizeof(host->ps4_mac))
+ {
+ CHIAKI_LOGE(regist->log, "Regist received invalid MAC Address in response");
+ memset(host->ps4_mac, 0, sizeof(host->ps4_mac));
+ }
+ else
+ {
+ mac_found = true;
+ }
+ }
+ else
+ {
+ CHIAKI_LOGI(regist->log, "Regist received unknown key %s in response payload", header->key);
+ }
+ }
+
+ chiaki_http_header_free(headers);
+
+ if(!regist_key_found)
+ {
+ CHIAKI_LOGE(regist->log, "Regist response is missing RegistKey (or it was invalid)");
+ return CHIAKI_ERR_INVALID_RESPONSE;
+ }
+
+ if(!key_found)
+ {
+ CHIAKI_LOGE(regist->log, "Regist response is missing key (or it was invalid)");
+ return CHIAKI_ERR_INVALID_RESPONSE;
+ }
+
+ if(!mac_found)
+ {
+ CHIAKI_LOGE(regist->log, "Regist response is missing MAC Adress (or it was invalid)");
+ return CHIAKI_ERR_INVALID_RESPONSE;
+ }
return CHIAKI_ERR_SUCCESS;
}
diff --git a/lib/src/utils.h b/lib/src/utils.h
index b1e2ff0..9fd4deb 100644
--- a/lib/src/utils.h
+++ b/lib/src/utils.h
@@ -43,4 +43,37 @@ static inline void xor_bytes(uint8_t *dst, uint8_t *src, size_t sz)
}
}
+static inline int8_t nibble_value(char c)
+{
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ if(c >= 'a' && c <= 'f')
+ return c - 'a' + 0xa;
+ if(c >= 'A' && c <= 'F')
+ return c - 'A' + 0xa;
+ return -1;
+}
+
+static inline ChiakiErrorCode parse_hex(uint8_t *buf, size_t *buf_size, const char *hex, size_t hex_size)
+{
+ if(hex_size % 2 != 0)
+ return CHIAKI_ERR_INVALID_DATA;
+ if(hex_size / 2 > *buf_size)
+ return CHIAKI_ERR_BUF_TOO_SMALL;
+
+ for(size_t i=0; i