Skip to main content
Build Routr from a clone of the repository, start its services on your machine with live reload, and run the tests.

Prerequisites

  • Node.js 22 (CI uses 22.x). nvm makes switching versions easy.
  • JDK 17, with JAVA_HOME set. EdgePort and Requester are Java services. CI pins 17 because the Java tests fail on JDK 21.
  • Docker with Compose, for the optional dependencies (PostgreSQL, Redis, RTPEngine).
  • OpenSSL, to create the development TLS keystore.
  • Optional: sngrep to watch SIP traffic and grpcurl to call the gRPC services.
If you’d rather not install anything, develop with Gitpod instead.

Build and start

1

Clone and build

Clone the repository, point JAVA_HOME at your JDK, and build everything. npm run make installs dependencies, builds the Node.js workspaces, and builds the Java services with Gradle:
2

Map the service hostnames

The development configs in config/ address services by name (dispatcher:51901, location:51902, apiserver:51907). Add those names to /etc/hosts from etc/hosts.txt:
The command uses sudo. Undo it later with npm run hostile:unload.
3

Create the TLS keystore

config/edgeport.yaml enables TLS and WSS and reads its keystore from /etc/routr/certs/signaling.p12 with the password changeme. Generate a self-signed keystore and copy it there:
4

Start the services

Start the Connect distribution in one process:
This runs two EdgePorts (config/edgeport.yaml on port 5060, config/edgeport.alt.yaml on port 6060), the Message Dispatcher, Location Service, Registry, Requester, the Connect processor, and the API Server with the YAML backend (simpledata, reading config/resources). Nodemon restarts the Node.js services when you edit their source. EdgePort and Requester are Java: rebuild them with npm run build:java and restart.
The log shows routr v2 // connect distribution followed by a starting routr service line for each Node.js service.
Register a softphone against sip.local on port 5060 with one of the Agents in config/resources/agents.yaml to try it.

Run a single service

Each component has its own script, so you can run only what you work on, each in its own terminal. For example, to work on the Location Service with an EdgePort:
See the scripts section of package.json for the full list.

Start the dependencies

PostgreSQL, Redis, and RTPEngine only matter when you use pgdata, the Redis cache, or RTPRelay. Start them, plus Adminer on port 8080, with Docker Compose:
This runs compose.dev.yaml with Postgres on 5432 (user and password postgres), Redis on 6379, and RTPEngine on 22222/udp. Before you start start:one or start:pgdata, apply the database migrations:
Stop the dependencies with npm run stop:deps.
RTPEngine needs DOCKER_HOST_ADDRESS set to an IP your SIP clients can reach. On macOS, Compose can’t use host networking, so the file publishes media ports 10000-10020/udp instead.

Run the tests

Run the same checks as CI before you open a pull request:
npm test runs against the built workspaces, so run npm run make (or npx lerna run build) after pulling. npm run lint also lints, but it applies --fix and rewrites files. To run the SIP Connect compliance scenarios (SEET) against containers built from your tree:

Pitfalls

  • Could not find a runtime environment: JAVA_HOME isn’t set in the shell that runs the script.
  • Connection errors to location or apiserver: the hostnames aren’t mapped. Run npm run hostile:load.
  • Build errors in @routr/ctl after npm install: use npm ci so the dependency tree matches package-lock.json.
  • Start fresh: npm run clean removes node_modules, dist, and Gradle outputs.

Build a processor

Plug your own processor into the local Dispatcher.

Contributing

Commit conventions and the pull request checklist.

Develop with Gitpod

The same setup in a browser workspace.

Architecture

How the services fit together.