diff --git a/.gitmodules b/.gitmodules index 9aae677..ec20004 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "extern/openssl"] path = extern/openssl url = https://github.com/openssl/openssl.git +[submodule "extern/libevent"] + path = extern/libevent + url = https://github.com/libevent/libevent.git +[submodule "extern/log.c"] + path = extern/log.c + url = https://github.com/rxi/log.c.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 17bdd13..840ff4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,8 @@ project(voice-chat VERSION 0.1.0 LANGUAGES C) -set(C_STANDARD 23) -set(C_STANDARD_REQUIRED True) - -add_executable(${PROJECT_NAME} src/main.c) - -set(EXTERN "${PROJECT_SOURCE_DIR}/extern") +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED True) # Pull all submodules if haven't already find_package(Git QUIET) @@ -26,9 +22,24 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") endif() endif() -# if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/openssl/CMakeLists.txt") -# message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.") -# endif() +if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/libevent/CMakeLists.txt") + message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.") +endif() + +if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/openssl/Configure") + message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.") +endif() + +set(EXTERN "${PROJECT_SOURCE_DIR}/extern") + +add_executable(${PROJECT_NAME} + src/main.c + "${EXTERN}/log.c/src/log.c" +) + +target_include_directories(${PROJECT_NAME} PRIVATE + "${PROJECT_SOURCE_DIR}/src" +) set(BUILD_DYNAMIC_LIBS ON CACHE BOOL "" FORCE) set(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE) @@ -45,3 +56,9 @@ target_link_directories(${PROJECT_NAME} PRIVATE "${EXTERN}/openssl") target_link_libraries(${PROJECT_NAME} PRIVATE ssl crypto) target_include_directories(${PROJECT_NAME} PRIVATE "${EXTERN}/openssl/include") +# libevent +add_subdirectory("${EXTERN}/libevent") +target_include_directories(${PROJECT_NAME} PRIVATE "${EXTERN}/libevent/include") + +# log.c +target_include_directories(${PROJECT_NAME} PRIVATE "${EXTERN}/log.c/src") diff --git a/CMakePresets.json b/CMakePresets.json index dbba25b..9906321 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -7,8 +7,12 @@ "generator": "Ninja", "binaryDir": "${sourceDir}/build", "cacheVariables": { + "CMAKE_C_COMPILER": "clang", + "CMAKE_BUILD_TYPE": "DEBUG", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": true, + + "EVENT__ENABLE_VERBOSE_DEBUG": true } } ], diff --git a/extern/libevent b/extern/libevent new file mode 160000 index 0000000..a994a52 --- /dev/null +++ b/extern/libevent @@ -0,0 +1 @@ +Subproject commit a994a52d5373d6284b27576efa617aff2baa7bd3 diff --git a/extern/log.c b/extern/log.c new file mode 160000 index 0000000..f9ea349 --- /dev/null +++ b/extern/log.c @@ -0,0 +1 @@ +Subproject commit f9ea34994bd58ed342d2245cd4110bb5c6790153 diff --git a/src/main.c b/src/main.c index 7039131..556d33b 100644 --- a/src/main.c +++ b/src/main.c @@ -1,95 +1,89 @@ -// beep.c -// Build (Linux/macOS): cc beep.c -lm -o beep -// Build (Windows MSVC): cl /O2 beep.c - -#define MINIAUDIO_IMPLEMENTATION -#include "miniaudio.h" - -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include "log.h" -typedef struct { - double phase; - double phase_inc; - uint32_t frames_left; - ma_uint32 channels; -} beep_state; +void +die(const char *errstr, ...) { + va_list ap; -static void data_callback(ma_device* dev, void* out, const void* in, ma_uint32 frameCount) -{ - (void)in; - beep_state* s = (beep_state*)dev->pUserData; - float* output = (float*)out; - - ma_uint32 framesToWrite = frameCount; - if (s->frames_left < framesToWrite) framesToWrite = s->frames_left; - - for (ma_uint32 i = 0; i < framesToWrite; i++) { - float sample = (float)sin(s->phase) * 0.2f; // volume - s->phase += s->phase_inc; - - // keep phase bounded (optional) - if (s->phase >= (2.0 * M_PI)) s->phase -= (2.0 * M_PI); - - for (ma_uint32 ch = 0; ch < s->channels; ch++) { - output[i * s->channels + ch] = sample; - } - } - - // If we ran out early, zero the rest (silence). - for (ma_uint32 i = framesToWrite; i < frameCount; i++) { - for (ma_uint32 ch = 0; ch < s->channels; ch++) { - output[i * s->channels + ch] = 0.0f; - } - } - - s->frames_left -= framesToWrite; - - // Stop after the beep finishes. - if (s->frames_left == 0) { - ma_device_stop(dev); // safe to request stop - } + va_start(ap, errstr); + vfprintf(stderr, errstr, ap); + va_end(ap); + exit(1); } -int main(void) -{ - const double freq = 440.0; - const ma_uint32 sampleRate = 48000; - const double durationSec = 1.0; +// Client connection +typedef struct { + int fd; +} cconnection_t; - beep_state s = {0}; - s.phase = 0.0; - s.phase_inc = (2.0 * M_PI * freq) / (double)sampleRate; - s.frames_left = (uint32_t)(durationSec * (double)sampleRate); - - ma_device_config cfg = ma_device_config_init(ma_device_type_playback); - cfg.playback.format = ma_format_f32; - cfg.playback.channels = 2; - cfg.sampleRate = sampleRate; - cfg.dataCallback = data_callback; - cfg.pUserData = &s; - - ma_device dev; - if (ma_device_init(NULL, &cfg, &dev) != MA_SUCCESS) { - fprintf(stderr, "Failed to init audio device\n"); - return 1; +void* +get_in_addr(struct sockaddr *addr) { + if (addr->sa_family == AF_INET) { + return &((struct sockaddr_in*)addr)->sin_addr; } - s.channels = dev.playback.channels; // in case backend adjusts + return &((struct sockaddr_in6*)addr)->sin6_addr; +} - if (ma_device_start(&dev) != MA_SUCCESS) { - fprintf(stderr, "Failed to start audio device\n"); - ma_device_uninit(&dev); - return 1; +// Returns error or nullptr +char* +connect_server(char *hostname, char *port, cconnection_t *connection) { + int rv; + struct addrinfo hints, *res, *p; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + + if ((rv = getaddrinfo(hostname, port, &hints, &res)) != 0) { + die("error getting address info: %s\n", gai_strerror(rv)); } - // Wait until callback stops the device. - while (ma_device_is_started(&dev)) { - ma_sleep(10); + int fd; + char ip_str[INET6_ADDRSTRLEN]; + for (p = res; p != nullptr; p = p->ai_next) { + if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { + close(fd); + continue; + } + + inet_ntop(p->ai_family, get_in_addr(p->ai_addr), ip_str, sizeof(ip_str)); + if (connect(fd, p->ai_addr, p->ai_addrlen) != 0) { + log_warn("Connection to %s:%s unsuccessful. %s", ip_str, port, strerror(errno)); + continue; + } + + log_info("Connection to %s successful", ip_str); + break; } - ma_device_uninit(&dev); + if (p == nullptr) { + ssize_t err_size = 512; + char *err = malloc(512); + snprintf(err, err_size, "Failed to connect to %s:%s", hostname, port); + return err; + } + + freeaddrinfo(res); + + + return nullptr; +} + +int +main() { + if(nullptr == NULL) return 1; return 0; } - diff --git a/src/ntypes.h b/src/types.h similarity index 89% rename from src/ntypes.h rename to src/types.h index d6a56d8..96ca1b1 100644 --- a/src/ntypes.h +++ b/src/types.h @@ -1,4 +1,4 @@ -// num types +// types #pragma once #include