diff --git a/gui/include/mainwindow.h b/gui/include/mainwindow.h index a78388f..110a8a6 100644 --- a/gui/include/mainwindow.h +++ b/gui/include/mainwindow.h @@ -30,6 +30,8 @@ struct DisplayServer { DiscoveryHost discovery_host; bool discovered; + + QString GetHostAddr() const { return discovered ? discovery_host.host_addr : QString(); } }; class MainWindow : public QMainWindow diff --git a/gui/include/registdialog.h b/gui/include/registdialog.h index 9eb1281..b31a95c 100644 --- a/gui/include/registdialog.h +++ b/gui/include/registdialog.h @@ -25,6 +25,8 @@ class Settings; class QLineEdit; +class QPlainTextEdit; +class QDialogButtonBox; class RegistDialog : public QDialog { @@ -33,16 +35,48 @@ class RegistDialog : public QDialog private: Settings *settings; - ChiakiRegist regist; - bool regist_active; - QLineEdit *host_edit; QLineEdit *psn_id_edit; QLineEdit *pin_edit; + QDialogButtonBox *button_box; + QPushButton *register_button; + + private slots: + void ValidateInput(); public: - explicit RegistDialog(Settings *settings, QWidget *parent = nullptr); + explicit RegistDialog(Settings *settings, QString host = QString(), QWidget *parent = nullptr); ~RegistDialog(); + + public slots: + void accept() override; }; +class RegistExecuteDialog: public QDialog +{ + Q_OBJECT + + friend class RegistExecuteDialogPrivate; + + private: + ChiakiLog log; + ChiakiRegist regist; + + QPlainTextEdit *log_edit; + QDialogButtonBox *button_box; + + void Finished(); + + private slots: + void Log(ChiakiLogLevel level, QString msg); + void Success(); + void Failed(); + + public: + explicit RegistExecuteDialog(const ChiakiRegistInfo ®ist_info, QWidget *parent = nullptr); + ~RegistExecuteDialog(); +}; + +Q_DECLARE_METATYPE(ChiakiRegistEventType) + #endif // CHIAKI_REGISTDIALOG_H diff --git a/gui/src/main.cpp b/gui/src/main.cpp index d658a37..2e31bd4 100644 --- a/gui/src/main.cpp +++ b/gui/src/main.cpp @@ -4,10 +4,12 @@ #include #include #include +#include #include #include +#include #include #include @@ -19,6 +21,8 @@ #include #include +Q_DECLARE_METATYPE(ChiakiLogLevel) + struct CLICommand { int (*cmd)(ChiakiLog *log, int argc, char *argv[]); @@ -35,6 +39,8 @@ int main(int argc, char *argv[]) { qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); QApplication::setOrganizationName("Chiaki"); QApplication::setApplicationName("Chiaki"); diff --git a/gui/src/mainwindow.cpp b/gui/src/mainwindow.cpp index 57461ef..08176a3 100644 --- a/gui/src/mainwindow.cpp +++ b/gui/src/mainwindow.cpp @@ -54,7 +54,7 @@ MainWindow::MainWindow(Settings *settings, QWidget *parent) auto regist_action = new QAction(tr("Register"), this); tool_bar->addAction(regist_action); connect(regist_action, &QAction::triggered, this, [this]() { - RegistDialog dialog(this->settings, this); + RegistDialog dialog(this->settings, QString(), this); dialog.exec(); }); @@ -108,8 +108,15 @@ void MainWindow::ServerItemWidgetTriggered() auto server_item_widget = qobject_cast(sender()); if(!server_item_widget) return; + int index = server_item_widgets.indexOf(server_item_widget); + if(index < 0 || index >= display_servers.count()) + return; + const auto &server = display_servers[index]; - // TODO: connect + // TODO: check if already registered and connect + + RegistDialog regist_dialog(settings, server.GetHostAddr(), this); + regist_dialog.exec(); } void MainWindow::UpdateDiscoveryEnabled() diff --git a/gui/src/registdialog.cpp b/gui/src/registdialog.cpp index 11b0fe1..154e99e 100644 --- a/gui/src/registdialog.cpp +++ b/gui/src/registdialog.cpp @@ -20,31 +20,169 @@ #include #include #include +#include +#include +#include +#include -static const QRegularExpression pin_re("[0-9][0-9][0-9][0-9][0-9][0-9]"); +Q_DECLARE_METATYPE(ChiakiLogLevel) -RegistDialog::RegistDialog(Settings *settings, QWidget *parent) +#define PIN_LENGTH 8 + +static const QRegularExpression pin_re(QString("[0-9]").repeated(PIN_LENGTH)); + +RegistDialog::RegistDialog(Settings *settings, QString host, QWidget *parent) : QDialog(parent), settings(settings) { - regist_active = false; + setWindowTitle(tr("Register Console")); - auto layout = new QFormLayout(this); + auto layout = new QVBoxLayout(this); setLayout(layout); + auto form_layout = new QFormLayout(); + layout->addLayout(form_layout); + host_edit = new QLineEdit(this); - layout->addRow(tr("Host:"), host_edit); + form_layout->addRow(tr("Host:"), host_edit); + host_edit->setText(host); psn_id_edit = new QLineEdit(this); - layout->addRow(tr("PSN ID (username):"), psn_id_edit); + form_layout->addRow(tr("PSN ID (username):"), psn_id_edit); pin_edit = new QLineEdit(this); pin_edit->setValidator(new QRegularExpressionValidator(pin_re, pin_edit)); - layout->addRow(tr("PIN:"), pin_edit); + form_layout->addRow(tr("PIN:"), pin_edit); + + button_box = new QDialogButtonBox(QDialogButtonBox::Cancel, this); + register_button = button_box->addButton(tr("Register"), QDialogButtonBox::AcceptRole); + layout->addWidget(button_box); + connect(button_box, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); + + connect(host_edit, &QLineEdit::textChanged, this, &RegistDialog::ValidateInput); + connect(psn_id_edit, &QLineEdit::textChanged, this, &RegistDialog::ValidateInput); + connect(pin_edit, &QLineEdit::textChanged, this, &RegistDialog::ValidateInput); + ValidateInput(); } RegistDialog::~RegistDialog() { - if(regist_active) - chiaki_regist_fini(®ist); -} \ No newline at end of file +} + +void RegistDialog::ValidateInput() +{ + bool valid = !host_edit->text().trimmed().isEmpty() + && !psn_id_edit->text().trimmed().isEmpty() + && pin_edit->text().length() == PIN_LENGTH; + register_button->setEnabled(valid); +} + +void RegistDialog::accept() +{ + ChiakiRegistInfo info = {}; + QByteArray psn_id = psn_id_edit->text().toUtf8(); + QByteArray host = host_edit->text().toUtf8(); + info.psn_id = psn_id.data(); + info.host = host.data(); + info.pin = (uint32_t)pin_edit->text().toULong(); + + RegistExecuteDialog execute_dialog(info, this); + int r = execute_dialog.exec(); + // TODO: check r + //close(); +} + +static void RegistExecuteDialogLogCb(ChiakiLogLevel level, const char *msg, void *user); +static void RegistExecuteDialogRegistCb(ChiakiRegistEvent *event, void *user); + +RegistExecuteDialog::RegistExecuteDialog(const ChiakiRegistInfo ®ist_info, QWidget *parent) + : QDialog(parent) +{ + setWindowTitle(tr("Register Console")); + + auto layout = new QVBoxLayout(this); + setLayout(layout); + + log_edit = new QPlainTextEdit(this); + log_edit->setReadOnly(true); + log_edit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); + layout->addWidget(log_edit); + + button_box = new QDialogButtonBox(QDialogButtonBox::Cancel, this); + layout->addWidget(button_box); + connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); + + chiaki_log_init(&log, CHIAKI_LOG_ALL & ~CHIAKI_LOG_VERBOSE, RegistExecuteDialogLogCb, this); + chiaki_regist_start(®ist, &log, ®ist_info, RegistExecuteDialogRegistCb, this); + + resize(600, 400); +} + +RegistExecuteDialog::~RegistExecuteDialog() +{ + chiaki_regist_stop(®ist); + chiaki_regist_fini(®ist); +} + +void RegistExecuteDialog::Log(ChiakiLogLevel level, QString msg) +{ + log_edit->appendPlainText(QString("[%1] %2").arg(chiaki_log_level_char(level)).arg(msg)); + log_edit->verticalScrollBar()->setValue(log_edit->verticalScrollBar()->maximum()); +} + +void RegistExecuteDialog::Finished() +{ + auto cancel_button = button_box->button(QDialogButtonBox::Cancel); + if(!cancel_button) + return; + button_box->removeButton(cancel_button); + button_box->addButton(QDialogButtonBox::Close); +} + +void RegistExecuteDialog::Success() +{ + printf("finished\n"); + Finished(); +} + +void RegistExecuteDialog::Failed() +{ + Finished(); +} + + +class RegistExecuteDialogPrivate +{ + public: + static void Log(RegistExecuteDialog *dialog, ChiakiLogLevel level, QString msg) + { QMetaObject::invokeMethod(dialog, "Log", Qt::ConnectionType::QueuedConnection, Q_ARG(ChiakiLogLevel, level), Q_ARG(QString, msg)); } + + static void RegistEvent(RegistExecuteDialog *dialog, ChiakiRegistEvent *event) + { + switch(event->type) + { + case CHIAKI_REGIST_EVENT_TYPE_FINISHED_SUCCESS: + QMetaObject::invokeMethod(dialog, "Success", Qt::ConnectionType::QueuedConnection); + break; + case CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED: + QMetaObject::invokeMethod(dialog, "Failed", Qt::ConnectionType::QueuedConnection); + break; + default: + break; + } + } +}; + +static void RegistExecuteDialogLogCb(ChiakiLogLevel level, const char *msg, void *user) +{ + chiaki_log_cb_print(level, msg, nullptr); + auto dialog = reinterpret_cast(user); + RegistExecuteDialogPrivate::Log(dialog, level, msg); +} + +static void RegistExecuteDialogRegistCb(ChiakiRegistEvent *event, void *user) +{ + auto dialog = reinterpret_cast(user); + RegistExecuteDialogPrivate::RegistEvent(dialog, event); +} diff --git a/lib/include/chiaki/regist.h b/lib/include/chiaki/regist.h index e62fb0e..76f29fc 100644 --- a/lib/include/chiaki/regist.h +++ b/lib/include/chiaki/regist.h @@ -58,7 +58,7 @@ typedef struct chiaki_regist_t ChiakiStopPipe stop_pipe; } ChiakiRegist; -CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user); +CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, const ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user); CHIAKI_EXPORT void chiaki_regist_fini(ChiakiRegist *regist); CHIAKI_EXPORT void chiaki_regist_stop(ChiakiRegist *regist); diff --git a/lib/src/regist.c b/lib/src/regist.c index 4b4dce6..9c99bf8 100644 --- a/lib/src/regist.c +++ b/lib/src/regist.c @@ -32,7 +32,7 @@ static void *regist_thread_func(void *user); static int regist_connect(ChiakiRegist *regist); -CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user) +CHIAKI_EXPORT ChiakiErrorCode chiaki_regist_start(ChiakiRegist *regist, ChiakiLog *log, const ChiakiRegistInfo *info, ChiakiRegistCb cb, void *cb_user) { regist->log = log; regist->info = *info; @@ -138,17 +138,19 @@ static void *regist_thread_func(void *user) goto fail; } + CHIAKI_LOGI(regist->log, "Regist connected to %s", regist->info.host); + int s = send(sock, request_header, request_header_size, 0); if(s < 0) { - CHIAKI_LOGE(regist->log, "Regist failed to send request header"); + CHIAKI_LOGE(regist->log, "Regist failed to send request header: %s", strerror(errno)); goto fail_socket; } - s = send(s, payload, payload_size, 0); + s = send(sock, payload, payload_size, 0); if(s < 0) { - CHIAKI_LOGE(regist->log, "Regist failed to send payload"); + CHIAKI_LOGE(regist->log, "Regist failed to send payload: %s", strerror(errno)); goto fail_socket; } @@ -158,7 +160,7 @@ rerecv: received = recv(sock, recv_buf, sizeof(recv_buf) - 1, 0); if(received < 0) CHIAKI_LOGE(regist->log, "Failed"); - else + else if(received > 0) { chiaki_log_hexdump(regist->log, CHIAKI_LOG_DEBUG, (uint8_t *)recv_buf, received); goto rerecv; @@ -183,7 +185,6 @@ static int regist_connect(ChiakiRegist *regist) if(r != 0) { CHIAKI_LOGE(regist->log, "Regist failed to getaddrinfo on %s", regist->info.host); - regist_event_simple(regist, CHIAKI_REGIST_EVENT_TYPE_FINISHED_FAILED); return -1; }