diff --git a/gui/src/main.cpp b/gui/src/main.cpp index 2948d07..6b423db 100644 --- a/gui/src/main.cpp +++ b/gui/src/main.cpp @@ -25,22 +25,22 @@ int main(int argc, char *argv[]) QCommandLineParser parser; parser.addHelpOption(); - parser.addPositionalArgument("command", "Command"); - parser.addPositionalArgument("host", "Host"); + parser.addPositionalArgument("command", "stream or discover"); + parser.addPositionalArgument("host", "Address to connect to"); - QCommandLineOption regist_key_option("registkey"); + QCommandLineOption regist_key_option("registkey", "", "registkey"); parser.addOption(regist_key_option); - QCommandLineOption ostype_option("ostype", "Win10.0.0"); + QCommandLineOption ostype_option("ostype", "", "ostype", "Win10.0.0"); parser.addOption(ostype_option); - QCommandLineOption auth_option("auth"); + QCommandLineOption auth_option("auth", "", "auth"); parser.addOption(auth_option); - QCommandLineOption morning_option("morning"); + QCommandLineOption morning_option("morning", "", "morning"); parser.addOption(morning_option); - QCommandLineOption did_option("did"); + QCommandLineOption did_option("did", "", "did"); parser.addOption(did_option); diff --git a/lib/include/chiaki/streamconnection.h b/lib/include/chiaki/streamconnection.h index 6c7989a..2f692ff 100644 --- a/lib/include/chiaki/streamconnection.h +++ b/lib/include/chiaki/streamconnection.h @@ -39,6 +39,7 @@ typedef struct chiaki_stream_connection_t uint8_t *ecdh_secret; ChiakiGKCrypt *gkcrypt_local; ChiakiGKCrypt *gkcrypt_remote; + ChiakiPredCond stop_cond; } ChiakiStreamConnection; CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(struct chiaki_session_t *session); diff --git a/lib/include/chiaki/takion.h b/lib/include/chiaki/takion.h index 9c6162b..d351fd9 100644 --- a/lib/include/chiaki/takion.h +++ b/lib/include/chiaki/takion.h @@ -112,7 +112,7 @@ typedef struct chiaki_takion_t CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, ChiakiTakionConnectInfo *info); CHIAKI_EXPORT void chiaki_takion_close(ChiakiTakion *takion); CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_raw(ChiakiTakion *takion, uint8_t *buf, size_t buf_size); -CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *takion, uint32_t key_pos, uint8_t type_b, uint16_t channel, uint8_t *buf, size_t buf_size); +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *takion, uint32_t key_pos, uint8_t *gmac, uint8_t type_b, uint16_t channel, uint8_t *buf, size_t buf_size); CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_congestion(ChiakiTakion *takion, ChiakiTakionCongestionPacket *packet); static inline void chiaki_takion_set_crypt(ChiakiTakion *takion, ChiakiGKCrypt *gkcrypt_local, ChiakiGKCrypt *gkcrypt_remote) { diff --git a/lib/src/congestioncontrol.c b/lib/src/congestioncontrol.c index 3ddcc24..6185648 100644 --- a/lib/src/congestioncontrol.c +++ b/lib/src/congestioncontrol.c @@ -18,7 +18,7 @@ #include -#define CONGESTION_CONTROL_INTERVAL 200 // ms +#define CONGESTION_CONTROL_INTERVAL_MS 200 static void *congestion_control_thread_func(void *user) @@ -31,13 +31,11 @@ static void *congestion_control_thread_func(void *user) while(true) { - err = chiaki_pred_cond_timedwait(&control->stop_cond, CONGESTION_CONTROL_INTERVAL); - if(err != CHIAKI_ERR_SUCCESS && err != CHIAKI_ERR_TIMEOUT) - break; + err = chiaki_pred_cond_timedwait(&control->stop_cond, CONGESTION_CONTROL_INTERVAL_MS); if(err != CHIAKI_ERR_TIMEOUT) break; - CHIAKI_LOGD(control->takion->log, "Sending Congestion Control Packet\n"); + //CHIAKI_LOGD(control->takion->log, "Sending Congestion Control Packet\n"); ChiakiTakionCongestionPacket packet = { 0 }; // TODO: fill with real values chiaki_takion_send_congestion(control->takion, &packet); } diff --git a/lib/src/ctrl.c b/lib/src/ctrl.c index bfffcdf..3eac979 100644 --- a/lib/src/ctrl.c +++ b/lib/src/ctrl.c @@ -229,7 +229,7 @@ static void ctrl_message_received_heartbeat_req(ChiakiCtrl *ctrl, uint8_t *paylo if(payload_size != 0) CHIAKI_LOGW(&ctrl->session->log, "Received Heartbeat request with non-empty payload\n"); - CHIAKI_LOGD(&ctrl->session->log, "Received Heartbeat\n"); + CHIAKI_LOGD(&ctrl->session->log, "Received Ctrl Heartbeat\n"); ctrl_message_send(ctrl, CTRL_MESSAGE_TYPE_HEARTBEAT_REP, NULL, 0); } diff --git a/lib/src/senkusha.c b/lib/src/senkusha.c index 0f495d8..bf1dd6b 100644 --- a/lib/src/senkusha.c +++ b/lib/src/senkusha.c @@ -177,7 +177,7 @@ static ChiakiErrorCode senkusha_send_big(Senkusha *senkusha) } buf_size = stream.bytes_written; - ChiakiErrorCode err = chiaki_takion_send_message_data(&senkusha->takion, 0, 1, 1, buf, buf_size); + ChiakiErrorCode err = chiaki_takion_send_message_data(&senkusha->takion, 0, NULL, 1, 1, buf, buf_size); return err; } @@ -204,7 +204,7 @@ static ChiakiErrorCode senkusha_send_disconnect(Senkusha *senkusha) } buf_size = stream.bytes_written; - ChiakiErrorCode err = chiaki_takion_send_message_data(&senkusha->takion, 0, 1, 1, buf, buf_size); + ChiakiErrorCode err = chiaki_takion_send_message_data(&senkusha->takion, 0, NULL, 1, 1, buf, buf_size); return err; } diff --git a/lib/src/streamconnection.c b/lib/src/streamconnection.c index 1ee9f75..d8fb546 100644 --- a/lib/src/streamconnection.c +++ b/lib/src/streamconnection.c @@ -40,6 +40,8 @@ #define EXPECT_TIMEOUT_MS 5000 +#define HEARTBEAT_INTERVAL_MS 1000 + typedef enum { STREAM_CONNECTION_MIRAI_REQUEST_BANG = 0, @@ -61,6 +63,7 @@ static void stream_connection_takion_data_expect_streaminfo(ChiakiStreamConnecti static ChiakiErrorCode stream_connection_send_streaminfo_ack(ChiakiStreamConnection *stream_connection); static void stream_connection_takion_av(ChiakiTakionAVPacket *packet, void *user); static ChiakiErrorCode stream_connection_takion_mac(uint8_t *buf, size_t buf_size, size_t key_pos, uint8_t *mac_out, void *user); +static ChiakiErrorCode stream_connection_send_heartbeat(ChiakiStreamConnection *stream_connection); CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiSession *session) @@ -71,9 +74,13 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiSession *sessio stream_connection->ecdh_secret = NULL; - ChiakiErrorCode err = chiaki_mirai_init(&stream_connection->mirai); + ChiakiErrorCode err = chiaki_pred_cond_init(&stream_connection->stop_cond); if(err != CHIAKI_ERR_SUCCESS) - goto error_mirai; + goto error; + + err = chiaki_mirai_init(&stream_connection->mirai); + if(err != CHIAKI_ERR_SUCCESS) + goto error_stop_cond; ChiakiTakionConnectInfo takion_info; takion_info.log = stream_connection->log; @@ -170,8 +177,24 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_stream_connection_run(ChiakiSession *sessio CHIAKI_LOGI(&session->log, "StreamConnection successfully received streaminfo\n"); - while(1) - sleep(1); + err = chiaki_pred_cond_lock(&stream_connection->stop_cond); + assert(err == CHIAKI_ERR_SUCCESS); + + while(true) + { + err = chiaki_pred_cond_timedwait(&stream_connection->stop_cond, HEARTBEAT_INTERVAL_MS); + if(err != CHIAKI_ERR_TIMEOUT) + break; + + err = stream_connection_send_heartbeat(stream_connection); + if(err != CHIAKI_ERR_SUCCESS) + CHIAKI_LOGE(stream_connection->log, "StreamConnection failed to send heartbeat\n"); + else + CHIAKI_LOGI(stream_connection->log, "StreamConnection sent heartbeat\n"); + } + + err = chiaki_pred_cond_unlock(&stream_connection->stop_cond); + assert(err == CHIAKI_ERR_SUCCESS); CHIAKI_LOGI(&session->log, "StreamConnection is disconnecting\n"); @@ -188,6 +211,9 @@ error_takion: CHIAKI_LOGI(&session->log, "StreamConnection closed takion\n"); error_mirai: chiaki_mirai_fini(&stream_connection->mirai); +error_stop_cond: + chiaki_pred_cond_fini(&stream_connection->stop_cond); +error: free(stream_connection->ecdh_secret); return err; @@ -499,7 +525,7 @@ static ChiakiErrorCode stream_connection_send_big(ChiakiStreamConnection *stream } buf_size = stream.bytes_written; - err = chiaki_takion_send_message_data(&stream_connection->takion, 0, 1, 1, buf, buf_size); + err = chiaki_takion_send_message_data(&stream_connection->takion, 0, 0, 1, 1, buf, buf_size); return err; } @@ -522,7 +548,7 @@ static ChiakiErrorCode stream_connection_send_streaminfo_ack(ChiakiStreamConnect } buf_size = stream.bytes_written; - return chiaki_takion_send_message_data(&stream_connection->takion, 0, 1, 9, buf, buf_size); + return chiaki_takion_send_message_data(&stream_connection->takion, 0, NULL, 1, 9, buf, buf_size); } static ChiakiErrorCode stream_connection_send_disconnect(ChiakiStreamConnection *stream_connection) @@ -547,7 +573,7 @@ static ChiakiErrorCode stream_connection_send_disconnect(ChiakiStreamConnection } buf_size = stream.bytes_written; - ChiakiErrorCode err = chiaki_takion_send_message_data(&stream_connection->takion, 0, 1, 1, buf, buf_size); + ChiakiErrorCode err = chiaki_takion_send_message_data(&stream_connection->takion, 0, 0 /* TODO: gmac? */,1, 1, buf, buf_size); return err; } @@ -589,3 +615,36 @@ static void stream_connection_takion_av(ChiakiTakionAVPacket *packet, void *user //CHIAKI_LOGD(stream_connection->log, "StreamConnection AV %lu\n", buf_size); //chiaki_log_hexdump(stream_connection->log, CHIAKI_LOG_DEBUG, buf, buf_size); } + + +static ChiakiErrorCode stream_connection_send_heartbeat(ChiakiStreamConnection *stream_connection) +{ + tkproto_TakionMessage msg = { 0 }; + msg.type = tkproto_TakionMessage_PayloadType_HEARTBEAT; + + uint8_t buf[8]; + + pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf)); + bool pbr = pb_encode(&stream, tkproto_TakionMessage_fields, &msg); + if(!pbr) + { + CHIAKI_LOGE(stream_connection->log, "StreamConnection heartbeat protobuf encoding failed\n"); + return CHIAKI_ERR_UNKNOWN; + } + + size_t buf_size = stream.bytes_written; + uint8_t gmac[CHIAKI_GKCRYPT_GMAC_SIZE]; + uint32_t key_pos; + + ChiakiErrorCode err = chiaki_mutex_lock(&stream_connection->takion.gkcrypt_local_mutex); + if(err != CHIAKI_ERR_SUCCESS) + return err; + key_pos = stream_connection->takion.key_pos_local; + err = chiaki_gkcrypt_gmac(stream_connection->takion.gkcrypt_local, key_pos, buf, buf_size, gmac); + stream_connection->takion.key_pos_local += buf_size; + chiaki_mutex_unlock(&stream_connection->takion.gkcrypt_local_mutex); + if(err != CHIAKI_ERR_SUCCESS) + return err; + + return chiaki_takion_send_message_data(&stream_connection->takion, key_pos, gmac, 1, 1, buf, buf_size); +} \ No newline at end of file diff --git a/lib/src/takion.c b/lib/src/takion.c index 9248dbe..5149928 100644 --- a/lib/src/takion.c +++ b/lib/src/takion.c @@ -94,7 +94,7 @@ static void takion_handle_packet_message(ChiakiTakion *takion, uint8_t *buf, siz static void takion_handle_packet_message_data(ChiakiTakion *takion, uint8_t type_b, uint8_t *buf, size_t buf_size); static void takion_handle_packet_message_data_ack(ChiakiTakion *takion, uint8_t type_b, uint8_t *buf, size_t buf_size); static ChiakiErrorCode takion_parse_message(ChiakiTakion *takion, uint8_t *buf, size_t buf_size, TakionMessage *msg); -static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint32_t key_pos, uint8_t type_a, uint8_t type_b, size_t payload_data_size); +static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint8_t *mac, uint32_t key_pos, uint8_t type_a, uint8_t type_b, size_t payload_data_size); static ChiakiErrorCode takion_send_message_init(ChiakiTakion *takion, TakionMessagePayloadInit *payload); static ChiakiErrorCode takion_send_message_cookie(ChiakiTakion *takion, uint8_t *cookie); static ChiakiErrorCode takion_recv(ChiakiTakion *takion, uint8_t *buf, size_t *buf_size, struct timeval *timeout); @@ -269,7 +269,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_raw(ChiakiTakion *takion, uint8 return CHIAKI_ERR_SUCCESS; } -CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *takion, uint32_t key_pos, uint8_t type_b, uint16_t channel, uint8_t *buf, size_t buf_size) +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *takion, uint32_t key_pos, uint8_t *gmac, uint8_t type_b, uint16_t channel, uint8_t *buf, size_t buf_size) { // TODO: can we make this more memory-efficient? // TODO: split packet if necessary? @@ -279,7 +279,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data(ChiakiTakion *taki if(!packet_buf) return CHIAKI_ERR_MEMORY; packet_buf[0] = TAKION_PACKET_TYPE_MESSAGE; - takion_write_message_header(packet_buf + 1, takion->tag_remote, key_pos, TAKION_MESSAGE_TYPE_A_DATA, type_b, 9 + buf_size); + takion_write_message_header(packet_buf + 1, takion->tag_remote, gmac, key_pos, TAKION_MESSAGE_TYPE_A_DATA, type_b, 9 + buf_size); uint8_t *msg_payload = packet_buf + 1 + MESSAGE_HEADER_SIZE; *((uint32_t *)(msg_payload + 0)) = htonl(takion->seq_num_local++); @@ -298,7 +298,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_message_data_ack(ChiakiTakion * { uint8_t buf[1 + MESSAGE_HEADER_SIZE + 0xc]; buf[0] = TAKION_PACKET_TYPE_MESSAGE; - takion_write_message_header(buf + 1, takion->tag_remote, 0, TAKION_MESSAGE_TYPE_A_DATA_ACK, 0, 0xc); + takion_write_message_header(buf + 1, takion->tag_remote, NULL, 0, TAKION_MESSAGE_TYPE_A_DATA_ACK, 0, 0xc); uint8_t *data_ack = buf + 1 + MESSAGE_HEADER_SIZE; *((uint32_t *)(data_ack + 0)) = htonl(seq_num); @@ -328,7 +328,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_congestion(ChiakiTakion *takion if(err != CHIAKI_ERR_SUCCESS) return err; - chiaki_log_hexdump(takion->log, CHIAKI_LOG_DEBUG, buf, sizeof(buf)); + //chiaki_log_hexdump(takion->log, CHIAKI_LOG_DEBUG, buf, sizeof(buf)); return chiaki_takion_send_raw(takion, buf, sizeof(buf)); } @@ -563,10 +563,13 @@ static void takion_handle_packet_message_data_ack(ChiakiTakion *takion, uint8_t * * @param raw_payload_size size of the actual data of the payload excluding type_a, type_b and payload_size */ -static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint32_t key_pos, uint8_t type_a, uint8_t type_b, size_t payload_data_size) +static void takion_write_message_header(uint8_t *buf, uint32_t tag, uint8_t *mac, uint32_t key_pos, uint8_t type_a, uint8_t type_b, size_t payload_data_size) { *((uint32_t *)(buf + 0)) = htonl(tag); - *((uint32_t *)(buf + 4)) = 0; + if(mac) + memcpy(buf + 4, mac, CHIAKI_GKCRYPT_GMAC_SIZE); + else + memset(buf + 4, 0, CHIAKI_GKCRYPT_GMAC_SIZE); *((uint32_t *)(buf + 8)) = htonl(key_pos); *(buf + 0xc) = type_a; *(buf + 0xd) = type_b; @@ -614,7 +617,7 @@ static ChiakiErrorCode takion_send_message_init(ChiakiTakion *takion, TakionMess { uint8_t message[1 + MESSAGE_HEADER_SIZE + 0x10]; message[0] = TAKION_PACKET_TYPE_MESSAGE; - takion_write_message_header(message + 1, takion->tag_remote, 0, TAKION_MESSAGE_TYPE_A_INIT, 0, 0x10); + takion_write_message_header(message + 1, takion->tag_remote, NULL, 0, TAKION_MESSAGE_TYPE_A_INIT, 0, 0x10); uint8_t *pl = message + 1 + MESSAGE_HEADER_SIZE; *((uint32_t *)(pl + 0)) = htonl(payload->tag0); @@ -632,7 +635,7 @@ static ChiakiErrorCode takion_send_message_cookie(ChiakiTakion *takion, uint8_t { uint8_t message[1 + MESSAGE_HEADER_SIZE + TAKION_COOKIE_SIZE]; message[0] = TAKION_PACKET_TYPE_MESSAGE; - takion_write_message_header(message + 1, takion->tag_remote, 0, TAKION_MESSAGE_TYPE_A_COOKIE, 0, TAKION_COOKIE_SIZE); + takion_write_message_header(message + 1, takion->tag_remote, NULL, 0, TAKION_MESSAGE_TYPE_A_COOKIE, 0, TAKION_COOKIE_SIZE); memcpy(message + 1 + MESSAGE_HEADER_SIZE, cookie, TAKION_COOKIE_SIZE); return chiaki_takion_send_raw(takion, message, sizeof(message)); }