diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 52c7bac..ac3bafc 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,7 +7,8 @@ set(HEADER_FILES include/chiaki/http.h include/chiaki/log.h include/chiaki/ctrl.h - include/chiaki/rpcrypt.h) + include/chiaki/rpcrypt.h + include/chiaki/takion.h) set(SOURCE_FILES src/common.c @@ -17,7 +18,8 @@ set(SOURCE_FILES src/http.c src/log.c src/ctrl.c - src/rpcrypt.c) + src/rpcrypt.c + src/takion.c) add_library(chiaki-lib ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/lib/include/chiaki/log.h b/lib/include/chiaki/log.h index ed70a30..666cacf 100644 --- a/lib/include/chiaki/log.h +++ b/lib/include/chiaki/log.h @@ -39,10 +39,10 @@ typedef struct chiaki_log_t void chiaki_log(ChiakiLog *log, ChiakiLogLevel level, const char *fmt, ...); void chiaki_log_hexdump(ChiakiLog *log, ChiakiLogLevel level, const uint8_t *buf, size_t buf_size); -#define CHIAKI_LOGD(log, ...) do { chiaki_log((log), CHIAKI_LOG_DEBUG, __VA_ARGS__); } while(0); -#define CHIAKI_LOGI(log, ...) do { chiaki_log((log), CHIAKI_LOG_INFO, __VA_ARGS__); } while(0); -#define CHIAKI_LOGW(log, ...) do { chiaki_log((log), CHIAKI_LOG_WARNING, __VA_ARGS__); } while(0); -#define CHIAKI_LOGE(log, ...) do { chiaki_log((log), CHIAKI_LOG_ERROR, __VA_ARGS__); } while(0); +#define CHIAKI_LOGD(log, ...) do { chiaki_log((log), CHIAKI_LOG_DEBUG, __VA_ARGS__); } while(0) +#define CHIAKI_LOGI(log, ...) do { chiaki_log((log), CHIAKI_LOG_INFO, __VA_ARGS__); } while(0) +#define CHIAKI_LOGW(log, ...) do { chiaki_log((log), CHIAKI_LOG_WARNING, __VA_ARGS__); } while(0) +#define CHIAKI_LOGE(log, ...) do { chiaki_log((log), CHIAKI_LOG_ERROR, __VA_ARGS__); } while(0) #ifdef __cplusplus } diff --git a/lib/include/chiaki/session.h b/lib/include/chiaki/session.h index bd7ca76..d761a79 100644 --- a/lib/include/chiaki/session.h +++ b/lib/include/chiaki/session.h @@ -23,6 +23,7 @@ #include "log.h" #include "ctrl.h" #include "rpcrypt.h" +#include "takion.h" #include #include @@ -108,6 +109,8 @@ typedef struct chiaki_session_t ChiakiMutex ctrl_cond_mutex; bool ctrl_session_id_received; + ChiakiTakion takion; + ChiakiLog log; } ChiakiSession; diff --git a/lib/include/chiaki/takion.h b/lib/include/chiaki/takion.h new file mode 100644 index 0000000..84456fb --- /dev/null +++ b/lib/include/chiaki/takion.h @@ -0,0 +1,50 @@ +/* + * 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_TAKION_H +#define CHIAKI_TAKION_H + +#include "common.h" +#include "thread.h" +#include "log.h" + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct chiaki_takion_t +{ + ChiakiLog *log; + int sock; + ChiakiThread thread; + int stop_pipe[2]; +} ChiakiTakion; + +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, ChiakiLog *log, struct sockaddr *sa, socklen_t sa_len); +CHIAKI_EXPORT void chiaki_takion_close(ChiakiTakion *takion); +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *buf, size_t buf_size); + + +#ifdef __cplusplus +} +#endif + +#endif // CHIAKI_TAKION_H diff --git a/lib/src/session.c b/lib/src/session.c index 12cc95d..48f17f5 100644 --- a/lib/src/session.c +++ b/lib/src/session.c @@ -151,9 +151,19 @@ static void *session_thread_func(void *arg) goto quit_ctrl; } - CHIAKI_LOGI(&session->log, "Looking good, we should now start the Senkusha\n"); + CHIAKI_LOGI(&session->log, "Starting Senkusha\n"); + // just testing... + struct sockaddr *sa = malloc(session->connect_info.host_addrinfo_selected->ai_addrlen); + memcpy(sa, session->connect_info.host_addrinfo_selected->ai_addr, session->connect_info.host_addrinfo_selected->ai_addrlen); + if(sa->sa_family == AF_INET) + ((struct sockaddr_in *)sa)->sin_port = 9297; + else if(sa->sa_family == AF_INET6) + ((struct sockaddr_in6 *)sa)->sin6_port = 9297; + chiaki_takion_connect(&session->takion, &session->log, sa, session->connect_info.host_addrinfo_selected->ai_addrlen); + free(sa); + CHIAKI_LOGI(&session->log, "Senkusha started\n"); quit_ctrl: chiaki_ctrl_join(&session->ctrl); diff --git a/lib/src/takion.c b/lib/src/takion.c new file mode 100644 index 0000000..b4129e7 --- /dev/null +++ b/lib/src/takion.c @@ -0,0 +1,230 @@ +/* + * 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 +#include + + +typedef enum takion_packet_type_t { + TAKION_PACKET_TYPE_MESSAGE = 0, + TAKION_PACKET_TYPE_2 = 2, + TAKION_PACKET_TYPE_3 = 3, +} TakionPacketType; + + +typedef struct takion_message_t +{ + uint32_t tag; + //uint8_t zero[4]; + uint32_t key_pos; + + uint8_t type_a; + uint8_t type_b; + uint16_t payload_size; + uint8_t *payload; +} TakionMessage; + + +static void *takion_thread_func(void *user); + +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_connect(ChiakiTakion *takion, ChiakiLog *log, struct sockaddr *sa, socklen_t sa_len) +{ + ChiakiErrorCode ret; + + takion->log = log; + + CHIAKI_LOGI(takion->log, "Takion connecting\n"); + + int r = pipe(takion->stop_pipe); + if(r < 0) + { + return CHIAKI_ERR_UNKNOWN; + } + + r = fcntl(takion->stop_pipe[0], F_SETFL, O_NONBLOCK); + if(r == -1) + { + ret = CHIAKI_ERR_UNKNOWN; + goto error_pipe; + } + + takion->sock = socket(sa->sa_family, SOCK_DGRAM, IPPROTO_UDP); + if(takion->sock < 0) + { + ret = CHIAKI_ERR_NETWORK; + goto error_pipe; + } + + r = connect(takion->sock, sa, sa_len); + if(r < 0) + { + ret = CHIAKI_ERR_NETWORK; + goto error_sock; + } + + CHIAKI_LOGI(takion->log, "Takion connected\n"); + + r = chiaki_thread_create(&takion->thread, takion_thread_func, takion); + if(r != CHIAKI_ERR_SUCCESS) + { + ret = r; + goto error_sock; + } + + uint8_t init_test_packet[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x14\x00\x00H#\x00\x01\x90\x00\x00d\x00d\x00\x00H#"; + chiaki_takion_send(takion, init_test_packet, sizeof(init_test_packet)); + + return CHIAKI_ERR_SUCCESS; + +error_sock: + close(takion->sock); +error_pipe: + close(takion->stop_pipe[0]); + close(takion->stop_pipe[1]); + return ret; +} + +CHIAKI_EXPORT void chiaki_takion_close(ChiakiTakion *takion) +{ + write(takion->stop_pipe[0], "\x00", 1); + chiaki_thread_join(&takion->thread, NULL); + close(takion->stop_pipe[0]); +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send(ChiakiTakion *takion, uint8_t *buf, size_t buf_size) +{ + CHIAKI_LOGI(takion->log, "Takion send:\n"); + chiaki_log_hexdump(takion->log, CHIAKI_LOG_INFO, buf, buf_size); + + ssize_t r = send(takion->sock, buf, buf_size, 0); + if(r < 0) + { + CHIAKI_LOGD(takion->log, "Takion send failed\n"); + return CHIAKI_ERR_NETWORK; + } + return CHIAKI_ERR_SUCCESS; +} + + + +static void takion_handle_packet(ChiakiTakion *takion, uint8_t *buf, size_t buf_size); +static void takion_handle_packet_message(ChiakiTakion *takion, uint8_t *buf, size_t buf_size); + +static void *takion_thread_func(void *user) +{ + ChiakiTakion *takion = user; + + fd_set fds; + + while(true) + { + FD_ZERO(&fds); + FD_SET(takion->sock, &fds); + FD_SET(takion->stop_pipe[1], &fds); + + CHIAKI_LOGD(takion->log, "Takion select\n"); + + int r = select(1, &fds, NULL, NULL, NULL); + if(r < 0) + { + CHIAKI_LOGE(takion->log, "Takion select failed: %s\n", strerror(errno)); + break; + } + + CHIAKI_LOGD(takion->log, "Takion select returned\n"); + + if(FD_ISSET(takion->sock, &fds)) + { + uint8_t buf[1500]; + ssize_t received_sz = recv(takion->sock, buf, sizeof(buf), 0); + if(received_sz <= 0) + { + if(received_sz < 0) + CHIAKI_LOGE(takion->log, "Takion recv failed: %s\n", strerror(errno)); + else + CHIAKI_LOGE(takion->log, "Takion recv returned 0\n"); + break; + } + takion_handle_packet(takion, buf, (size_t)received_sz); + } + } + + close(takion->sock); + close(takion->stop_pipe[1]); + return NULL; +} + + +static void takion_handle_packet(ChiakiTakion *takion, uint8_t *buf, size_t buf_size) +{ + assert(buf_size > 0); + switch(buf[0]) + { + case TAKION_PACKET_TYPE_MESSAGE: + takion_handle_packet_message(takion, buf+1, buf_size-1); + break; + case TAKION_PACKET_TYPE_2: + CHIAKI_LOGW(takion->log, "TODO: Handle Takion Packet type 2\n"); + break; + case TAKION_PACKET_TYPE_3: + CHIAKI_LOGW(takion->log, "TODO: Handle Takion Packet type 3\n"); + break; + default: + CHIAKI_LOGW(takion->log, "Takion packet with unknown type %#x received\n", buf[0]); + break; + } +} + + +static void takion_handle_packet_message(ChiakiTakion *takion, uint8_t *buf, size_t buf_size) +{ + if(buf_size < 0x10) + { + CHIAKI_LOGE(takion->log, "Takion message received that is too short\n"); + return; + } + + TakionMessage msg; + msg.tag = htonl(*((uint32_t *)buf)); + msg.key_pos = htonl(*((uint32_t *)(buf + 0x8))); + msg.type_a = buf[0xc]; + msg.type_a = buf[0xd]; + msg.payload_size = htons(*((uint16_t *)(buf + 0xe))); + + if(buf_size != msg.payload_size + 0xc) + { + CHIAKI_LOGE(takion->log, "Takion received message payload size mismatch\n"); + return; + } + + msg.payload_size -= 0x4; + + if(msg.payload_size > 0) + msg.payload = buf + 0x10; + else + msg.payload = NULL; + + CHIAKI_LOGI(takion->log, "Takion received message with tag %#x, key pos %#x, type (%#x, %#x), payload size %#x, payload:\n", msg.tag, msg.key_pos, msg.type_a, msg.type_b, msg.payload_size); + chiaki_log_hexdump(takion->log, CHIAKI_LOG_INFO, msg.payload, msg.payload_size); +}