devenv shenanigans
This commit is contained in:
parent
8dc75613c7
commit
586c3e3e3a
5 changed files with 289 additions and 0 deletions
2
.envrc
Normal file
2
.envrc
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
eval "$(devenv direnvrc)"
|
||||
use devenv
|
||||
81
PLAN-calls.md
Normal file
81
PLAN-calls.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Stabilize Existing VoIP Call Flow and Add Non-Fatal Diagnostics
|
||||
|
||||
## Summary
|
||||
|
||||
Tighten the existing Matrix call flow in the current VoIP stack, focusing on real correctness issues already present in src/voip/CallManager.cpp and src/voip/WebRTCSession.cpp, and
|
||||
add structured logging around non-fatal failures so future call bugs are diagnosable without crashing or silently retrying forever.
|
||||
|
||||
This plan targets:
|
||||
|
||||
- Core invite/answer/candidate/select-answer stability
|
||||
- Inbound renegotiation support for m.call.negotiate
|
||||
- Logging of non-critical exceptions and ignored/invalid call events
|
||||
- No user-visible feature expansion beyond making current calls more reliable
|
||||
|
||||
## Implementation Changes
|
||||
|
||||
- Fix the CallSelectAnswer rejection lookup bug in CallManager::handleEvent(const RoomEvent<CallSelectAnswer>&) by changing the std::find(begin, begin, ...) calls to search through
|
||||
end(). This is a concrete logic bug that currently prevents expected branch behavior.
|
||||
- Add strict call-id and state guards across inbound handlers in CallManager and log every early-return branch that currently drops events silently. Include at least:
|
||||
- mismatched call_id
|
||||
- wrong local webrtc::State
|
||||
- duplicate answers/select-answer/reject
|
||||
- self-echo cases
|
||||
- candidates received before a call is initialized
|
||||
- Implement WebRTCSession::acceptNegotiation(const std::string &) instead of the current unconditional false. Use the same parsing/validation style as acceptOffer:
|
||||
- require an active session, not DISCONNECTED
|
||||
- parse SDP as a remote offer
|
||||
- validate required audio media and optional VP8 video media
|
||||
- update remote video direction flags
|
||||
- call set-remote-description
|
||||
- create and send an answer through the existing answerCreated path
|
||||
- keep wire format unchanged; do not add local renegotiation initiation in this pass
|
||||
- Extend CallManager::handleEvent(const RoomEvent<CallNegotiate>&) so renegotiation only applies to the active call, logs dropped mismatches, and drains queued ICE candidates only
|
||||
after renegotiation is accepted.
|
||||
- Harden acceptICECandidates handling:
|
||||
- log when candidates are ignored because the session is not ready
|
||||
- keep buffering only in manager-side inbound invite/renegotiation waiting states
|
||||
- avoid silent no-ops when candidates arrive for the wrong call or after teardown
|
||||
- Improve failure handling around setup paths:
|
||||
- log TURN retrieval failures in retrieveTurnServer() with the request error and retry interval
|
||||
- log why createOffer, acceptOffer, acceptAnswer, and renegotiation fail, including current state and call id where available
|
||||
- log pipeline creation failures with the missing device/element context instead of only generic “Problem setting up call”
|
||||
- Add non-critical exception logging around call orchestration paths that touch cache/state but should not kill the process:
|
||||
- syncEvent dispatch
|
||||
- inbound call event handlers that query room info/members
|
||||
- outbound invite setup that reads room/member data
|
||||
- TURN response parsing/conversion
|
||||
Catch std::exception and log with nhlog at warn or error depending on whether the call can continue; rethrow nothing for these paths. Add a final catch (...) only where needed
|
||||
to prevent silent termination, with a clear “unknown exception” log line.
|
||||
- Keep user notifications mostly unchanged. Prefer logs for diagnostics and only surface UI notifications for existing fatal outcomes such as setup failure, ICE failure, reject,
|
||||
timeout, or answered elsewhere.
|
||||
|
||||
## Public Interfaces / Behavior
|
||||
|
||||
- No QML property or signal changes.
|
||||
- No Matrix event schema changes.
|
||||
- Existing CallAnswer, CallCandidates, CallNegotiate, and CallSelectAnswer messages remain the transport surface.
|
||||
- Behavioral change: inbound m.call.negotiate will now be handled instead of always failing.
|
||||
- Behavioral change: previously silent dropped call events and recoverable exceptions will now emit logs with call id, party id, and local state.
|
||||
|
||||
## Test Plan
|
||||
|
||||
- Add focused unit-style coverage where practical for pure call-manager logic, or otherwise add regression tests around isolated helper logic if the repo lacks VoIP integration
|
||||
tests.
|
||||
- Verify manually or with targeted harness coverage:
|
||||
- outbound call reaches OFFERSENT, receives answer, transitions to CONNECTED
|
||||
- inbound call invite buffers ICE before accept, then drains after accept
|
||||
- duplicate CallAnswer and CallSelectAnswer are ignored with logs, not state corruption
|
||||
- CallSelectAnswer rejection-party matching now works after the std::find fix
|
||||
- incoming CallNegotiate on the active call produces a local answer instead of immediate failure
|
||||
- CallNegotiate for a different call_id is ignored with a diagnostic log
|
||||
- TURN retrieval failure logs retry details without crashing
|
||||
- exceptions thrown from room/member lookup in call paths are logged and do not abort the process
|
||||
- Run a build check after the changes. If the environment still lacks cmake, document that verification gap and at minimum run the strongest available static inspection.
|
||||
|
||||
## Assumptions
|
||||
|
||||
- Use existing nhlog logging categories rather than raw printf; “prints” here means persistent diagnostic logging.
|
||||
- Keep the existing user-facing notification policy unless a failure is already fatal to the active call.
|
||||
- Renegotiation scope is inbound-only for now because the current codebase already receives m.call.negotiate but does not expose a local renegotiation initiator.
|
||||
- No attempt will be made in this pass to redesign the entire call state machine or add automatic media-session recovery after teardown.
|
||||
65
devenv.lock
Normal file
65
devenv.lock
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"nodes": {
|
||||
"devenv": {
|
||||
"locked": {
|
||||
"dir": "src/modules",
|
||||
"lastModified": 1773179136,
|
||||
"narHash": "sha256-aOxRGdpITEvasogdZXGqlSrr8pJQ+QGiRxpzmT3i/UQ=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "169c048513ca064c02a4233ace0ecbdd935d4f80",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"dir": "src/modules",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"inputs": {
|
||||
"nixpkgs-src": "nixpkgs-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1772749504,
|
||||
"narHash": "sha256-eqtQIz0alxkQPym+Zh/33gdDjkkch9o6eHnMPnXFXN0=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "08543693199362c1fddb8f52126030d0d374ba2e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "rolling",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1772173633,
|
||||
"narHash": "sha256-MOH58F4AIbCkh6qlQcwMycyk5SWvsqnS/TCfnqDlpj4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c0f3d81a7ddbc2b1332be0d8481a672b4f6004d6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
129
devenv.nix
Normal file
129
devenv.nix
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
{ pkgs, lib, config, inputs, ... }:
|
||||
|
||||
let
|
||||
qtPackages = with pkgs.qt6Packages; [
|
||||
qtbase
|
||||
qtdeclarative
|
||||
qtimageformats
|
||||
qtkeychain
|
||||
qtmultimedia
|
||||
qtsvg
|
||||
qttools
|
||||
qtwayland
|
||||
qt-jdenticon
|
||||
];
|
||||
|
||||
gstreamerPackages = [
|
||||
pkgs.gst_all_1.gstreamer
|
||||
pkgs.gst_all_1.gst-plugins-base
|
||||
(pkgs.gst_all_1.gst-plugins-good.override { qt6Support = true; })
|
||||
pkgs.gst_all_1.gst-plugins-bad
|
||||
];
|
||||
|
||||
cmakePackages = [
|
||||
pkgs.cmark
|
||||
pkgs.coeurl
|
||||
pkgs.curl
|
||||
pkgs.kdsingleapplication
|
||||
pkgs.libevent
|
||||
pkgs.libsecret
|
||||
pkgs.lmdb
|
||||
pkgs.lmdbxx
|
||||
pkgs.mtxclient
|
||||
pkgs.nlohmann_json
|
||||
pkgs.olm
|
||||
pkgs.re2
|
||||
pkgs.spdlog
|
||||
] ++ qtPackages ++ gstreamerPackages ++ [ pkgs.libnice ];
|
||||
|
||||
runtimePackages = [
|
||||
pkgs.pipewire
|
||||
];
|
||||
|
||||
qtPluginPath = lib.makeSearchPath "lib/qt-6/plugins" qtPackages;
|
||||
qmlImportPath = lib.makeSearchPath "lib/qt-6/qml" qtPackages;
|
||||
gstreamerPluginPath = lib.makeSearchPath "lib/gstreamer-1.0" gstreamerPackages;
|
||||
runtimeLibraryPath = lib.makeLibraryPath runtimePackages;
|
||||
cmakePrefixPath =
|
||||
lib.concatStringsSep ":" (
|
||||
(map (pkg: "${lib.getDev pkg}/lib/cmake") cmakePackages)
|
||||
++ (map (pkg: "${lib.getDev pkg}") cmakePackages)
|
||||
);
|
||||
in
|
||||
{
|
||||
packages = [
|
||||
pkgs.asciidoc
|
||||
pkgs.cmake
|
||||
pkgs.direnv
|
||||
pkgs.gcc
|
||||
pkgs.git
|
||||
pkgs.gnumake
|
||||
pkgs.gdb
|
||||
pkgs.ninja
|
||||
pkgs.pkg-config
|
||||
pkgs.pipewire
|
||||
pkgs.qt6Packages.wrapQtAppsHook
|
||||
] ++ cmakePackages;
|
||||
|
||||
env = {
|
||||
CMAKE_GENERATOR = "Ninja";
|
||||
CMAKE_PREFIX_PATH = cmakePrefixPath;
|
||||
GST_PLUGIN_SYSTEM_PATH_1_0 = gstreamerPluginPath;
|
||||
LD_LIBRARY_PATH = runtimeLibraryPath;
|
||||
NHEKO_BUILD_DIR = "build";
|
||||
QT_PLUGIN_PATH = qtPluginPath;
|
||||
QML2_IMPORT_PATH = qmlImportPath;
|
||||
};
|
||||
|
||||
scripts."configure-nheko".exec = ''
|
||||
cmake -S . -B "$NHEKO_BUILD_DIR" \
|
||||
-G "$CMAKE_GENERATOR" \
|
||||
-DCMAKE_BUILD_TYPE="''${CMAKE_BUILD_TYPE:-RelWithDebInfo}" \
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
'';
|
||||
|
||||
scripts."build-nheko".exec = ''
|
||||
if [ ! -f "$NHEKO_BUILD_DIR/CMakeCache.txt" ]; then
|
||||
configure-nheko
|
||||
fi
|
||||
|
||||
cmake --build "$NHEKO_BUILD_DIR" --parallel "''${NIX_BUILD_CORES:-$(nproc)}"
|
||||
'';
|
||||
|
||||
scripts."test-nheko".exec = ''
|
||||
build-nheko
|
||||
ctest --test-dir "$NHEKO_BUILD_DIR" --output-on-failure
|
||||
|
||||
binary="$(find "$NHEKO_BUILD_DIR" -maxdepth 4 -type f -name nheko -executable | head -n 1)"
|
||||
if [ -z "$binary" ]; then
|
||||
echo "Unable to locate the built nheko binary under $NHEKO_BUILD_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
QT_QPA_PLATFORM=offscreen "$binary" --help >/dev/null
|
||||
'';
|
||||
|
||||
scripts."run-nheko".exec = ''
|
||||
build-nheko
|
||||
|
||||
binary="$(find "$NHEKO_BUILD_DIR" -maxdepth 4 -type f -name nheko -executable | head -n 1)"
|
||||
if [ -z "$binary" ]; then
|
||||
echo "Unable to locate the built nheko binary under $NHEKO_BUILD_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec "$binary" "$@"
|
||||
'';
|
||||
|
||||
enterShell = ''
|
||||
echo "nheko devenv ready"
|
||||
echo " configure-nheko Configure the CMake build tree"
|
||||
echo " build-nheko Build the nheko binary"
|
||||
echo " test-nheko Run ctest and a headless --help smoke test"
|
||||
echo " run-nheko Launch the built client"
|
||||
'';
|
||||
|
||||
enterTest = ''
|
||||
test-nheko
|
||||
'';
|
||||
}
|
||||
12
devenv.yaml
Normal file
12
devenv.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
||||
inputs:
|
||||
nixpkgs:
|
||||
url: github:cachix/devenv-nixpkgs/rolling
|
||||
|
||||
nixpkgs:
|
||||
permittedInsecurePackages:
|
||||
- "olm-3.2.16"
|
||||
|
||||
# If you have more than one devenv you can merge them
|
||||
#imports:
|
||||
# - ./backend
|
||||
Loading…
Add table
Add a link
Reference in a new issue