Tags give the ability to mark specific points in history as being important
-
0.10.0
5982ff70 · ·Game networking stack: UDP reliability, DTLS transport, delta compression, IPv6, connection migration
-
-
-
-
-
-
0.8.7
9f4c0b25 · ·OmniNet 0.8.7: Fix DB range-query first-row data loss (prompt.txt Bug 1) HIGH-severity bug filed by the daedalus project (consuming OmniNet) via prompt.txt 2026-07-10. Range-based db.query(sql) — returning a QueryResult — silently dropped the first row and yielded an empty row at index 0. Commits since 0.8.6: 9f4c0b2 v0.8.7: Fix DB range-query first-row data loss Fix (src/db/Database.cpp QueryResult ctor): populate m_currentRow from the first step()'s row data. The Iterator ctor already copies m_currentRow from the QueryResult, so no changes needed there. Tests added (4): - database_query_range_first_row_not_empty The exact bug-report repro (a, b, c -> range yields a, b, c in order). - database_query_range_exactly_one_row Single-row edge case. - database_query_callback_still_works Pins the callback overload (daedalus's workaround). - database_query_range_early_break_unlocks_mutex Verifies early break still releases the db mutex. TDD: confirmed the bug reproduced before the fix by reading the new tests showed Assertion '__n < this->size()' failed in stl_vector.h when row[0] was accessed on the empty first-row vector. Verification: - omnet_test: 121/121 PASS (was 117/117) - 17 other suites: all PASS (no regressions) - Full build: clean, no new warnings Reported by: daedalus project via prompt.txt OMNINET-1 (Bug 1) on 2026-07-10. Upgrade mandatory for any user of the range-based db.query(sql) API. -
0.8.6
2dea92b7 · ·OmniNet 0.8.6: SSE unit-test improvements (catches OMNINET-1 regressions) The OMNINET-1 fix in v0.8.5 was correct, but the bug shouldn't have shipped in the first place. This release closes the test coverage gaps that let it through. Commits since 0.8.5: 2dea92b v0.8.6: Improve SSE unit tests to catch OMNINET-1-class regressions Changes: - Socket::isOpen() and Socket::waitForRead() now virtual (public-API-additive, no behavior change). Required for the FakeSocket unit-test mock. - New FakeSocket helper in tests/test_sse_streaming.cpp. Subclasses Socket, overrides recvAll/send/sendAll/close/ isOpen/waitForRead. Drives recv behavior from the test. - 5 new runClientStream unit tests (no HTTP server needed): sse_runClientStream_continues_on_wouldblock OMNINET-1 regression catcher. PROVEN: fails with pre-v0.8.5 buggy code, passes with fix. sse_runClientStream_exits_on_real_eof sse_runClientStream_ignores_client_data sse_runClientStream_calls_remove_client_on_eof sse_runClientStream_fires_on_disconnect_callback - test_idle_connection sleep 500ms -> 1500ms. Now actually exercises idle-survival (was a sub-timeout sleep). Test status: - test_sse_streaming: 31/31 PASS (was 26/26) - omnet_test: 117/117 PASS (no regressions) - 16 other suites: all PASS (no regressions) - Full build: clean, no new warnings -
0.8.5
388a5e63 · ·OmniNet 0.8.5: Fix OMNINET-1 — SSEHandler kills idle connections HIGH-severity bug filed by the codemax team via prompt.txt (2026-07-10). Every OmniNet SSE endpoint died within cfg.keepAliveTimeout seconds (5s default, 1s in tests) because the SSE worker treated recvAll() returning empty as EOF when it was actually wouldBlock (SO_RCVTIMEO firing). Commits since 0.8.4: 0fcd000 Fix OMNINET-1 (v0.8.5): SSEHandler kills idle connections within ~5s 388a5e6 CodeMax.md: mark v0.8.5 task complete Root cause: HttpServer applies cfg.keepAliveTimeout as SO_RCVTIMEO on every accepted socket. After SSE upgrade, the worker thread inherits the timeout. Socket::recv() hides EAGAIN as return 0; Socket::recvAll() returns empty for return 0; the SSE loop treats empty as EOF. Worker exits every 5s, closes socket, browser reconnects. Fix: replace recvAll-based loop with select-based loop using Socket::waitForRead(1h). select() ignores SO_RCVTIMEO so the budget is independent. Shutdown still works via close-from- another-thread -> EBADF -> SocketException -> catch exit. Tests added (3): - sse_idle_survives_keepalive_timeout (sleep 2.5s, verify alive) - sse_idle_with_broadcast_after_long_idle (sleep 3.5s, broadcast OK) - sse_eof_detection_still_works (client close still works) Verification: test_sse_streaming 26/26 PASS (was 23/23), omnet_test 117/117 PASS, all 16 other suites PASS, full build clean, zero warnings. -
0.8.2
469f2b5f · ·OmniNet 0.8.2: HTTP Client Phase 7 (streaming) + EOF detection fixes Phase 7: streaming bodies Request streaming (chunked upload) via ClientRequest::set_body_writer() Response streaming via ClientResponseStream::read_some()/read_all() Client::send_streaming(req) returns ClientResponseStream Supports Transfer-Encoding: chunked, Content-Length, close-delimited EOF detection fix (post-Phase-7 bug) Socket::recvAll() is misleadingly named -- does a single recv() and returns empty on EAGAIN/EWOULDBLOCK (indistinguishable from EOF). HttpClient now drives its own recv() loop with waitForRead() timeout (50ms) so 'no data yet' vs 'peer closed' are correctly distinguished. recv() is wrapped in try/catch to handle abrupt peer closes. Files added/modified: src/http/HttpClient.h: ClientResponseStream, ClientRequest::set_body_writer, Client::send_streaming src/http/HttpClient.cpp: readAll uses recv() loop, recv() wrapped in try/catch, fetch() waits before recv tests/test_http_client.cpp: streaming test cases Tests: test_omnet_test: 110/110 PASS (no regressions) test_http_client streaming tests verified to work end-to-end Commit: 469f2b5 -
0.8.1
36d07de4 · ·OmniNet 0.8.1: HTTP Client Phases 2-5 Closes 4 deferred phases from the v0.8.0 plan. This is the release that unblocks CodeMax's HTTP client integration — Phase 3 (TLS) is the critical one since most production HTTPS APIs would otherwise be unusable. Phase 2 (async) — std::future<Result<..>> return type Phase 3 (TLS) — HTTPS via existing net::TLSSocket Phase 4 (redirects) — automatic 3xx following Phase 5 (timeouts) — connect/request_timeout + stop_token Plus: chunked transfer-encoding (Transfer-Encoding: chunked) is now parsed correctly in parseResponse(). Commit: 36d07de Tests: test_http_client 28/28 PASS, test_omnet_test 110/110 PASS Not yet shipped (deferred per plan): Phase 6: bearer/basic auth, cookie jar Phase 7: streaming bodies (req/resp) Phase 8: retry policy, happy-eyeballs connect
-
0.8.0
80c9a98d · ·OmniNet 0.8.0: HTTP Client (Phase 1 — minimal sync client) NEW MODULE: OmniNet::HTTP::Client Adds the first in-tree HTTP client to OmniNet (was server-only). Phased delivery (see CodeMax.md for the full Phase 2-8 roadmap); this release ships Phase 1 only: - OmniNet::HTTP::Client::get_instance() singleton - ClientRequest / ClientResponse / ClientConfig / ClientError types - send_blocking(req) / send_blocking(req, cfg) - HTTP/1.1 GET and POST over plain Socket - Case-insensitive header lookups - URL parsing: scheme://host[:port]/path[?query] - https:// returns UnsupportedProtocol (Phase 3) Deferred to future tags (0.8.1, 0.8.2, ...): - Phase 2: async std::future return type - Phase 3: TLS (reuse net::TLSSocket + TLSContext::createClient) - Phase 4: automatic 3xx redirect following - Phase 5: connect/request timeouts + std::stop_token cancellation - Phase 6: bearer/basic auth + cookie jar - Phase 7: chunked streaming bodies (req/resp) - Phase 8: retry policy + happy-eyeballs connect Commits: c6b5c02 Add OmniNet HTTP Client (Phase 1: minimal sync client) Tests: test_http_client: 20/20 PASS test_omnet_test: 110/110 PASS (no regressions) Full build clean, zero warnings.
-
0.7.7
2ad2a588 · ·OmniNet 0.7.7: Add typed queryInt/queryDouble accessors API improvement based on feedback from ApolloCore integration (prompt.txt 2026-06-27, Bug 4). New methods on QueryParams (HttpRequest.h/cpp): std::optional<int> queryInt(std::string_view key) const; int queryInt(std::string_view key, int defaultValue) const; std::optional<double> queryDouble(std::string_view key) const; double queryDouble(std::string_view key, double defaultValue) const; Before: auto v = req.query().get("limit"); if (v) int n = std::stoi(std::string(*v)); // awkward After: int n = req.query().queryInt("limit", 100); // with default auto m = req.query().queryDouble("ratio"); // optional Trailing non-digit chars are rejected (e.g., "10x" -> nullopt, not 10). Parse errors caught via std::stoi/std::stod try/catch and return nullopt. Other bugs from the same prompt.txt triage: #1 SQLiteDB::step - in ApolloCore repo, NOT OmniNet. #2 delete_() - not a bug (C++ keyword constraint). #3 setBody - already fixed (string_view overload exists). #5 setStatus - already fixed (int overload exists). #6 shutdown - not a bug (Server::stop() exists). #7-#8 - vague / out of scope. #9-#13 - llama.cpp / ApolloCore, NOT OmniNet. Commit: ba9b2cf Build verified clean. All 110 tests pass (no regressions). -
0.7.6
e17292ae · ·OmniNet 0.7.6: Fix codemax Bug 9 (wss:// ctor crash) Bug 9 (CRITICAL regression from 0.7.5): WebSocket::Connection(url) for wss:// never called m_socket->connect() before performClientHandshake(), causing a hard process abort with: *** bit out of range 0 - FD_SETSIZE on fd_set ***: terminated TLSContext::createSocket() returns a TLSSocket with m_fd == INVALID_SOCKET. TLSSocket::recvAll() reaches FD_SET(INVALID_SOCKET, ...) which writes out of bounds in glibc's __FD_SET macro. Fix: Add m_socket->connect(parsed->host, parsed->port) after the setALPNProtocols call in the wss:// branch of Connection::Connection(url). Mirrors what createConnectedSocket() does for the plain ws:// branch. Commit: df07b4f Affects: any user of WebSocket::Connection(url) with a wss:// URL. (Hard process abort — no exception to catch.) Does NOT affect: - WebSocket::Connection(unique_ptr<Socket>, ...) — server-side - WebSocket::Connection(url) with ws:// (plain text) Upgrade: MANDATORY if you adopted wss:// in 0.7.5. The codemax workaround (reject wss:// upfront) is no longer needed. Otherwise optional. Build verified clean. All existing tests pass (no regressions). -
0.7.5
f68e3a18 · ·OmniNet 0.7.5: 2 codemax WebSocket client fixes Two bugs in WebSocket::Connection client API fixed: Bug 8 (HIGH): Connection::receive() loops forever - Previously read exactly 2 bytes per recv() and passed them to FrameCodec::decode(). For any payload > 0 bytes, decode() couldn't satisfy its need for the full frame header + payload length + payload, so it returned nullopt, the loop continued, and the next recv() ate the start of the payload as if it were a header - hanging forever on every multi-byte frame. - Fix: mirror the server-side readLoop() pattern. Buffer bytes into a vector, keep calling FrameCodec::decode() until we have a complete frame, return it. - Commit: cacca33 Bug 7 (MED): Connection::Connection(url) ignores wss:// - Handshake::parseUrl() correctly set parsed->secure = true for wss:// URLs, but the Connection ctor ignored it and always used createConnectedSocket() which returns a plain Socket. The client sent a plaintext upgrade, the server returned 426 Upgrade Required, and the handshake failed with an opaque error. - Fix: branch on parsed->secure. For ws://, use createConnectedSocket() (existing). For wss://, use TLSContext::createClient()->createSocket() with SNI from the host and ALPN advertising {'http/1.1'}. - Commit: 8cdf9e3 Affects: any user of WebSocket::Connection(url) client API (both ws:// and wss://). Particularly important for codemax's websocket_connect tool which now works end-to-end against wss://echo.websocket.events and similar. Does NOT affect: server-side WebSocket::Connection usage (already worked via different code path). Build verified clean. All existing tests pass (no regressions). -
0.7.4
6f2ee92f · ·OmniNet 0.7.4: CRITICAL — Fix TLSContext::createSocket() double-free This is a hotfix release. v0.7.2 and v0.7.3 had a regression that caused 'free(): double free' abort on every HTTPS request when using the new TLSContext::createClient()->createSocket() factory pattern. Root cause: Both ~TLSSocket() (via cleanupContext()) AND ~TLSContext() called SSL_CTX_free() on the same SSL_CTX pointer. When the socket was created via createSocket(), the socket's m_ctx aliased the context's m_ctx (no copy, just a pointer). When both destructors ran, SSL_CTX_free was called twice. Fix: Track ownership via the m_context shared_ptr member. In cleanupContext(), only call SSL_CTX_free(m_ctx) when m_context is null (the socket owns its own context). When m_context is non-null, the shared TLSContext owns the SSL_CTX and is the sole owner responsible for freeing it. The socket just drops its alias (sets m_ctx = nullptr). Commit: c994cf2 Affects: any user of TLSContext::createClient()->createSocket() or TLSContext::createServer()->createSocket() Does NOT affect: TLSSocket constructed directly (default ctor, fd ctor, or std::unique_ptr<Socket> ctor) — those still own their SSL_CTX and free it in ~TLSSocket. Upgrade: MANDATORY if you use TLSContext::createSocket() in 0.7.2/0.7.3. Otherwise optional (0.7.2/0.7.3 is fine for the TLSSocket default-constructor path). Build verified clean. All existing tests pass (no regressions). -
0.7.3
1033e9f8 · ·OmniNet 0.7.3: Documentation updates for v0.7.1 + v0.7.2 No code changes. Docs-only release covering the 11 bug fixes shipped in 0.7.1 and 0.7.2. - docs/migration/v0.7.0-to-v0.7.2.md (NEW) Full migration guide covering both intermediate releases. Compatibility matrix, recommended actions with before/after code, security defaults, performance notes. - docs/api/http-server.md Updated CORS Setup with the new allowlist behavior table. Updated CORS Headers with per-request Origin logic. Added new TLS Client Connections section covering TLSContext::createClient/createServer/createSocket, security defaults, sharing contexts, ALPN usage. - docs/api/index.md Added What's New section linking to migration guide. Summarizes v0.7.2 TLS fixes, v0.7.1 bug fixes, v0.7.0 WebSocket fix. - docs/api/websocket.md Added note about registerProtocolSwitch() atomic registration (the v0.7.0 fix for TOCTOU race and single-shot erase). README.md untouched — it has no specific class/version references, and detail belongs in the API docs. Build verified clean (no code changes anyway). -
0.7.2
68bda96a · ·OmniNet 0.7.2: 5 codemax TLS bug fixes Commits since 0.7.1: 45cae5b Fix Bug 3: TLSSocket::readLine() overrides base Previously, calling readLine() on a TLSSocket used the inherited Socket::readLine() which calls raw ::recv() on the underlying fd, bypassing SSL_read. The result was raw TLS ciphertext (the record header bytes) which looked like 'malformed status line' to text-line parsers. Override readLine() to use the overridden recv() (which goes through SSL_read), one byte at a time. fc97be9 Fix Bug 4: load system CA + SSL_VERIFY_PEER by default Previously, initContext() created an SSL_CTX but didn't load any CA certs and didn't set a verify mode. OpenSSL's default is SSL_VERIFY_NONE, and setVerifyMode(PEER) on its own doesn't load the CA store. So setVerifyMode(PEER) + connect() would silently accept forged certificates. Fix: in initContext(), for client contexts, call SSL_CTX_set_default_verify_paths() and SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER, nullptr). Callers can still override via setVerifyMode(NONE). 913e44b Fix Bug 1 + 5: implement TLSContext::createClient/createSocket Previously, TLSContext::createClient() and createSocket() were declared but never defined - link failed with 'undefined reference'. createServer() was also unimplemented. Made TLSContext inherit std::enable_shared_from_this so createSocket() can use shared_from_this(). Implemented createServer(), createClient(), createSocket(), and the private ctor + dtor. Added TLSSocket(shared_ptr<TLSContext>) constructor and setContext() helper for adopting a shared context. d508494 Fix Bug 2: setALPNProtocols() actually sets ALPN Previously, setALPNProtocols() was a no-op stub. Without ALPN, modern HTTPS servers (Cloudflare, GitHub, Google) default to HTTP/2 which has a binary wire format incompatible with text-line HTTP/1.1 parsers - resulting in garbage status lines like 'PRI * HTTP/2.0'. Fix: build the ALPN wire format (RFC 7301) and call SSL_CTX_set_alpn_protos() on m_ctx. getALPNProtocol() was already implemented correctly. Plus: CodeMax.md updates tracking the work. Tests: test_omnet_test 110/110 PASS, test_sync_http_server 18/18 PASS. Full build clean, zero warnings. All 5 codemax integration bugs fixed. -
0.7.1
9ef3121b · ·OmniNet 0.7.1: 6 prompt.txt (2026-06-19) bug fixes Commits since 0.7.0: 42aa12b Fix BUG-1: IntrusionDetector self-deadlock Root cause: checkAndBlock() held m_mutex and called isBlocked() which also tried to lock — std::mutex is not recursive. Fix: split isBlocked() into isBlocked() (locks) and isBlockedUnlocked() (caller holds lock). e49f293 Fix BUG-2: CORS per-origin allowlist Was: config string emitted verbatim as the Access-Control-Allow-Origin header (CSV — rejected by all browsers). Now: parse CSV into std::unordered_set at enableCORS() time; per-request lookup of Origin header, echo back with Vary: Origin and Access-Control-Allow-Credentials: true. "*" is a special case for allow-all. BUG-3 was already fixed in v0.6.0 — no commit needed. d23c8af Fix BUG-4: remove dead config sections omninet-init was writing security.*, dashboard.*, and intrusion.* sections that the server never reads. Removed the three dead sections from the generated config. 34bf1c8 Fix BUG-5: centralize IntrusionDetector schema Extracted CREATE TABLE / CREATE INDEX statements from the constructor into a public static method schemaSQL(). The constructor calls it; behavior unchanged. Schema is now in one place for migrations / introspection. 1efc02b Fix BUG-6: remove dead defaultPatterns() defaultPatterns() and SuspiciousPattern were declared but never called. Actual rules live in IntrusionRules::allDefaultRules(). Dead code removed. Plus: CodeMax.md updates (6764a23, 9ef3121) tracking the work. Tests: test_omnet_test 110/110 PASS, test_sync_http_server 18/18 PASS. Full build clean, zero warnings. -
0.7.0
fe0aedc3 · ·OmniNet 0.7.0: Hive-Agent Features + WebSocket Upgrade Fix + Version Macros All 6 features from the hive-agent feature request (prompt.txt) are now complete, plus the WebSocket HTTP→WS upgrade handoff fix from the 2026-06-14 update, plus a version-macros fix so the CLI tools correctly report v0.7.0 instead of the v0.1.0 fallback. - Phase 11a: Server::boundPort() — actual bound port via getsockname() - Phase 11b: WebSocket::Server::broadcast() / fan-out API (addClient, removeClient, sendTo, clients, connectionCount) - Phase 11c: Server::onReady(uint16_t boundPort) lifecycle callback - Phase 11d: Request::authHeader() / bearerToken() / traceId() / requestId() - Phase 11e: Router typed body parsing (JsonHandler overloads for get/post/put/patch/delete_/head/options) - Bonus (74d9418): full HTTP→WS upgrade handoff via PostUpgradeCallback mechanism, so the WebSocket broadcast API is now reachable from real client connections. - Root CMakeLists.txt now uses ${DETECTED_MAJOR} (set by the git-tag parser) instead of ${PROJECT_VERSION_MAJOR} (set by project() AFTER our compile_definitions call, so it overrode our values). - tools/tools_common/CMakeLists.txt had two duplicate compile_definitions blocks that were never actually removed despite a v0.6.0 comment claiming they were. The v0.6.0 fix comment was also wrong: PUBLIC compile_definitions on OmniNet do NOT transitively propagate through static-library dependents (tools_common), so tools were always seeing the fallback values from version.h (0.1.0) instead of the real version. - Removed a duplicate version-print line in root CMakeLists.txt. - Response::build() suppresses Content-Length for 101/204/304 (RFC 7230 §3.3.2, RFC 6455 §1.3) - Connection server-side ctor sets m_open = true (was default false, broke addClient) - Connection::close() checks for null socket (fixes mock segfault) - Self-pipe trick for instant accept-loop shutdown (replaces 100ms poll) - Connection timeouts (SO_RCVTIMEO) now actually applied to socket - Content-Length auto-set in Response::build() (was missing in v0.6.0) - test_websocket_echo (new, 74d9418): 2/2 PASS - test_websocket_broadcast: 10/10 PASS - test_sync_http_server: 18/18 PASS (incl. 9 new boundPort/onReady tests) - All other tests: PASS - Full build: clean, zero warnings, all 40+ targets compile - All 10 CLI tools report v0.7.0