Skip to content

Commit bff0221

Browse files
committed
feat(net): initial net module with NetworkProbe (v0.1.0)
- Introduce standalone net module - Provide NetworkProbe for connectivity and reachability checks - Expose public CMake target vix::net
1 parent d8c179d commit bff0221

5 files changed

Lines changed: 281 additions & 0 deletions

File tree

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,14 @@
3939

4040
# debug information files
4141
*.dwo
42+
43+
.vscode/
44+
build/
45+
vix.log
46+
cmd.md
47+
build/
48+
build-ninja/
49+
.vix-test/
50+
.vix_test_inflight/
51+
.vix_test/
52+
.vix_test_perm/

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
This project follows [Semantic Versioning](https://semver.org/).
6+
7+
---
8+
9+
## [0.1.0] — 2026-01-12
10+
11+
### Added
12+
13+
- Initial `net` module providing low-level networking utilities.
14+
- `NetworkProbe` for connectivity and reachability detection.
15+
- Public CMake target `vix::net`.
16+
17+
### Notes
18+
19+
- First standalone release of the Vix networking primitives.
20+
- Designed as a lightweight, dependency-minimal foundation for higher-level modules.

CMakeLists.txt

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# ====================================================================
2+
# Vix.cpp — Net Module
3+
# ====================================================================
4+
# Purpose:
5+
# Low-level networking primitives for Vix (connectivity probing,
6+
# reachability checks, lightweight network utilities). Builds as
7+
# STATIC when sources exist, otherwise as a header-only INTERFACE target.
8+
#
9+
# Public Targets:
10+
# - vix_net : The actual library target (STATIC or INTERFACE)
11+
# - vix::net : Namespaced alias for consumers
12+
#
13+
# Public Dependencies:
14+
# - vix::utils
15+
#
16+
# Options:
17+
# - VIX_ENABLE_SANITIZERS : Inherit sanitizers from the parent project
18+
#
19+
# Installation/Export:
20+
# Installs into the umbrella export-set `VixTargets`.
21+
# ====================================================================
22+
23+
cmake_minimum_required(VERSION 3.20)
24+
project(vix_net VERSION 0.1.0 LANGUAGES CXX)
25+
26+
include(GNUInstallDirs)
27+
28+
# ------------------------ Global settings ----------------------------
29+
set(CMAKE_CXX_STANDARD 20)
30+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
31+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
32+
33+
# ------------------------ Sources discovery --------------------------
34+
file(GLOB_RECURSE NET_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
35+
36+
# ------------------------ Utils dependency (robust) ------------------
37+
option(VIX_NET_FETCH_UTILS "Auto-fetch vix::utils if missing" ON)
38+
39+
if (NOT TARGET vix::utils)
40+
if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/../utils/CMakeLists.txt")
41+
message(STATUS "[net] Adding utils from umbrella: ../utils")
42+
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../utils" "utils")
43+
elseif (VIX_NET_FETCH_UTILS)
44+
include(FetchContent)
45+
message(STATUS "[net] Fetching vix::utils via FetchContent")
46+
FetchContent_Declare(vix_utils
47+
GIT_REPOSITORY https://github.com/vixcpp/utils.git
48+
GIT_TAG dev
49+
)
50+
FetchContent_MakeAvailable(vix_utils)
51+
else()
52+
message(FATAL_ERROR "vix::utils not found. Enable VIX_NET_FETCH_UTILS=ON or provide the target before net.")
53+
endif()
54+
endif()
55+
56+
set(VIX_UTILS_TARGET vix::utils)
57+
if (NOT TARGET ${VIX_UTILS_TARGET} AND TARGET vix::utils)
58+
set(VIX_UTILS_TARGET vix::utils)
59+
endif()
60+
61+
# ============================== STATIC ===============================
62+
if (NET_SOURCES)
63+
message(STATUS "[net] Building STATIC library with detected sources.")
64+
65+
add_library(vix_net STATIC ${NET_SOURCES})
66+
67+
if (TARGET vix_warnings)
68+
message(STATUS "[net] vix_warnings detected (from umbrella)")
69+
target_link_libraries(vix_net PUBLIC vix_warnings)
70+
if (VIX_ENABLE_SANITIZERS AND TARGET vix_sanitizers)
71+
target_link_libraries(vix_net INTERFACE vix_sanitizers)
72+
endif()
73+
else()
74+
message(STATUS "[net] vix_warnings not found (building net standalone)")
75+
endif()
76+
77+
add_library(vix::net ALIAS vix_net)
78+
target_compile_features(vix_net PUBLIC cxx_std_20)
79+
80+
target_include_directories(vix_net
81+
PUBLIC
82+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
83+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
84+
)
85+
86+
target_link_libraries(vix_net
87+
PUBLIC
88+
${VIX_UTILS_TARGET}
89+
)
90+
91+
set_target_properties(vix_net PROPERTIES
92+
OUTPUT_NAME vix_net
93+
VERSION ${PROJECT_VERSION}
94+
SOVERSION 0
95+
EXPORT_NAME net
96+
)
97+
98+
install(TARGETS vix_net
99+
EXPORT VixTargets
100+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
101+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
102+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
103+
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
104+
)
105+
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
106+
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h")
107+
108+
# ============================ HEADER-ONLY ============================
109+
else()
110+
message(STATUS "[net] Building HEADER-ONLY library (no sources).")
111+
112+
add_library(vix_net INTERFACE)
113+
add_library(vix::net ALIAS vix_net)
114+
target_compile_features(vix_net INTERFACE cxx_std_20)
115+
116+
target_include_directories(vix_net INTERFACE
117+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
118+
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
119+
)
120+
121+
target_link_libraries(vix_net INTERFACE
122+
${VIX_UTILS_TARGET}
123+
)
124+
125+
if (VIX_ENABLE_SANITIZERS AND TARGET vix_sanitizers)
126+
target_link_libraries(vix_net INTERFACE vix_sanitizers)
127+
endif()
128+
129+
install(TARGETS vix_net
130+
EXPORT VixTargets
131+
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
132+
)
133+
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
134+
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h")
135+
endif()
136+
137+
# ----------------------------- Tests ---------------------------------
138+
option(VIX_NET_BUILD_TESTS "Build net module tests" OFF)
139+
140+
if (VIX_NET_BUILD_TESTS)
141+
include(CTest)
142+
enable_testing()
143+
add_subdirectory(tests)
144+
endif()
145+
146+
# ----------------------------- Summary -------------------------------
147+
message(STATUS "------------------------------------------------------")
148+
message(STATUS "vix::net configured (${PROJECT_VERSION})")
149+
if (NET_SOURCES)
150+
message(STATUS "Mode: STATIC / sources found")
151+
else()
152+
message(STATUS "Mode: HEADER-ONLY / no sources")
153+
endif()
154+
message(STATUS "Utils target: ${VIX_UTILS_TARGET}")
155+
message(STATUS "Include dir: ${CMAKE_CURRENT_SOURCE_DIR}/include (for <vix/...>)")
156+
message(STATUS "Sanitizers (inherited): ${VIX_ENABLE_SANITIZERS}")
157+
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
158+
message(STATUS "------------------------------------------------------")

include/vix/net/NetworkProbe.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <functional>
5+
6+
namespace vix::net
7+
{
8+
9+
class NetworkProbe
10+
{
11+
public:
12+
using ProbeFn = std::function<bool()>; // returns true if online
13+
14+
struct Config
15+
{
16+
std::int64_t min_interval_ms{1000};
17+
std::int64_t online_ttl_ms{2000}; // cached online validity
18+
std::int64_t offline_ttl_ms{500}; // cached offline validity
19+
};
20+
21+
NetworkProbe(Config cfg, ProbeFn fn);
22+
23+
bool isOnline(std::int64_t now_ms) const;
24+
bool refresh(std::int64_t now_ms);
25+
bool lastKnownOnline() const noexcept { return last_online_; }
26+
std::int64_t lastProbeAtMs() const noexcept { return last_probe_at_ms_; }
27+
28+
private:
29+
bool canProbe(std::int64_t now_ms) const noexcept;
30+
31+
private:
32+
Config cfg_;
33+
ProbeFn probe_;
34+
35+
bool last_online_{false};
36+
std::int64_t last_probe_at_ms_{0};
37+
std::int64_t last_update_ms_{0};
38+
};
39+
40+
} // namespace vix::net

src/NetworkProbe.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <vix/net/NetworkProbe.hpp>
2+
3+
namespace vix::net
4+
{
5+
6+
NetworkProbe::NetworkProbe(Config cfg, ProbeFn fn)
7+
: cfg_(cfg), probe_(std::move(fn))
8+
{
9+
}
10+
11+
bool NetworkProbe::canProbe(std::int64_t now_ms) const noexcept
12+
{
13+
return (now_ms - last_probe_at_ms_) >= cfg_.min_interval_ms;
14+
}
15+
16+
bool NetworkProbe::isOnline(std::int64_t now_ms) const
17+
{
18+
const auto age = now_ms - last_update_ms_;
19+
const auto ttl = last_online_ ? cfg_.online_ttl_ms : cfg_.offline_ttl_ms;
20+
21+
if (age <= ttl)
22+
{
23+
return last_online_;
24+
}
25+
// cache expired -> caller should call refresh()
26+
return last_online_;
27+
}
28+
29+
bool NetworkProbe::refresh(std::int64_t now_ms)
30+
{
31+
if (!probe_)
32+
{
33+
// No probe function -> assume online (or false). Choose conservative?
34+
last_online_ = true;
35+
last_update_ms_ = now_ms;
36+
return last_online_;
37+
}
38+
39+
if (!canProbe(now_ms))
40+
{
41+
// Too soon: return cached
42+
return last_online_;
43+
}
44+
45+
last_probe_at_ms_ = now_ms;
46+
const bool ok = probe_();
47+
last_online_ = ok;
48+
last_update_ms_ = now_ms;
49+
return last_online_;
50+
}
51+
52+
} // namespace vix::net

0 commit comments

Comments
 (0)