Repository navigation
development
For development or non-Docker deployments. Most users should prefer the Docker Compose deployment.
- Rust stable (pinned by
rust-toolchain.toml) - System packages:
build-essential,pkg-config,clang,libclang-dev - Libraries:
libasound2-dev,libusb-1.0-0-dev,libpjproject-dev(>= 2.14),uuid-dev - Hardware: One or more Quectel EC20 USB modems with active SIM cards (see supported-hardware.md for one-time module prep)
- SIP server account (Asterisk, FreePBX, MikoPBX, etc.)
Install build dependencies:
sudo apt install build-essential pkg-config clang libclang-dev \
libasound2-dev libusb-1.0-0-dev libpjproject-dev uuid-dev libssl-devcp config.toml.example config.toml # edit with your SIP/PBX details
export SIP_PASSWORD=yourpassword
make build
make test
make runUseful invocations:
gsm-sip-bridge --config config.toml # auto-detect all EC20 modules
gsm-sip-bridge --config config.toml --verbose # verbose SIP + AT logging
gsm-sip-bridge -s /dev/ttyUSB3 -a hw:2,0 # single-card overridemake test/make build normally exercise pjsua-safe in stub mode —
no real PJSIP calls are made, which is what makes the default test suite
fast and hardware-independent. pjsua-safe's own integration tests
(pjsua-safe/tests/*.rs) additionally run against a real, linked
PJSIP when built with --features pjsip-linked:
cargo test -p pjsua-safe --features pjsip-linkedTwo environment-specific gotchas apply here, both handled automatically where possible:
-
Wrong
libclangpicked up.bindgen(viaclang-sys) defaults to whateverllvm-configis first onPATH. If a dev machine has an unusual, very new LLVM toolchain installed alongside the distro one (seen in the wild: an unreleased Homebrew LLVM 23 build), that libclang has a real parsing regression — several PJSIP structs that aretypedef'd via a forward declaration before their full body appears later in the header (pjsua_media_config,pjsip_cred_info,pjsip_rx_data,pjsua_msg_data, ...) come out with no fields at all, which then failspjsua-safe's build with a wall of unrelated-lookingno field Xerrors.pjsua-sys/build.rsnow auto-detects and prefers a mainstream, distro-packagedlibclang(Debian/Ubuntu'slibclang-19/-20/-21) wheneverLIBCLANG_PATHisn't already set, and warns loudly (naming the libclang it picked, or the opaque structs it detected if bindgen still produced them) so this is never silently confusing again. SetLIBCLANG_PATHyourself to override the auto-detection. -
Locally built/installed PJSIP missing this project's
config_site.h. The Docker image always builds PJSIP withdocker/pjsip-config-site.h(enablesPJMEDIA_CODEC_L16_HAS_16KHZ_MONO, the VoWiFi bridge's wideband codec, andPJ_GETHOSTIP_DISABLE_LOCAL_RESOLUTION). Thelibpjproject-devapt package this doc's own Prerequisites section tells you to install does not set either — so--features pjsip-linkedtests that depend on those (e.g. anything asserting anL16/16000codec offer) fail locally even though the Docker build is fine.pjsua-sys/build.rsdetects this and warns at build time, naming the missing defines. To fix it for real, rebuild PJSIP from source with the project'sconfig_site.hin place — version pinned bydocker/Dockerfile'sPJSIP_VERSIONbuild arg (2.16as of this writing):wget https://github.com/pjsip/pjproject/archive/refs/tags/2.16.tar.gz tar xzf 2.16.tar.gz && cd pjproject-2.16 cp ../gsm-sip-bridge/docker/pjsip-config-site.h pjlib/include/pj/config_site.h ./configure --prefix=/usr/local CFLAGS="-fPIC" # shared libs, matching # the apt package's layout # — don't add Docker's # --disable-shared here make dep && make sudo make install sudo ldconfig
This is optional — it only affects the subset of
--features pjsip-linkedtests that care about the wideband codec or the hostname-lookup behavior; everything else (including this project's own[sip].public_addrtests) passes against the stock apt package.
Three crates — pjsua-sys (generated FFI), pjsua-safe (safe wrappers,
all unsafe confined here with // SAFETY: comments), and
gsm-sip-bridge (the binary, zero unsafe). See
architecture.md for the module map. Feature specs,
plans, and task breakdowns live under specs/.
| Target | Description |
|---|---|
make build |
Build all crates in release mode |
make test |
Run all workspace tests (via cargo nextest when installed, for its per-test timeout) |
make run |
Start the bridge |
make lint |
rustfmt check + clippy (--workspace --all-targets -D warnings) + cargo-deny + shellcheck + unsafe audit |
make coverage |
Generate lcov coverage report |
make docker-build |
Build the Docker image |
make docker-up |
Start the full Docker Compose stack |
make docker-down |
Stop the Docker Compose stack |
make docker-logs |
Tail logs from the bridge container |
make help |
Show all available targets |
Run, in order — all must pass:
cargo fmt --all # fix formatting in place
make lint # clippy --workspace --all-targets -D warnings, + deny/shellcheck/unsafe
make test # all tests must passTwo optional tools change what these actually check, so it is worth having
them installed locally rather than discovering the difference in CI:
cargo-deny (otherwise the dependency/licence policy is silently skipped) and
cargo-nextest (otherwise there is no per-test timeout, and a test that hangs
wedges the whole run).