From 99fb690ad754ca07289ea6476a8fb3b54fb3a891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Sat, 3 Aug 2019 12:59:30 +0200 Subject: [PATCH] Make Ctrl stoppable --- lib/include/chiaki/ctrl.h | 3 ++ lib/include/chiaki/session.h | 7 ----- lib/src/ctrl.c | 54 ++++++++++++++++++++++++++---------- lib/src/session.c | 8 +++--- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/lib/include/chiaki/ctrl.h b/lib/include/chiaki/ctrl.h index 2f740d0..438a703 100644 --- a/lib/include/chiaki/ctrl.h +++ b/lib/include/chiaki/ctrl.h @@ -20,6 +20,7 @@ #include "common.h" #include "thread.h" +#include "stoppipe.h" #include #include @@ -32,6 +33,7 @@ typedef struct chiaki_ctrl_t { struct chiaki_session_t *session; ChiakiThread thread; + ChiakiStopPipe stop_pipe; int sock; uint8_t recv_buf[512]; size_t recv_buf_size; @@ -39,6 +41,7 @@ typedef struct chiaki_ctrl_t } ChiakiCtrl; 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); #ifdef __cplusplus diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h index 2f3235c..3318be2 100644 --- a/lib/include/chiaki/session.h +++ b/lib/include/chiaki/session.h @@ -174,13 +174,6 @@ static inline void chiaki_session_set_video_sample_cb(ChiakiSession *session, Ch session->video_sample_cb_user = user; } -static inline void chiaki_session_set_quit_reason(ChiakiSession *session, ChiakiQuitReason reason) -{ - if(session->quit_reason != CHIAKI_QUIT_REASON_NONE) - return; - session->quit_reason = reason; -} - #ifdef __cplusplus } #endif diff --git a/lib/src/ctrl.c b/lib/src/ctrl.c index 91c02ac..65e6c04 100644 --- a/lib/src/ctrl.c +++ b/lib/src/ctrl.c @@ -30,6 +30,8 @@ #define SESSION_CTRL_PORT 9295 +#define CTRL_EXPECT_TIMEOUT 5000 + typedef enum ctrl_message_type_t { CTRL_MESSAGE_TYPE_SESSION_ID = 0x33, CTRL_MESSAGE_TYPE_HEARTBEAT_REQ = 0xfe, @@ -42,18 +44,38 @@ static void *ctrl_thread_func(void *user); CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_start(ChiakiCtrl *ctrl, ChiakiSession *session) { ctrl->session = session; + ChiakiErrorCode err = chiaki_stop_pipe_init(&ctrl->stop_pipe); + if(err != CHIAKI_ERR_SUCCESS) + return err; return chiaki_thread_create(&ctrl->thread, ctrl_thread_func, ctrl); } +CHIAKI_EXPORT void chiaki_ctrl_stop(ChiakiCtrl *ctrl) +{ + chiaki_stop_pipe_stop(&ctrl->stop_pipe); +} + CHIAKI_EXPORT ChiakiErrorCode chiaki_ctrl_join(ChiakiCtrl *ctrl) { - return chiaki_thread_join(&ctrl->thread, NULL); + ChiakiErrorCode err = chiaki_thread_join(&ctrl->thread, NULL); + chiaki_stop_pipe_fini(&ctrl->stop_pipe); + return err; } static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl); static void ctrl_message_received(ChiakiCtrl *ctrl, uint16_t msg_type, uint8_t *payload, size_t payload_size); +static void ctrl_failed(ChiakiCtrl *ctrl, ChiakiQuitReason reason) +{ + ChiakiErrorCode mutex_err = chiaki_mutex_lock(&ctrl->session->state_mutex); + assert(mutex_err == CHIAKI_ERR_SUCCESS); + ctrl->session->quit_reason = reason; + ctrl->session->ctrl_failed = true; + chiaki_mutex_unlock(&ctrl->session->state_mutex); + chiaki_cond_signal(&ctrl->session->state_cond); +} + static void *ctrl_thread_func(void *user) { ChiakiCtrl *ctrl = user; @@ -61,11 +83,7 @@ static void *ctrl_thread_func(void *user) ChiakiErrorCode err = ctrl_connect(ctrl); if(err != CHIAKI_ERR_SUCCESS) { - chiaki_session_set_quit_reason(ctrl->session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); - chiaki_mutex_lock(&ctrl->session->state_mutex); - ctrl->session->ctrl_failed = true; - chiaki_mutex_unlock(&ctrl->session->state_mutex); - chiaki_cond_signal(&ctrl->session->state_cond); + ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); return NULL; } @@ -100,7 +118,15 @@ static void *ctrl_thread_func(void *user) if(overflow) { - chiaki_session_set_quit_reason(ctrl->session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); + ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); + break; + } + + err = chiaki_stop_pipe_select_single(&ctrl->stop_pipe, ctrl->sock, UINT64_MAX); + if(err != CHIAKI_ERR_SUCCESS) + { + if(err == CHIAKI_ERR_CANCELED) + CHIAKI_LOGI(&ctrl->session->log, "Ctrl requested to stop"); break; } @@ -108,7 +134,7 @@ static void *ctrl_thread_func(void *user) if(received <= 0) { if(received < 0) - chiaki_session_set_quit_reason(ctrl->session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); + ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); break; } @@ -288,7 +314,7 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl) if(sock < 0) { CHIAKI_LOGE(&session->log, "Session ctrl socket creation failed."); - chiaki_session_set_quit_reason(session, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); + ctrl_failed(ctrl, CHIAKI_QUIT_REASON_CTRL_UNKNOWN); return CHIAKI_ERR_NETWORK; } @@ -298,10 +324,7 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl) { int errsv = errno; CHIAKI_LOGE(&session->log, "Ctrl connect failed: %s", strerror(errsv)); - if(errsv == ECONNREFUSED) - session->quit_reason = CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED; - else - session->quit_reason = CHIAKI_QUIT_REASON_NONE; + ctrl_failed(ctrl, errsv == ECONNREFUSED ? CHIAKI_QUIT_REASON_SESSION_REQUEST_CONNECTION_REFUSED : CHIAKI_QUIT_REASON_CTRL_UNKNOWN); close(sock); return CHIAKI_ERR_NETWORK; } @@ -371,10 +394,11 @@ static ChiakiErrorCode ctrl_connect(ChiakiCtrl *ctrl) size_t header_size; size_t received_size; - err = chiaki_recv_http_header(sock, buf, sizeof(buf), &header_size, &received_size, NULL, UINT64_MAX); // TODO: stop pipe! + err = chiaki_recv_http_header(sock, buf, sizeof(buf), &header_size, &received_size, &ctrl->stop_pipe, CTRL_EXPECT_TIMEOUT); if(err != CHIAKI_ERR_SUCCESS) { - CHIAKI_LOGE(&session->log, "Failed to receive ctrl request response"); + if(err != CHIAKI_ERR_CANCELED) + CHIAKI_LOGE(&session->log, "Failed to receive ctrl request response"); goto error; } diff --git a/lib/src/session.c b/lib/src/session.c index a3a01c1..633f6d7 100644 --- a/lib/src/session.c +++ b/lib/src/session.c @@ -68,6 +68,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_session_init(ChiakiSession *session, Chiaki goto error_state_mutex; session->should_stop = false; + session->ctrl_session_id_received = false; err = chiaki_stream_connection_init(&session->stream_connection, session); if(err != CHIAKI_ERR_SUCCESS) @@ -212,12 +213,11 @@ static void *session_thread_func(void *arg) chiaki_rpcrypt_init(&session->rpcrypt, session->nonce, session->connect_info.morning); - usleep(5000); + // PS4 doesn't always react right away, sleep a bit + chiaki_cond_timedwait_pred(&session->state_cond, &session->state_mutex, 10, session_check_state_pred, session); CHIAKI_LOGI(&session->log, "Starting ctrl"); - session->ctrl_session_id_received = false; - ChiakiErrorCode err = chiaki_ctrl_start(&session->ctrl, session); if(err != CHIAKI_ERR_SUCCESS) QUIT(quit); @@ -306,7 +306,7 @@ quit_audio_receiver: session->audio_receiver = NULL; quit_ctrl: - // TODO: stop ctrl + chiaki_ctrl_stop(&session->ctrl); chiaki_ctrl_join(&session->ctrl); CHIAKI_LOGI(&session->log, "Ctrl stopped");