Detect Remote Disconnect

This commit is contained in:
Florian Märkl 2019-08-03 20:20:10 +02:00
commit bea03d667a
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
11 changed files with 91 additions and 12 deletions

View file

@ -94,7 +94,7 @@ class StreamSession : public QObject
signals: signals:
void CurrentImageUpdated(); void CurrentImageUpdated();
void SessionQuit(ChiakiQuitReason reason); void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
private slots: private slots:
#if CHIAKI_GUI_ENABLE_QT_GAMEPAD #if CHIAKI_GUI_ENABLE_QT_GAMEPAD

View file

@ -46,7 +46,7 @@ class StreamWindow: public QMainWindow
private slots: private slots:
void FramesAvailable(); void FramesAvailable();
void SessionQuit(ChiakiQuitReason reason); void SessionQuit(ChiakiQuitReason reason, const QString &reason_str);
}; };
#endif // CHIAKI_GUI_STREAMWINDOW_H #endif // CHIAKI_GUI_STREAMWINDOW_H

View file

@ -71,7 +71,7 @@ int main(int argc, char *argv[])
connect_info.did = parser.value(did_option); connect_info.did = parser.value(did_option);
chiaki_connect_video_profile_preset(&connect_info.video_profile, chiaki_connect_video_profile_preset(&connect_info.video_profile,
CHIAKI_VIDEO_RESOLUTION_PRESET_540p, CHIAKI_VIDEO_RESOLUTION_PRESET_360p,
CHIAKI_VIDEO_FPS_PRESET_30); CHIAKI_VIDEO_FPS_PRESET_30);
if(connect_info.registkey.isEmpty() || connect_info.ostype.isEmpty() || connect_info.auth.isEmpty() || connect_info.morning.isEmpty() || connect_info.did.isEmpty()) if(connect_info.registkey.isEmpty() || connect_info.ostype.isEmpty() || connect_info.auth.isEmpty() || connect_info.morning.isEmpty() || connect_info.did.isEmpty())

View file

@ -257,7 +257,7 @@ void StreamSession::Event(ChiakiEvent *event)
switch(event->type) switch(event->type)
{ {
case CHIAKI_EVENT_QUIT: case CHIAKI_EVENT_QUIT:
emit SessionQuit(event->quit.reason); emit SessionQuit(event->quit.reason, event->quit.reason_str ? QString::fromUtf8(event->quit.reason_str) : QString());
break; break;
} }
} }

View file

@ -83,10 +83,13 @@ void StreamWindow::FramesAvailable()
} }
} }
void StreamWindow::SessionQuit(ChiakiQuitReason reason) void StreamWindow::SessionQuit(ChiakiQuitReason reason, const QString &reason_str)
{ {
if(reason == CHIAKI_QUIT_REASON_STOPPED) if(reason == CHIAKI_QUIT_REASON_STOPPED)
return; return;
QMessageBox::critical(this, tr("Session has quit"), tr("Chiaki Session has quit:") + "\n" + chiaki_quit_reason_string(reason)); 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(); close();
} }

View file

@ -35,6 +35,7 @@ typedef enum
CHIAKI_ERR_MEMORY, CHIAKI_ERR_MEMORY,
CHIAKI_ERR_OVERFLOW, CHIAKI_ERR_OVERFLOW,
CHIAKI_ERR_NETWORK, CHIAKI_ERR_NETWORK,
CHIAKI_ERR_DISCONNECTED,
CHIAKI_ERR_INVALID_DATA, CHIAKI_ERR_INVALID_DATA,
CHIAKI_ERR_BUF_TOO_SMALL, CHIAKI_ERR_BUF_TOO_SMALL,
CHIAKI_ERR_MUTEX_LOCKED, CHIAKI_ERR_MUTEX_LOCKED,

View file

@ -86,7 +86,8 @@ typedef enum {
CHIAKI_QUIT_REASON_SESSION_REQUEST_RP_CRASH, CHIAKI_QUIT_REASON_SESSION_REQUEST_RP_CRASH,
CHIAKI_QUIT_REASON_CTRL_UNKNOWN, CHIAKI_QUIT_REASON_CTRL_UNKNOWN,
CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED, CHIAKI_QUIT_REASON_CTRL_CONNECTION_REFUSED,
CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN,
CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED
} ChiakiQuitReason; } ChiakiQuitReason;
CHIAKI_EXPORT const char *chiaki_quit_reason_string(ChiakiQuitReason reason); CHIAKI_EXPORT const char *chiaki_quit_reason_string(ChiakiQuitReason reason);
@ -94,6 +95,7 @@ CHIAKI_EXPORT const char *chiaki_quit_reason_string(ChiakiQuitReason reason);
typedef struct chiaki_quit_event_t typedef struct chiaki_quit_event_t
{ {
ChiakiQuitReason reason; ChiakiQuitReason reason;
const char *reason_str;
} ChiakiQuitEvent; } ChiakiQuitEvent;
typedef struct chiaki_audio_stream_info_event_t typedef struct chiaki_audio_stream_info_event_t
@ -145,6 +147,7 @@ typedef struct chiaki_session_t
ChiakiECDH ecdh; ChiakiECDH ecdh;
ChiakiQuitReason quit_reason; ChiakiQuitReason quit_reason;
char *quit_reason_str; // additional reason string from remote
ChiakiEventCallback event_cb; ChiakiEventCallback event_cb;
void *event_cb_user; void *event_cb_user;

View file

@ -66,6 +66,8 @@ typedef struct chiaki_stream_connection_t
bool state_finished; bool state_finished;
bool state_failed; bool state_failed;
bool should_stop; bool should_stop;
bool remote_disconnected;
char *remote_disconnect_reason;
} ChiakiStreamConnection; } ChiakiStreamConnection;
CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_init(ChiakiStreamConnection *stream_connection, ChiakiSession *session); CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_init(ChiakiStreamConnection *stream_connection, ChiakiSession *session);

View file

@ -32,6 +32,8 @@ CHIAKI_EXPORT const char *chiaki_error_string(ChiakiErrorCode code)
return "Memory error"; return "Memory error";
case CHIAKI_ERR_NETWORK: case CHIAKI_ERR_NETWORK:
return "Network error"; return "Network error";
case CHIAKI_ERR_DISCONNECTED:
return "Disconnected";
case CHIAKI_ERR_INVALID_DATA: case CHIAKI_ERR_INVALID_DATA:
return "Invalid data"; return "Invalid data";
case CHIAKI_ERR_BUF_TOO_SMALL: case CHIAKI_ERR_BUF_TOO_SMALL:

View file

@ -103,6 +103,8 @@ CHIAKI_EXPORT const char *chiaki_quit_reason_string(ChiakiQuitReason reason)
return "Connection Refused in Ctrl"; return "Connection Refused in Ctrl";
case CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN: case CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN:
return "Unknown Error in Stream Connection"; return "Unknown Error in Stream Connection";
case CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED:
return "Remote has disconnected from Stream Connection";
case CHIAKI_QUIT_REASON_NONE: case CHIAKI_QUIT_REASON_NONE:
default: default:
return "Unknown"; return "Unknown";
@ -186,6 +188,7 @@ CHIAKI_EXPORT void chiaki_session_fini(ChiakiSession *session)
{ {
if(!session) if(!session)
return; return;
free(session->quit_reason_str);
chiaki_stream_connection_fini(&session->stream_connection); chiaki_stream_connection_fini(&session->stream_connection);
chiaki_stop_pipe_fini(&session->stop_pipe); chiaki_stop_pipe_fini(&session->stop_pipe);
chiaki_cond_fini(&session->state_cond); chiaki_cond_fini(&session->state_cond);
@ -357,7 +360,13 @@ static void *session_thread_func(void *arg)
chiaki_mutex_unlock(&session->state_mutex); chiaki_mutex_unlock(&session->state_mutex);
err = chiaki_stream_connection_run(&session->stream_connection); err = chiaki_stream_connection_run(&session->stream_connection);
chiaki_mutex_lock(&session->state_mutex); chiaki_mutex_lock(&session->state_mutex);
if(err != CHIAKI_ERR_SUCCESS && err != CHIAKI_ERR_CANCELED) if(err == CHIAKI_ERR_DISCONNECTED)
{
CHIAKI_LOGE(&session->log, "Remote disconnected from StreamConnection");
session->quit_reason = CHIAKI_QUIT_REASON_STREAM_CONNECTION_REMOTE_DISCONNECTED;
session->quit_reason_str = strdup(session->stream_connection.remote_disconnect_reason);
}
else if(err != CHIAKI_ERR_SUCCESS && err != CHIAKI_ERR_CANCELED)
{ {
CHIAKI_LOGE(&session->log, "StreamConnection run failed"); CHIAKI_LOGE(&session->log, "StreamConnection run failed");
session->quit_reason = CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN; session->quit_reason = CHIAKI_QUIT_REASON_STREAM_CONNECTION_UNKNOWN;
@ -388,6 +397,7 @@ quit:
CHIAKI_LOGI(&session->log, "Session has quit"); CHIAKI_LOGI(&session->log, "Session has quit");
quit_event.type = CHIAKI_EVENT_QUIT; quit_event.type = CHIAKI_EVENT_QUIT;
quit_event.quit.reason = session->quit_reason; quit_event.quit.reason = session->quit_reason;
quit_event.quit.reason_str = session->quit_reason_str;
session_send_event(session, &quit_event); session_send_event(session, &quit_event);
return NULL; return NULL;

View file

@ -88,6 +88,8 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_init(ChiakiStreamConnecti
stream_connection->state_finished = false; stream_connection->state_finished = false;
stream_connection->state_failed = false; stream_connection->state_failed = false;
stream_connection->should_stop = false; stream_connection->should_stop = false;
stream_connection->remote_disconnected = false;
stream_connection->remote_disconnect_reason = NULL;
return CHIAKI_ERR_SUCCESS; return CHIAKI_ERR_SUCCESS;
@ -101,6 +103,8 @@ error:
CHIAKI_EXPORT void chiaki_stream_connection_fini(ChiakiStreamConnection *stream_connection) CHIAKI_EXPORT void chiaki_stream_connection_fini(ChiakiStreamConnection *stream_connection)
{ {
free(stream_connection->remote_disconnect_reason);
chiaki_gkcrypt_free(stream_connection->gkcrypt_remote); chiaki_gkcrypt_free(stream_connection->gkcrypt_remote);
chiaki_gkcrypt_free(stream_connection->gkcrypt_local); chiaki_gkcrypt_free(stream_connection->gkcrypt_local);
@ -116,7 +120,7 @@ CHIAKI_EXPORT void chiaki_stream_connection_fini(ChiakiStreamConnection *stream_
static bool state_finished_cond_check(void *user) static bool state_finished_cond_check(void *user)
{ {
ChiakiStreamConnection *stream_connection = user; ChiakiStreamConnection *stream_connection = user;
return stream_connection->state_finished || stream_connection->should_stop; return stream_connection->state_finished || stream_connection->should_stop || stream_connection->remote_disconnected;
} }
CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnection *stream_connection) CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnection *stream_connection)
@ -145,7 +149,6 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnectio
#define CHECK_STOP(quit_label) do { \ #define CHECK_STOP(quit_label) do { \
if(stream_connection->should_stop) \ if(stream_connection->should_stop) \
{ \ { \
session->quit_reason = CHIAKI_QUIT_REASON_STOPPED; \
goto quit_label; \ goto quit_label; \
} } while(0) } } while(0)
@ -259,7 +262,15 @@ disconnect:
stream_connection_send_disconnect(stream_connection); stream_connection_send_disconnect(stream_connection);
if(stream_connection->should_stop) if(stream_connection->should_stop)
{
CHIAKI_LOGI(stream_connection->log, "StreamConnection was requested to stop"); CHIAKI_LOGI(stream_connection->log, "StreamConnection was requested to stop");
err = CHIAKI_ERR_CANCELED;
}
else if(stream_connection->remote_disconnected)
{
CHIAKI_LOGI(stream_connection->log, "StreamConnection closing after Remote disconnected");
err = CHIAKI_ERR_DISCONNECTED;
}
close_takion: close_takion:
chiaki_mutex_unlock(&stream_connection->state_mutex); chiaki_mutex_unlock(&stream_connection->state_mutex);
@ -329,6 +340,36 @@ static void stream_connection_takion_data(ChiakiStreamConnection *stream_connect
chiaki_mutex_unlock(&stream_connection->state_mutex); chiaki_mutex_unlock(&stream_connection->state_mutex);
} }
static void stream_connection_takion_data_handle_disconnect(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size)
{
tkproto_TakionMessage msg;
memset(&msg, 0, sizeof(msg));
char reason[256];
ChiakiPBDecodeBuf decode_buf;
decode_buf.size = 0;
decode_buf.max_size = sizeof(reason) - 1;
decode_buf.buf = (uint8_t *)reason;
msg.disconnect_payload.reason.arg = &decode_buf;
msg.disconnect_payload.reason.funcs.decode = chiaki_pb_decode_buf;
pb_istream_t stream = pb_istream_from_buffer(buf, buf_size);
bool r = pb_decode(&stream, tkproto_TakionMessage_fields, &msg);
if(!r)
{
CHIAKI_LOGE(stream_connection->log, "StreamConnection failed to decode data protobuf");
chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_ERROR, buf, buf_size);
return;
}
reason[decode_buf.size] = '\0';
CHIAKI_LOGI(stream_connection->log, "Remote disconnected from StreamConnection with reason \"%s\"", reason);
stream_connection->remote_disconnected = true;
free(stream_connection->remote_disconnect_reason);
stream_connection->remote_disconnect_reason = strdup(reason);
chiaki_cond_signal(&stream_connection->state_cond);
}
static void stream_connection_takion_data_idle(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size) static void stream_connection_takion_data_idle(ChiakiStreamConnection *stream_connection, uint8_t *buf, size_t buf_size)
{ {
@ -344,8 +385,11 @@ static void stream_connection_takion_data_idle(ChiakiStreamConnection *stream_co
return; return;
} }
//CHIAKI_LOGD(stream_connection->log, "StreamConnection received data"); CHIAKI_LOGV(stream_connection->log, "StreamConnection received data");
//chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_DEBUG, buf, buf_size); chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_VERBOSE, buf, buf_size);
if(msg.type == tkproto_TakionMessage_PayloadType_DISCONNECT)
stream_connection_takion_data_handle_disconnect(stream_connection, buf, buf_size);
} }
static ChiakiErrorCode stream_connection_init_crypt(ChiakiStreamConnection *stream_connection) static ChiakiErrorCode stream_connection_init_crypt(ChiakiStreamConnection *stream_connection)
@ -397,6 +441,12 @@ static void stream_connection_takion_data_expect_bang(ChiakiStreamConnection *st
if(msg.type != tkproto_TakionMessage_PayloadType_BANG || !msg.has_bang_payload) if(msg.type != tkproto_TakionMessage_PayloadType_BANG || !msg.has_bang_payload)
{ {
if(msg.type == tkproto_TakionMessage_PayloadType_DISCONNECT)
{
stream_connection_takion_data_handle_disconnect(stream_connection, buf, buf_size);
return;
}
CHIAKI_LOGE(stream_connection->log, "StreamConnection expected bang payload but received something else"); CHIAKI_LOGE(stream_connection->log, "StreamConnection expected bang payload but received something else");
return; return;
} }
@ -531,6 +581,12 @@ static void stream_connection_takion_data_expect_streaminfo(ChiakiStreamConnecti
if(msg.type != tkproto_TakionMessage_PayloadType_STREAMINFO || !msg.has_stream_info_payload) if(msg.type != tkproto_TakionMessage_PayloadType_STREAMINFO || !msg.has_stream_info_payload)
{ {
if(msg.type == tkproto_TakionMessage_PayloadType_DISCONNECT)
{
stream_connection_takion_data_handle_disconnect(stream_connection, buf, buf_size);
return;
}
CHIAKI_LOGE(stream_connection->log, "StreamConnection expected streaminfo payload but received something else"); CHIAKI_LOGE(stream_connection->log, "StreamConnection expected streaminfo payload but received something else");
chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_VERBOSE, buf, buf_size); chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_VERBOSE, buf, buf_size);
return; return;
@ -710,6 +766,8 @@ static ChiakiErrorCode stream_connection_send_disconnect(ChiakiStreamConnection
return CHIAKI_ERR_UNKNOWN; return CHIAKI_ERR_UNKNOWN;
} }
CHIAKI_LOGI(stream_connection->log, "StreamConnection sending Disconnect");
buf_size = stream.bytes_written; buf_size = stream.bytes_written;
ChiakiErrorCode err = chiaki_takion_send_message_data(&stream_connection->takion, 1, 1, buf, buf_size); ChiakiErrorCode err = chiaki_takion_send_message_data(&stream_connection->takion, 1, 1, buf, buf_size);