commit 970dec76ff23f35477364098e7e1e280648ce3a4 Author: Karutoh Date: Sun Mar 23 03:08:20 2025 -0700 Initial commit. diff --git a/.gitea/workflows/BuildRelease.yaml b/.gitea/workflows/BuildRelease.yaml new file mode 100644 index 0000000..9d8e3ca --- /dev/null +++ b/.gitea/workflows/BuildRelease.yaml @@ -0,0 +1,104 @@ +name: Build & Release +run-name: ${{ gitea.actor }} is testing out Gitea Actions +on: + push: + tags: + - "v*" + +jobs: + Windows-AMD64-Build: + runs-on: windows-x86_64 + steps: + - name: Check out repository code + uses: actions/checkout@v3 + + - name: Building/Compiling/Installing Project + run: | + cd ${{ gitea.workspace }} + cmake -A x64 -DCMAKE_BUILD_TYPE=Release --preset=default . + cd build + cmake --build . --config Release + + - name: Creating Appropriate Directories + run: | + cd ${{ gitea.workspace }} + mv build/Release/DeviceScanner.exe . + mv build/Release/zlib1.dll . + + - name: Zipping Binaries + run: | + cd ${{ gitea.workspace }} + tar -a -c -f device-scanner-windows-amd64.zip DeviceScanner.exe zlib1.dll + + - uses: https://github.com/actions/setup-go@v4 + with: + go-version: '>=1.20.1' + + - name: Use Go Action + id: use-go-action + uses: https://gitea.com/actions/release-action@main + with: + files: |- + device-scanner-windows-amd64.zip + api_key: '${{secrets.RELEASE_TOKEN}}' + + Linux-AMD64-Build: + runs-on: linux-x86_64 + steps: + - name: Check out repository code + uses: actions/checkout@v3 + + - name: Installing Dependencies + run: | + sudo pacman -S --noconfirm zip alsa-lib libxcb xcb-util-cursor + + - name: Building/Compiling/Installing Project + run: | + cd ${{ gitea.workspace }} + cmake -DCMAKE_BUILD_TYPE=Release . + cmake --build . --config Release + + - name: Zipping Binaries + run: zip -r device-scanner-linux-amd64.zip DeviceScanner + + - uses: https://github.com/actions/setup-go@v4 + with: + go-version: '>=1.20.1' + + - name: Use Go Action + id: use-go-action + uses: https://gitea.com/actions/release-action@main + with: + files: |- + device-scanner-linux-amd64.zip + api_key: '${{secrets.RELEASE_TOKEN}}' + + Linux-AARCH64-Build: + runs-on: linux-aarch64 + steps: + - name: Check out repository code + uses: actions/checkout@v3 + + - name: Installing Dependencies + run: sudo apt install -y zip libasound2-dev libxcb1-dev libxcb-xinput-dev libxcb-cursor-dev + + - name: Building/Compiling/Installing Project + run: | + cd ${{ gitea.workspace }} + cmake -DCMAKE_BUILD_TYPE=Release . + cmake --build . --config Release + + - name: Zipping Binaries + run: zip -r device-scanner-linux-aarch64.zip DeviceScanner + + - uses: https://github.com/actions/setup-go@v4 + with: + go-version: '>=1.20.1' + + - name: Use Go Action + id: use-go-action + uses: https://gitea.com/actions/release-action@main + with: + files: |- + device-scanner-linux-aarch64.zip + api_key: '${{secrets.RELEASE_TOKEN}}' \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ef9bfbf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.18.4) +project(DeviceScanner C CXX) + +if (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows") + set(IS_OS_WINDOWS TRUE) + set(USER_HOME_DIRECTORY $ENV{USERPROFILE}) + message("Building for the Windows operating system.") +elseif (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux") + set(IS_OS_LINUX TRUE) + set(USER_HOME_DIRECTORY $ENV{HOME}) + add_compile_options(-Wno-stringop-overflow) + message("Building for the Linux operating system.") +elseif (${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin") + set(IS_OS_MAC TRUE) + set(USER_HOME_DIRECTORY $ENV{HOME}) + message("Building for the Mac operating system.") +endif () + +if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "AMD64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64") + message("Building for AMD64 architecture.") + set(IS_ARCH_AMD64 TRUE) +elseif ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ARM64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") + message("Building for ARM64 architecture.") + set(IS_ARCH_ARM64 TRUE) +endif () + +set(CMAKE_CXX_STANDARD 20) + +add_executable(DeviceScanner main.cpp) + +if (IS_OS_WINDOWS) + add_compile_definitions(VK_USE_PLATFORM_WIN32_KHR) +elseif (IS_OS_LINUX) + add_compile_definitions(VK_USE_PLATFORM_WAYLAND_KHR EHS_WS_WAYLAND) +endif() + +target_link_directories(DeviceScanner PRIVATE "${USER_HOME_DIRECTORY}/.local/lib") +target_include_directories(DeviceScanner PRIVATE "${USER_HOME_DIRECTORY}/.local/include") + +find_package(ZLIB REQUIRED) +if (ZLIB_FOUND) + message(STATUS "ZLIB was found.") +else () + message(STATUS "ZLIB was not found.") +endif () + +find_package(OpenSSL REQUIRED) +if (OpenSSL_FOUND) + message(STATUS "OpenSSL was found.") +else () + message(STATUS "OpenSSL was not found.") +endif () + +target_link_libraries(DeviceScanner PRIVATE OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB EHS_Stc wayland-client) \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..dd37d3f --- /dev/null +++ b/main.cpp @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ehs; + +union IPv4 +{ + UInt_32 address; + UInt_8 octets[4]; +}; + +struct Result +{ + IPv4 address; + bool response; + UInt_8 padding[3]; +}; + +struct PingData +{ + Result* results; + UInt_64 count; +}; + +UInt_64 resultsPerThread = CPU::GetCacheLineSize() / sizeof(Result); + +Str_8 AddressToStr(const IPv4 &address) +{ + Str_8 result; + result += address.octets[0]; + result += "."; + result += address.octets[1]; + result += "."; + result += address.octets[2]; + result += "."; + result += address.octets[3]; + return result; +} + +UInt_32 Ping(void *data) +{ + PingData* pingData = (PingData*)data; + + Serializer payload(Endianness::LE); + payload.WriteStr("Hello world!"); + + ICMP icmp(IP::V4); + icmp.SetReceiveTimeout(1); + + for (UInt_32 i = 0; i < pingData->count; ++i) + { + const UInt_16 id = HRNG::Generate_u16(); + + icmp.SendEchoRequest(AddressToStr(pingData->results[i].address), {id, (UInt_16)(i + 1)}, payload, payload.Size()); + + Str_8 inAddr; + ICMP_Header header = {}; + + Serializer inPayload = Serializer(Endianness::LE); + UInt_64 received = icmp.Receive(inAddr, header, inPayload); + if (!received) + continue; + + ICMP_EchoRequest er = inPayload.Read(); + + if (er.id != id) + continue; + + pingData->results[i].response = true; + } + + return 0; +} + +IPv4 StrToAddress(const Str_8 &address) +{ + const Vector octets = address.Split("."); + if (octets.Size() != 4) + return {}; + + IPv4 result; + result.octets[0] = octets[0].ToDecimal(); + result.octets[1] = octets[1].ToDecimal(); + result.octets[2] = octets[2].ToDecimal(); + result.octets[3] = octets[3].ToDecimal(); + + return result; +} + +UInt_8 GetClass(const IPv4 &address) +{ + if (address.octets[0] >= 1 && address.octets[0] <= 126) + return 0; + else if (address.octets[0] >= 128 && address.octets[0] <= 191) + return 1; + else if (address.octets[0] >= 192 && address.octets[0] <= 223) + return 2; + else + return EHS_UINT_8_MAX; +} + +IPv4 GetSubnetMask(const UInt_8 &ipClass) +{ + switch (ipClass) + { + case 0: + return {0x000000FF}; + case 1: + return {0x0000FFFF}; + case 2: + return {0x00FFFFFF}; + default: + return {0x00000000}; + } +} + +int main() +{ + Initialize("Device Scanner", "Release", {1, 0, 0}); + Log::EnableImmediateMode(true); + + Console::Write_8("Default Gateway: ", false); + Str_8 gateway = Console::Read_8(); + IPv4 octets = StrToAddress(gateway); + UInt_8 ipClass = GetClass(octets); + IPv4 subnetMask = GetSubnetMask(ipClass); + + IPv4 networkAddress = {octets.address & subnetMask.address}; + IPv4 invertedMask = {~subnetMask.address}; + IPv4 broadcastAddress = {octets.address | invertedMask.address}; + + IPv4 firstAddress = {networkAddress.address}; + firstAddress.octets[3] += 1; + + IPv4 lastAddress = {broadcastAddress.address}; + lastAddress.octets[3] -= 1; + + Console::Write_8("\nIP Class: " + Str_8::FromNum(ipClass)); + Console::Write_8("Subnet Mask: " + AddressToStr(subnetMask)); + Console::Write_8("Network Address: " + AddressToStr(networkAddress)); + Console::Write_8("Inverted Mask: " + AddressToStr(invertedMask)); + Console::Write_8("Broadcast Address: " + AddressToStr(broadcastAddress)); + Console::Write_8("First Address: " + AddressToStr(firstAddress)); + Console::Write_8("Last Address: " + AddressToStr(lastAddress) + "\n"); + + Array results(lastAddress.octets[3] - firstAddress.octets[3]); + for (UInt_64 i = 0; i < results.Size(); ++i) + { + results[i] = {}; + results[i].address = networkAddress; + results[i].address.octets[3] = firstAddress.octets[3] + i; + results[i].response = false; + } + + Array threads((UInt_64)Math::Ceil((double)results.Size() / (double)resultsPerThread)); + Array pings(threads.Size()); + + for (UInt_64 i = 0; i < threads.Size(); ++i) + { + UInt_64 offset = i * resultsPerThread; + if (offset + resultsPerThread > results.Size()) + { + UInt_64 delta = results.Size() - offset; + + pings[i].results = &results[offset]; + pings[i].count = delta; + } + else + { + pings[i].results = &results[offset]; + pings[i].count = resultsPerThread; + } + } + + for (UInt_64 i = 0; i < threads.Size(); ++i) + threads[i].Start(Ping, &pings[i]); + + for (UInt_64 i = 0; i < threads.Size(); ++i) + threads[i].Join(); + + Console::Write_8("Active Devices:"); + + for (UInt_64 i = 0; i < results.Size(); ++i) + { + if (!results[i].response) + continue; + + Console::Write_8(AddressToStr(results[i].address)); + } + + Uninitialize(); + + return 0; +} \ No newline at end of file