diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 884d48b..652a4e8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -11,7 +11,6 @@ set(HEADER_FILES include/chiaki/takion.h include/chiaki/senkusha.h include/chiaki/streamconnection.h - include/chiaki/mirai.h include/chiaki/ecdh.h include/chiaki/launchspec.h include/chiaki/random.h @@ -48,7 +47,6 @@ set(SOURCE_FILES src/utils.h src/pb_utils.h src/streamconnection.c - src/mirai.c src/ecdh.c src/launchspec.c src/random.c diff --git a/lib/include/chiaki/mirai.h b/lib/include/chiaki/mirai.h deleted file mode 100644 index e4db2c2..0000000 --- a/lib/include/chiaki/mirai.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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_MIRAI_H -#define CHIAKI_MIRAI_H - -#include "thread.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct chiaki_mirai_t -{ - int request; - int response; - ChiakiMutex mutex; - ChiakiCond cond; -} ChiakiMirai; - -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_init(ChiakiMirai *mirai); -CHIAKI_EXPORT void chiaki_mirai_fini(ChiakiMirai *mirai); -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_signal(ChiakiMirai *mirai, int response); -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_request_begin(ChiakiMirai *mirai, int request, bool first); -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_request_wait(ChiakiMirai *mirai, uint64_t timeout_ms, bool keep_locked); -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_request_unlock(ChiakiMirai *mirai); - -#ifdef __cplusplus -} -#endif - -#endif // CHIAKI_MIRAI_H diff --git a/lib/include/chiaki/senkusha.h b/lib/include/chiaki/senkusha.h index b633e65..0e3e5ec 100644 --- a/lib/include/chiaki/senkusha.h +++ b/lib/include/chiaki/senkusha.h @@ -24,10 +24,33 @@ extern "C" { #endif -struct chiaki_session_t; +typedef struct chiaki_session_t ChiakiSession; +typedef struct senkusha_t +{ + ChiakiSession *session; + ChiakiLog *log; + ChiakiTakion takion; -CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_run(struct chiaki_session_t *session); + int state; + bool state_finished; + bool state_failed; + bool should_stop; + + /** + * signaled on change of state_finished or should_stop + */ + ChiakiCond state_cond; + + /** + * protects state, state_finished, state_failed and should_stop + */ + ChiakiMutex state_mutex; +} ChiakiSenkusha; + +CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_init(ChiakiSenkusha *senkusha, ChiakiSession *session); +CHIAKI_EXPORT void chiaki_senkusha_fini(ChiakiSenkusha *senkusha); +CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_run(ChiakiSenkusha *senkusha); #ifdef __cplusplus } diff --git a/lib/src/mirai.c b/lib/src/mirai.c deleted file mode 100644 index 548243c..0000000 --- a/lib/src/mirai.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 - -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_init(ChiakiMirai *mirai) -{ - mirai->request = -1; - mirai->response = -1; - ChiakiErrorCode err = chiaki_mutex_init(&mirai->mutex, false); - if(err != CHIAKI_ERR_SUCCESS) - return err; - err = chiaki_cond_init(&mirai->cond); - if(err != CHIAKI_ERR_SUCCESS) - { - chiaki_mutex_fini(&mirai->mutex); - return err; - } - return CHIAKI_ERR_SUCCESS; -} - -CHIAKI_EXPORT void chiaki_mirai_fini(ChiakiMirai *mirai) -{ - chiaki_mutex_fini(&mirai->mutex); - chiaki_cond_fini(&mirai->cond); -} - -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_signal(ChiakiMirai *mirai, int response) -{ - ChiakiErrorCode err = chiaki_mutex_lock(&mirai->mutex); - if(err != CHIAKI_ERR_SUCCESS) - return err; - mirai->response = response; - err = chiaki_cond_signal(&mirai->cond); - if(err != CHIAKI_ERR_SUCCESS) - return err; - return chiaki_mutex_unlock(&mirai->mutex); -} - -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_request_begin(ChiakiMirai *mirai, int request, bool first) -{ - ChiakiErrorCode err = first ? chiaki_mutex_lock(&mirai->mutex) : CHIAKI_ERR_SUCCESS; - mirai->request = request; - return err; -} - -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_request_wait(ChiakiMirai *mirai, uint64_t timeout_ms, bool keep_locked) -{ - ChiakiErrorCode err = chiaki_cond_timedwait(&mirai->cond, &mirai->mutex, timeout_ms); - mirai->request = -1; - if(!keep_locked) - { - ChiakiErrorCode err2 = chiaki_mutex_unlock(&mirai->mutex); - if(err2 != CHIAKI_ERR_SUCCESS) - return err2; - } - return err; -} - -CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_request_unlock(ChiakiMirai *mirai) -{ - return chiaki_mutex_unlock(&mirai->mutex); -} \ No newline at end of file diff --git a/lib/src/senkusha.c b/lib/src/senkusha.c index c5bd5e5..fa8ab4b 100644 --- a/lib/src/senkusha.c +++ b/lib/src/senkusha.c @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -33,43 +32,86 @@ #define SENKUSHA_PORT 9297 -#define BIG_TIMEOUT_MS 5000 - - -typedef struct senkusha_t -{ - ChiakiLog *log; - ChiakiTakion takion; - - ChiakiMirai bang_mirai; -} Senkusha; - -#define MIRAI_REQUEST_CONNECT 1 -#define MIRAI_REQUEST_BANG 2 +#define EXPECT_TIMEOUT_MS 5000 +typedef enum { + STATE_IDLE, + STATE_TAKION_CONNECT, + STATE_EXPECT_BANG +} SenkushaState; static void senkusha_takion_cb(ChiakiTakionEvent *event, void *user); -static void senkusha_takion_data(Senkusha *senkusha, ChiakiTakionMessageDataType data_type, uint8_t *buf, size_t buf_size); -static ChiakiErrorCode senkusha_send_big(Senkusha *senkusha); -static ChiakiErrorCode senkusha_send_disconnect(Senkusha *senkusha); +static void senkusha_takion_data(ChiakiSenkusha *senkusha, ChiakiTakionMessageDataType data_type, uint8_t *buf, size_t buf_size); +static ChiakiErrorCode senkusha_send_big(ChiakiSenkusha *senkusha); +static ChiakiErrorCode senkusha_send_disconnect(ChiakiSenkusha *senkusha); -CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_run(ChiakiSession *session) +CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_init(ChiakiSenkusha *senkusha, ChiakiSession *session) { - Senkusha senkusha; - senkusha.log = &session->log; - ChiakiErrorCode err = chiaki_mirai_init(&senkusha.bang_mirai); + senkusha->session = session; + senkusha->log = &session->log; + + ChiakiErrorCode err = chiaki_mutex_init(&senkusha->state_mutex, false); if(err != CHIAKI_ERR_SUCCESS) - goto error_bang_mirai; + goto error; + + err = chiaki_cond_init(&senkusha->state_cond); + if(err != CHIAKI_ERR_SUCCESS) + goto error_state_mutex; + + senkusha->state = STATE_IDLE; + senkusha->state_finished = false; + senkusha->state_failed = false; + senkusha->should_stop = false; + + return CHIAKI_ERR_SUCCESS; + +error_state_mutex: + chiaki_mutex_fini(&senkusha->state_mutex); +error: + return err; +} + +CHIAKI_EXPORT void chiaki_senkusha_fini(ChiakiSenkusha *senkusha) +{ + chiaki_cond_fini(&senkusha->state_cond); + chiaki_mutex_fini(&senkusha->state_mutex); +} + +static bool state_finished_cond_check(void *user) +{ + ChiakiSenkusha *senkusha = user; + return senkusha->state_finished || senkusha->should_stop; +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_run(ChiakiSenkusha *senkusha) +{ + ChiakiSession *session = senkusha->session; + ChiakiErrorCode err; + + err = chiaki_mutex_lock(&senkusha->state_mutex); + assert(err == CHIAKI_ERR_SUCCESS); + +#define QUIT(quit_label) do { \ + chiaki_mutex_unlock(&senkusha->state_mutex); \ + goto quit_label; \ + } while(0) + + if(senkusha->should_stop) + { + err = CHIAKI_ERR_CANCELED; + goto quit; + } ChiakiTakionConnectInfo takion_info; - takion_info.log = senkusha.log; + takion_info.log = senkusha->log; takion_info.sa_len = session->connect_info.host_addrinfo_selected->ai_addrlen; takion_info.sa = malloc(takion_info.sa_len); if(!takion_info.sa) { err = CHIAKI_ERR_MEMORY; - goto error_bang_mirai; + QUIT(quit); } + memcpy(takion_info.sa, session->connect_info.host_addrinfo_selected->ai_addr, takion_info.sa_len); err = set_port(takion_info.sa, htons(SENKUSHA_PORT)); assert(err == CHIAKI_ERR_SUCCESS); @@ -77,83 +119,96 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_senkusha_run(ChiakiSession *session) takion_info.enable_crypt = false; takion_info.cb = senkusha_takion_cb; - takion_info.cb_user = &senkusha; + takion_info.cb_user = senkusha; - err = chiaki_mirai_request_begin(&senkusha.bang_mirai, MIRAI_REQUEST_CONNECT, true); - assert(err == CHIAKI_ERR_SUCCESS); + senkusha->state = STATE_TAKION_CONNECT; + senkusha->state_finished = false; + senkusha->state_failed = false; - err = chiaki_takion_connect(&senkusha.takion, &takion_info); + err = chiaki_takion_connect(&senkusha->takion, &takion_info); free(takion_info.sa); if(err != CHIAKI_ERR_SUCCESS) { CHIAKI_LOGE(&session->log, "Senkusha connect failed"); - goto error_bang_mirai; + QUIT(quit); } - err = chiaki_mirai_request_wait(&senkusha.bang_mirai, BIG_TIMEOUT_MS, false); + err = chiaki_cond_timedwait_pred(&senkusha->state_cond, &senkusha->state_mutex, EXPECT_TIMEOUT_MS, state_finished_cond_check, senkusha); assert(err == CHIAKI_ERR_SUCCESS || err == CHIAKI_ERR_TIMEOUT); - - if(!senkusha.bang_mirai.response) + if(!senkusha->state_finished) { if(err == CHIAKI_ERR_TIMEOUT) CHIAKI_LOGE(&session->log, "Senkusha connect timeout"); - CHIAKI_LOGE(&session->log, "Senkusha Takion connect failed"); - err = CHIAKI_ERR_UNKNOWN; - goto error_takion; + if(senkusha->should_stop) + err = CHIAKI_ERR_CANCELED; + else + CHIAKI_LOGE(&session->log, "Senkusha Takion connect failed"); + + QUIT(quit_takion); } CHIAKI_LOGI(&session->log, "Senkusha sending big"); - err = chiaki_mirai_request_begin(&senkusha.bang_mirai, MIRAI_REQUEST_BANG, true); - assert(err == CHIAKI_ERR_SUCCESS); - - err = senkusha_send_big(&senkusha); + senkusha->state = STATE_EXPECT_BANG; + senkusha->state_finished = false; + senkusha->state_failed = false; + err = senkusha_send_big(senkusha); if(err != CHIAKI_ERR_SUCCESS) { CHIAKI_LOGE(&session->log, "Senkusha failed to send big"); - goto error_takion; + QUIT(quit_takion); } - err = chiaki_mirai_request_wait(&senkusha.bang_mirai, BIG_TIMEOUT_MS, false); + err = chiaki_cond_timedwait_pred(&senkusha->state_cond, &senkusha->state_mutex, EXPECT_TIMEOUT_MS, state_finished_cond_check, senkusha); assert(err == CHIAKI_ERR_SUCCESS || err == CHIAKI_ERR_TIMEOUT); - if(!senkusha.bang_mirai.response) + if(!senkusha->state_finished) { if(err == CHIAKI_ERR_TIMEOUT) CHIAKI_LOGE(&session->log, "Senkusha bang receive timeout"); - CHIAKI_LOGE(&session->log, "Senkusha didn't receive bang"); - err = CHIAKI_ERR_UNKNOWN; - goto error_takion; + if(senkusha->should_stop) + err = CHIAKI_ERR_CANCELED; + else + CHIAKI_LOGE(&session->log, "Senkusha didn't receive bang"); + + QUIT(quit_takion); } CHIAKI_LOGI(&session->log, "Senkusha successfully received bang"); + // TODO: Do the actual tests + CHIAKI_LOGI(&session->log, "Senkusha is disconnecting"); - senkusha_send_disconnect(&senkusha); + senkusha_send_disconnect(senkusha); + chiaki_mutex_unlock(&senkusha->state_mutex); err = CHIAKI_ERR_SUCCESS; -error_takion: - chiaki_takion_close(&senkusha.takion); +quit_takion: + chiaki_takion_close(&senkusha->takion); CHIAKI_LOGI(&session->log, "Senkusha closed takion"); -error_bang_mirai: - chiaki_mirai_fini(&senkusha.bang_mirai); +quit: return err; } static void senkusha_takion_cb(ChiakiTakionEvent *event, void *user) { - Senkusha *senkusha = user; + ChiakiSenkusha *senkusha = user; switch(event->type) { case CHIAKI_TAKION_EVENT_TYPE_CONNECTED: case CHIAKI_TAKION_EVENT_TYPE_DISCONNECT: - if(senkusha->bang_mirai.request == MIRAI_REQUEST_CONNECT) + chiaki_mutex_lock(&senkusha->state_mutex); + if(senkusha->state == STATE_TAKION_CONNECT) { - chiaki_mirai_signal(&senkusha->bang_mirai, event->type == CHIAKI_TAKION_EVENT_TYPE_CONNECTED); + senkusha->state_finished = event->type == CHIAKI_TAKION_EVENT_TYPE_CONNECTED; + senkusha->state_failed = event->type == CHIAKI_TAKION_EVENT_TYPE_DISCONNECT; + chiaki_cond_signal(&senkusha->state_cond); } + chiaki_mutex_unlock(&senkusha->state_mutex); + break; case CHIAKI_TAKION_EVENT_TYPE_DATA: senkusha_takion_data(senkusha, event->data.data_type, event->data.buf, event->data.buf_size); break; @@ -162,7 +217,7 @@ static void senkusha_takion_cb(ChiakiTakionEvent *event, void *user) } } -static void senkusha_takion_data(Senkusha *senkusha, ChiakiTakionMessageDataType data_type, uint8_t *buf, size_t buf_size) +static void senkusha_takion_data(ChiakiSenkusha *senkusha, ChiakiTakionMessageDataType data_type, uint8_t *buf, size_t buf_size) { if(data_type != CHIAKI_TAKION_MESSAGE_DATA_TYPE_PROTOBUF) return; @@ -178,18 +233,23 @@ static void senkusha_takion_data(Senkusha *senkusha, ChiakiTakionMessageDataType return; } - if(senkusha->bang_mirai.request == MIRAI_REQUEST_BANG) + chiaki_mutex_lock(&senkusha->state_mutex); + if(senkusha->state == STATE_EXPECT_BANG) { if(msg.type != tkproto_TakionMessage_PayloadType_BANG || !msg.has_bang_payload) { CHIAKI_LOGE(senkusha->log, "Senkusha expected bang payload but received something else"); - return; } - chiaki_mirai_signal(&senkusha->bang_mirai, 1); + else + { + senkusha->state_finished = true; + chiaki_cond_signal(&senkusha->state_cond); + } } + chiaki_mutex_unlock(&senkusha->state_mutex); } -static ChiakiErrorCode senkusha_send_big(Senkusha *senkusha) +static ChiakiErrorCode senkusha_send_big(ChiakiSenkusha *senkusha) { tkproto_TakionMessage msg; memset(&msg, 0, sizeof(msg)); @@ -221,7 +281,7 @@ static ChiakiErrorCode senkusha_send_big(Senkusha *senkusha) return err; } -static ChiakiErrorCode senkusha_send_disconnect(Senkusha *senkusha) +static ChiakiErrorCode senkusha_send_disconnect(ChiakiSenkusha *senkusha) { tkproto_TakionMessage msg; memset(&msg, 0, sizeof(msg)); diff --git a/lib/src/session.c b/lib/src/session.c index 6ce494f..3f070e5 100644 --- a/lib/src/session.c +++ b/lib/src/session.c @@ -166,6 +166,8 @@ static bool session_check_state_pred(void *user) || session->ctrl_session_id_received; } +//#define ENABLE_SENKUSHA + static void *session_thread_func(void *arg) { ChiakiSession *session = arg; @@ -217,21 +219,30 @@ static void *session_thread_func(void *arg) QUIT(quit_ctrl); } - //CHIAKI_LOGI(&session->log, "Starting Senkusha"); +#ifdef ENABLE_SENKUSHA + CHIAKI_LOGI(&session->log, "Starting Senkusha"); + + ChiakiSenkusha senkusha; + err = chiaki_senkusha_init(&senkusha, session); + if(err != CHIAKI_ERR_SUCCESS) + QUIT(quit_ctrl); + + err = chiaki_senkusha_run(&senkusha); + chiaki_senkusha_fini(&senkusha); - /* TODO err = chiaki_senkusha_run(session); if(err != CHIAKI_ERR_SUCCESS) { CHIAKI_LOGE(&session->log, "Senkusha failed"); - goto quit_ctrl; - }*/ + QUIT(quit_ctrl); + } + + CHIAKI_LOGI(&session->log, "Senkusha completed successfully"); +#endif // TODO: Senkusha should set that session->mtu = 1454; session->rtt = 12; - //CHIAKI_LOGI(&session->log, "Senkusha completed successfully"); - err = chiaki_random_bytes(session->handshake_key, sizeof(session->handshake_key)); if(err != CHIAKI_ERR_SUCCESS) { diff --git a/lib/src/streamconnection.c b/lib/src/streamconnection.c index 09c8582..de714d7 100644 --- a/lib/src/streamconnection.c +++ b/lib/src/streamconnection.c @@ -113,7 +113,7 @@ CHIAKI_EXPORT void chiaki_stream_connection_fini(ChiakiStreamConnection *stream_ } -bool state_finished_cond_check(void *user) +static bool state_finished_cond_check(void *user) { ChiakiStreamConnection *stream_connection = user; return stream_connection->state_finished || stream_connection->should_stop; @@ -150,11 +150,14 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnectio if(err != CHIAKI_ERR_SUCCESS) { CHIAKI_LOGE(&session->log, "StreamConnection connect failed"); + chiaki_mutex_unlock(&stream_connection->state_mutex); return err; } + // TODO: timeout? err = chiaki_cond_wait_pred(&stream_connection->state_cond, &stream_connection->state_mutex, state_finished_cond_check, stream_connection); assert(err == CHIAKI_ERR_SUCCESS || err == CHIAKI_ERR_TIMEOUT); + // TODO: check stop if(err != CHIAKI_ERR_SUCCESS) { CHIAKI_LOGE(&session->log, "StreamConnection Takion connect failed"); @@ -181,6 +184,8 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiStreamConnectio if(err == CHIAKI_ERR_TIMEOUT) CHIAKI_LOGE(&session->log, "StreamConnection bang receive timeout"); + // TODO: check canceled and don't report error + CHIAKI_LOGE(&session->log, "StreamConnection didn't receive bang or failed to handle it"); err = CHIAKI_ERR_UNKNOWN; goto disconnect;