diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt
index 45bc9df..65e8d1c 100644
--- a/gui/CMakeLists.txt
+++ b/gui/CMakeLists.txt
@@ -63,7 +63,9 @@ add_executable(chiaki WIN32
src/manualhostdialog.cpp
res/resources.qrc
include/controllermanager.h
- src/controllermanager.cpp)
+ src/controllermanager.cpp
+ include/loginpindialog.h
+ src/loginpindialog.cpp)
target_include_directories(chiaki PRIVATE include)
target_link_libraries(chiaki chiaki-lib)
diff --git a/gui/include/loginpindialog.h b/gui/include/loginpindialog.h
new file mode 100644
index 0000000..2784694
--- /dev/null
+++ b/gui/include/loginpindialog.h
@@ -0,0 +1,44 @@
+/*
+ * 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_LOGINPINDIALOG_H
+#define CHIAKI_LOGINPINDIALOG_H
+
+#include
+
+class QLineEdit;
+class QDialogButtonBox;
+
+class LoginPINDialog : public QDialog
+{
+ Q_OBJECT
+
+ private:
+ QString pin;
+
+ QLineEdit *pin_edit;
+ QDialogButtonBox *button_box;
+
+ void UpdateButtons();
+
+ public:
+ explicit LoginPINDialog(QWidget *parent = nullptr);
+
+ QString GetPIN() { return pin; }
+};
+
+#endif // CHIAKI_LOGINPINDIALOG_H
diff --git a/gui/include/streamsession.h b/gui/include/streamsession.h
index b555577..c695e0b 100644
--- a/gui/include/streamsession.h
+++ b/gui/include/streamsession.h
@@ -92,6 +92,8 @@ class StreamSession : public QObject
void Start();
void Stop();
+ void SetLoginPIN(const QString &pin);
+
#if CHIAKI_GUI_ENABLE_QT_GAMEPAD
QGamepad *GetGamepad() { return gamepad; }
#endif
@@ -103,6 +105,7 @@ class StreamSession : public QObject
signals:
void CurrentImageUpdated();
void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
+ void LoginPINRequested();
private slots:
void UpdateGamepads();
diff --git a/gui/include/streamwindow.h b/gui/include/streamwindow.h
index ffe3524..ab698f6 100644
--- a/gui/include/streamwindow.h
+++ b/gui/include/streamwindow.h
@@ -47,6 +47,7 @@ class StreamWindow: public QMainWindow
private slots:
void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
+ void LoginPINRequested();
void ToggleFullscreen();
};
diff --git a/gui/src/loginpindialog.cpp b/gui/src/loginpindialog.cpp
new file mode 100644
index 0000000..a9a35ea
--- /dev/null
+++ b/gui/src/loginpindialog.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define PIN_LENGTH 4
+
+static const QRegularExpression pin_re(QString("[0-9]").repeated(PIN_LENGTH));
+
+LoginPINDialog::LoginPINDialog(QWidget *parent) : QDialog(parent)
+{
+ auto layout = new QVBoxLayout(this);
+ setLayout(layout);
+
+ pin_edit = new QLineEdit(this);
+ pin_edit->setPlaceholderText(tr("Login PIN"));
+ pin_edit->setValidator(new QRegularExpressionValidator(pin_re, pin_edit));
+ layout->addWidget(pin_edit);
+ connect(pin_edit, &QLineEdit::textChanged, this, [this](const QString &text) {
+ this->pin = text;
+ UpdateButtons();
+ });
+
+ button_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ layout->addWidget(button_box);
+
+ connect(button_box, &QDialogButtonBox::accepted, this, &QDialog::accept);
+ connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
+
+ UpdateButtons();
+}
+
+void LoginPINDialog::UpdateButtons()
+{
+ button_box->button(QDialogButtonBox::Ok)->setEnabled(pin_edit->text().length() == PIN_LENGTH);
+}
\ No newline at end of file
diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp
index 244f4f1..7dbd244 100644
--- a/gui/src/streamsession.cpp
+++ b/gui/src/streamsession.cpp
@@ -124,6 +124,12 @@ void StreamSession::Stop()
chiaki_session_stop(&session);
}
+void StreamSession::SetLoginPIN(const QString &pin)
+{
+ QByteArray data = pin.toUtf8();
+ chiaki_session_set_login_pin(&session, (const uint8_t *)data.constData(), data.size());
+}
+
void StreamSession::HandleKeyboardEvent(QKeyEvent *event)
{
uint64_t button_mask;
@@ -325,6 +331,9 @@ void StreamSession::Event(ChiakiEvent *event)
case CHIAKI_EVENT_QUIT:
emit SessionQuit(event->quit.reason, event->quit.reason_str ? QString::fromUtf8(event->quit.reason_str) : QString());
break;
+ case CHIAKI_EVENT_LOGIN_PIN_REQUEST:
+ emit LoginPINRequested();
+ break;
}
}
diff --git a/gui/src/streamwindow.cpp b/gui/src/streamwindow.cpp
index b5959ea..4bb4ccb 100644
--- a/gui/src/streamwindow.cpp
+++ b/gui/src/streamwindow.cpp
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
@@ -29,14 +30,16 @@ StreamWindow::StreamWindow(const StreamSessionConnectInfo &connect_info, QWidget
{
setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(qApp->applicationName());
+
+ session = nullptr;
+ av_widget = nullptr;
+
try
{
Init(connect_info);
}
catch(const Exception &e)
{
- session = nullptr;
- av_widget = nullptr;
QMessageBox::critical(this, tr("Stream failed"), tr("Failed to initialize Stream Session: %1").arg(e.what()));
close();
}
@@ -53,6 +56,7 @@ void StreamWindow::Init(const StreamSessionConnectInfo &connect_info)
session = new StreamSession(connect_info, this);
connect(session, &StreamSession::SessionQuit, this, &StreamWindow::SessionQuit);
+ connect(session, &StreamSession::LoginPINRequested, this, &StreamWindow::LoginPINRequested);
av_widget = new AVOpenGLWidget(session->GetVideoDecoder(), this);
setCentralWidget(av_widget);
@@ -90,15 +94,35 @@ void StreamWindow::closeEvent(QCloseEvent *)
void StreamWindow::SessionQuit(ChiakiQuitReason reason, const QString &reason_str)
{
- if(reason == CHIAKI_QUIT_REASON_STOPPED)
- return;
- QString m = tr("Chiaki Session has quit") + ":\n" + chiaki_quit_reason_string(reason);
- if(!reason_str.isEmpty())
- m += "\n" + tr("Reason") + ": \"" + reason_str + "\"";
- QMessageBox::critical(this, tr("Session has quit"), m);
+ if(reason != CHIAKI_QUIT_REASON_STOPPED)
+ {
+ QString m = tr("Chiaki Session has quit") + ":\n" + chiaki_quit_reason_string(reason);
+ if(!reason_str.isEmpty())
+ m += "\n" + tr("Reason") + ": \"" + reason_str + "\"";
+ QMessageBox::critical(this, tr("Session has quit"), m);
+ }
close();
}
+void StreamWindow::LoginPINRequested()
+{
+ auto dialog = new LoginPINDialog(this);
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ connect(dialog, &QDialog::finished, this, [this, dialog](int result) {
+ grabKeyboard();
+
+ if(!session)
+ return;
+
+ if(result == QDialog::Accepted)
+ session->SetLoginPIN(dialog->GetPIN());
+ else
+ session->Stop();
+ });
+ releaseKeyboard();
+ dialog->show();
+}
+
void StreamWindow::ToggleFullscreen()
{
if(isFullScreen())
diff --git a/lib/include/chiaki/ctrl.h b/lib/include/chiaki/ctrl.h
index 4e0258b..e2ab838 100644
--- a/lib/include/chiaki/ctrl.h
+++ b/lib/include/chiaki/ctrl.h
@@ -40,7 +40,7 @@ typedef struct chiaki_ctrl_t
bool should_stop;
bool login_pin_entered;
- uint8_t *login_pin; // not owned
+ uint8_t *login_pin;
size_t login_pin_size;
ChiakiStopPipe notif_pipe;
ChiakiMutex notif_mutex;
@@ -55,7 +55,7 @@ typedef struct chiaki_ctrl_t
CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_start(ChiakiCtrl *ctrl, struct chiaki_session_t *session);
CHIAKI_EXPORT void chiaki_ctrl_stop(ChiakiCtrl *ctrl);
CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_join(ChiakiCtrl *ctrl);
-CHIAKI_EXPORT void chiaki_ctrl_set_login_pin(ChiakiCtrl *ctrl, uint8_t *pin, size_t pin_size);
+CHIAKI_EXPORT void chiaki_ctrl_set_login_pin(ChiakiCtrl *ctrl, const uint8_t *pin, size_t pin_size);
#ifdef __cplusplus
}
diff --git a/lib/include/chiaki/rpcrypt.h b/lib/include/chiaki/rpcrypt.h
index d5b9dcc..12d0705 100644
--- a/lib/include/chiaki/rpcrypt.h
+++ b/lib/include/chiaki/rpcrypt.h
@@ -41,8 +41,8 @@ CHIAKI_EXPORT void chiaki_rpcrypt_aeropause(uint8_t *aeropause, const uint8_t *a
CHIAKI_EXPORT void chiaki_rpcrypt_init_auth(ChiakiRPCrypt *rpcrypt, const uint8_t *nonce, const uint8_t *morning);
CHIAKI_EXPORT void chiaki_rpcrypt_init_regist(ChiakiRPCrypt *rpcrypt, const uint8_t *ambassador, uint32_t pin);
CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt, uint8_t *iv, uint64_t counter);
-CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz);
-CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_decrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_decrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz);
#ifdef __cplusplus
}
diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h
index 8942cc1..f4811da 100644
--- a/lib/include/chiaki/session.h
+++ b/lib/include/chiaki/session.h
@@ -198,7 +198,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_start(ChiakiSession *session);
CHIAKI_EXPORT ChiakiErrorCode chiaki_session_stop(ChiakiSession *session);
CHIAKI_EXPORT ChiakiErrorCode chiaki_session_join(ChiakiSession *session);
CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_controller_state(ChiakiSession *session, ChiakiControllerState *state);
-CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_login_pin(ChiakiSession *session, uint8_t *pin, size_t pin_size);
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_login_pin(ChiakiSession *session, const uint8_t *pin, size_t pin_size);
static inline void chiaki_session_set_event_cb(ChiakiSession *session, ChiakiEventCallback cb, void *user)
{
diff --git a/lib/src/ctrl.c b/lib/src/ctrl.c
index 750838c..fc6651e 100644
--- a/lib/src/ctrl.c
+++ b/lib/src/ctrl.c
@@ -104,15 +104,22 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_join(ChiakiCtrl *ctrl)
ChiakiErrorCode err = chiaki_thread_join(&ctrl->thread, NULL);
chiaki_stop_pipe_fini(&ctrl->notif_pipe);
chiaki_mutex_fini(&ctrl->notif_mutex);
+ free(ctrl->login_pin);
return err;
}
-CHIAKI_EXPORT void chiaki_ctrl_set_login_pin(ChiakiCtrl *ctrl, uint8_t *pin, size_t pin_size)
+CHIAKI_EXPORT void chiaki_ctrl_set_login_pin(ChiakiCtrl *ctrl, const uint8_t *pin, size_t pin_size)
{
+ uint8_t *buf = malloc(pin_size);
+ if(!buf)
+ return;
+ memcpy(buf, pin, pin_size);
ChiakiErrorCode err = chiaki_mutex_lock(&ctrl->notif_mutex);
assert(err == CHIAKI_ERR_SUCCESS);
+ if(ctrl->login_pin_entered)
+ free(ctrl->login_pin);
ctrl->login_pin_entered = true;
- ctrl->login_pin = pin;
+ ctrl->login_pin = buf;
ctrl->login_pin_size = pin_size;
chiaki_stop_pipe_stop(&ctrl->notif_pipe);
chiaki_mutex_unlock(&ctrl->notif_mutex);
@@ -194,8 +201,12 @@ static void *ctrl_thread_func(void *user)
if(ctrl->login_pin_entered)
{
+ CHIAKI_LOGI(ctrl->session->log, "Ctrl received entered Login PIN, sending to console");
ctrl_message_send(ctrl, CTRL_MESSAGE_TYPE_LOGIN_PIN_REP, ctrl->login_pin, ctrl->login_pin_size);
ctrl->login_pin_entered = false;
+ free(ctrl->login_pin);
+ ctrl->login_pin = NULL;
+ ctrl->login_pin_size = 0;
chiaki_stop_pipe_reset(&ctrl->notif_pipe);
}
else
@@ -232,6 +243,21 @@ static ChiakiErrorCode ctrl_message_send(ChiakiCtrl *ctrl, CtrlMessageType type,
{
assert(payload_size == 0 || payload);
+ uint8_t *enc = NULL;
+ if(payload && payload_size)
+ {
+ enc = malloc(payload_size);
+ if(!enc)
+ return CHIAKI_ERR_MEMORY;
+ ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&ctrl->session->rpcrypt, ctrl->crypt_counter_local++, payload, enc, payload_size);
+ if(err != CHIAKI_ERR_SUCCESS)
+ {
+ CHIAKI_LOGE(ctrl->session->log, "Ctrl failed to encrypt payload");
+ free(enc);
+ return err;
+ }
+ }
+
uint8_t header[8];
*((uint32_t *)header) = htonl((uint32_t)payload_size);
*((uint16_t *)(header + 4)) = htons(type);
@@ -244,9 +270,10 @@ static ChiakiErrorCode ctrl_message_send(ChiakiCtrl *ctrl, CtrlMessageType type,
return CHIAKI_ERR_NETWORK;
}
- if(payload)
+ if(enc)
{
- sent = send(ctrl->sock, payload, payload_size, 0);
+ sent = send(ctrl->sock, enc, payload_size, 0);
+ free(enc);
if(sent < 0)
{
CHIAKI_LOGE(ctrl->session->log, "Failed to send Ctrl Message Payload");
@@ -437,7 +464,7 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
uint8_t auth_enc[CHIAKI_RPCRYPT_KEY_SIZE];
- ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (uint8_t *)session->connect_info.regist_key, auth_enc, CHIAKI_RPCRYPT_KEY_SIZE);
+ ChiakiErrorCode err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (const uint8_t *)session->connect_info.regist_key, auth_enc, CHIAKI_RPCRYPT_KEY_SIZE);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char auth_b64[CHIAKI_RPCRYPT_KEY_SIZE*2];
@@ -446,7 +473,7 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
goto error;
uint8_t did_enc[CHIAKI_RP_DID_SIZE];
- err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (uint8_t *)session->connect_info.did, did_enc, CHIAKI_RP_DID_SIZE);
+ err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, session->connect_info.did, did_enc, CHIAKI_RP_DID_SIZE);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char did_b64[CHIAKI_RP_DID_SIZE*2];
@@ -458,7 +485,7 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl)
size_t ostype_len = strlen(SESSION_OSTYPE) + 1;
if(ostype_len > sizeof(ostype_enc))
goto error;
- err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (uint8_t *)SESSION_OSTYPE, ostype_enc, ostype_len);
+ err = chiaki_rpcrypt_encrypt(&session->rpcrypt, ctrl->crypt_counter_local++, (const uint8_t *)SESSION_OSTYPE, ostype_enc, ostype_len);
if(err != CHIAKI_ERR_SUCCESS)
goto error;
char ostype_b64[256];
diff --git a/lib/src/rpcrypt.c b/lib/src/rpcrypt.c
index 4181b09..708947f 100644
--- a/lib/src/rpcrypt.c
+++ b/lib/src/rpcrypt.c
@@ -104,7 +104,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_generate_iv(ChiakiRPCrypt *rpcrypt,
return CHIAKI_ERR_SUCCESS;
}
-static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz, bool encrypt)
+static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz, bool encrypt)
{
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if(!ctx)
@@ -151,12 +151,12 @@ static ChiakiErrorCode chiaki_rpcrypt_crypt(ChiakiRPCrypt *rpcrypt, uint64_t cou
return CHIAKI_ERR_SUCCESS;
}
-CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_encrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz)
{
return chiaki_rpcrypt_crypt(rpcrypt, counter, in, out, sz, true);
}
-CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_decrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, uint8_t *in, uint8_t *out, size_t sz)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_rpcrypt_decrypt(ChiakiRPCrypt *rpcrypt, uint64_t counter, const uint8_t *in, uint8_t *out, size_t sz)
{
return chiaki_rpcrypt_crypt(rpcrypt, counter, in, out, sz, false);
}
diff --git a/lib/src/session.c b/lib/src/session.c
index 112221e..23528c4 100644
--- a/lib/src/session.c
+++ b/lib/src/session.c
@@ -258,12 +258,12 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_controller_state(ChiakiSession
return CHIAKI_ERR_SUCCESS;
}
-CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_login_pin(ChiakiSession *session, uint8_t *pin, size_t pin_size)
+CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_login_pin(ChiakiSession *session, const uint8_t *pin, size_t pin_size)
{
uint8_t *buf = malloc(pin_size);
- memcpy(buf, pin, pin_size);
if(!buf)
return CHIAKI_ERR_MEMORY;
+ memcpy(buf, pin, pin_size);
ChiakiErrorCode err = chiaki_mutex_lock(&session->state_mutex);
assert(err == CHIAKI_ERR_SUCCESS);
if(session->login_pin_entered)
@@ -272,6 +272,8 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_set_login_pin(ChiakiSession *sessio
session->login_pin = buf;
session->login_pin_size = pin_size;
chiaki_mutex_unlock(&session->state_mutex);
+ chiaki_cond_signal(&session->state_cond);
+ return CHIAKI_ERR_SUCCESS;
}
static void session_send_event(ChiakiSession *session, ChiakiEvent *event)
@@ -308,6 +310,14 @@ static bool session_check_state_pred_pin(void *user)
|| session->login_pin_entered;
}
+static bool session_check_state_pred_session_id(void *user)
+{
+ ChiakiSession *session = user;
+ return session->should_stop
+ || session->ctrl_failed
+ || session->ctrl_session_id_received;
+}
+
#define ENABLE_SENKUSHA
static void *session_thread_func(void *arg)
@@ -369,11 +379,16 @@ static void *session_thread_func(void *arg)
goto ctrl_failed;
assert(session->login_pin_entered && session->login_pin);
+ CHIAKI_LOGI(session->log, "Session received entered Login PIN, forwarding to Ctrl");
chiaki_ctrl_set_login_pin(&session->ctrl, session->login_pin, session->login_pin_size);
session->login_pin_entered = false;
free(session->login_pin);
session->login_pin = NULL;
session->login_pin_size = 0;
+
+ // wait for session id again
+ chiaki_cond_timedwait_pred(&session->state_cond, &session->state_mutex, SESSION_EXPECT_TIMEOUT_MS, session_check_state_pred_session_id, session);
+ CHECK_STOP(quit_ctrl);
}
if(!session->ctrl_session_id_received)