# Kamailio and OpenSIPS SIP proxies

Canonical: https://warmtransfer.net/knowledge/kamailio-sip-proxy

Last verified: 2026-09-24

RFC 3261 defines two proxy behaviours, stateless and transaction-stateful[^41][^40]. RFC 3261 defines a stateless proxy as one that does not maintain transaction state machines while forwarding requests downstream and responses upstream, whereas a stateful proxy maintains client and server transaction state machines during request processing[^41][^40].

## Transaction Processing and Stateless Handling

In Kamailio, stateful transaction processing is handled by the `tm` module, which creates transaction state, absorbs upstream retransmissions, generates downstream retransmissions, and matches replies to requests[^55]. The `t_relay()` function creates a transaction if one does not already exist and relays the request statefully[^57]. When Kamailio acts as a UAS, `t_newtran()` creates a transaction without relaying[^56]. For failure handling, `t_on_failure()` specifies a `failure_route` block that executes after a transaction completes negatively but before a final response is forwarded upstream, facilitating serial failover logic[^52]. The `tm` module configures `fr_timer` with a default of 30000 ms and `fr_inv_timer` with a default of 120000 ms[^54][^53].

Stateless replies in Kamailio are provided by the `sl` module[^51]. The `sl_send_reply()` function operates independently of `tm` and does not retransmit replies to INVITE requests[^49]. To handle ACKs, the `sl` module inserts a signature into the To-tag of local stateless INVITE replies, filtering matching ACKs until a timeout allows subsequent ACKs through[^48]. The adaptive function `send_reply()` selects stateful transmission if a `tm` transaction exists and statelessly sends the reply otherwise[^50].

## Registration and User Location

The Kamailio `registrar` module handles REGISTER requests and depends on both `usrloc` and `sl`[^32]. Its `save()` function updates location records in `usrloc` and responds with 200 OK containing current contacts, with flag 0x04 limiting the address of record (AOR) to a single contact[^39]. Contacts are queried using `lookup()`, which overwrites the request URI with the contact carrying the highest q value[^36]. The `lookup()` function returns 1 when contacts exist, -1 when no contacts match, -2 for unsupported methods, and -3 on internal errors[^35].

Default parameter values for the `registrar` module include `default_expires` at 3600 seconds, `min_expires` at 60 seconds, and `max_expires` at 0, which removes the upper limit[^33]. The `max_contacts` parameter defaults to 0, imposing no cap on contacts per AOR[^37]. RFC 3327 Path support is configured via `path_mode` in off, lazy, or strict settings, with strict mode rejecting registrations missing client Path indicators using a 420 Bad Extension reply[^38]. GRUU (RFC 5627) is supported using `+sip.instance` values to construct public GRUUs, and SIP Outbound (RFC 5626) is governed by an outbound mode parameter taking values from 0 to 2[^34].

Location storage persistence is configured in the `usrloc` module via `db_mode`[^58]:
- Mode 0: Memory only (registrations do not persist across restarts)[^58][^59].
- Mode 1: Write-through[^58].
- Mode 2: Write-back on a timer[^58].
- Mode 3: Database-only without a memory cache[^58].
- Mode 4: Loaded into memory from the database at startup without subsequent database writes[^58].

The timer interval for contact expiration and database synchronization (`timer_interval`) defaults to 60 seconds[^60].

## Dispatching and Load Balancing

Kamailio provides algorithms 0 through 14 and 64 within its `dispatcher` module, including Call-ID hash (0), round-robin (4), priority-ordered serial forking (8), weight-based routing (9), call load distribution (10), relative weight with congestion control (11), parallel forking (12), latency optimization (13), and round-robin with overload control (64)[^3]. Destination selection is performed with `ds_select_dst()`, which writes the selection to the destination URI without modifying the request URI, or `ds_select_domain()`, which overwrites the host and port in the request URI[^7]. Probing of inactive gateways is governed by `ds_ping_interval`, where setting 0 disables pings, and `ds_probing_mode`, where mode 1 probes continuously and mode 0 probes only gateways flagged for probing[^5][^6]. Setting flag 2 stores residual destinations so `ds_next_dst()` can step through targets on failure[^4].

The OpenSIPS dispatcher module provides algorithms 0 through 10, including Call-ID hash (0), From URI hash (1), To URI hash (2), request URI hash (3), weighted round-robin (4), authorization username hash (5), random (6), custom PV hash (7), first entry in the set (8), load-based routing via `pvar_algo_pattern` (9), and ordering via an `algo_route` callback (10)[^20]. WarmTransfer's reading of the sources is that dispatcher algorithm numbering cannot be ported directly between Kamailio and OpenSIPS, as algorithm 8 indicates priority serial forking in Kamailio but the first set entry in OpenSIPS, and algorithm 10 indicates call load distribution in Kamailio but an `algo_route` callback in OpenSIPS[^1].

In OpenSIPS, `ds_select_dst()` sets the destination URI (`$du`) and supports partition names, failover flags, and maximum result limits, while `ds_next_dst()` advances through stored destinations[^24][^21]. Destination sets can be split into partitions with independent database URLs, tables, AVPs, blacklists, and pinging configurations[^22]. Pinging failed gateways requires the `tm` module and uses `ds_ping_interval`, defaulting to 0[^23]. OpenSIPS distinguishes between `dispatcher` (probabilistic routing without load tracking) and `load_balancer` (load-directed routing)[^28]. The `load_balancer` module relies on the `dialog` module to count concurrent calls and selects destinations by available capacity rather than lowest total call count[^26][^25]. The `lb_start()` function returns 1 on success, -1 on internal error, -2 for exhausted capacity, -3 when no destination matches, and -4 on invalid resources[^27].

## Media Control and SBC Building Blocks

Sipwise rtpengine operates on GNU/Linux and supports in-kernel packet forwarding[^42]. It provides ICE handling (RFC 8445, including ICE-lite and trickle ICE), SRTP via SDES and DTLS-SRTP, network bridging across IPv4 and IPv6, codec transcoding, and recording[^46]. Its NG control protocol runs over plain UDP, plain TCP, HTTP, or WebSocket, employing cookie-prefixed messages and bencode or JSON encodings[^45][^43]. Supported NG commands include `ping`, `offer`, `answer`, `delete`, `query`, recording control, media blocking, DTMF injection, media play, forwarding controls, and statistics collection[^44].

Kamailio controls Sipwise rtpengine through the `rtpengine` module, an evolution of `rtpproxy` using the NG protocol[^12]. The Kamailio `rtpengine_sock` parameter accepts UDP (IPv4 or IPv6) and WebSocket or secure WebSocket control addresses, and it can define several sets of rtpengine instances with per-instance weights (default weight 1) for load balancing[^13]. Media sessions are altered using `rtpengine_offer()`, `rtpengine_answer()`, `rtpengine_delete()`, and `rtpengine_manage()`, supporting flags for interface bridging, transport profiles (such as RTP/SAVP and UDP/TLS/RTP/SAVPF), DTLS, ICE control, transcoding, and call recording[^10][^9]. In OpenSIPS, the `rtpengine` module explicitly works with Sipwise rtpengine and supports multiple weighted sets selectable by `rtpengine_use_set()` or `setid_avp`, defaulting to set 0[^30][^29].

Topology hiding in Kamailio can be implemented with `topoh` or `topos`[^14][^17]. The `topoh` module masks Via, Record-Route, Route, Contact, and optionally Call-ID headers using an encryption key configured by `mask_key`, allowing stateless header encoding without modifying routing scripts[^14][^15]. The `topos` module strips headers and stores them in a database, Redis, or `htable` to reconstruct in-dialog messages, though it ignores REGISTER and PUBLISH requests[^17][^16]. WarmTransfer's reading of the sources is that SBC-front roles are formed by scripting combinations of individual modules—such as `dispatcher` for distribution, `topoh` or `topos` for topology hiding, and `rtpengine` for media—rather than configuring a single dedicated SBC module[^47].

## Script Execution and Process Architecture

Kamailio routing logic is arranged into blocks including `request_route`, `route`, `branch_route`, `failure_route`, `reply_route`, `onreply_route`, `onsend_route`, and `event_route`[^8]. Its core parameter `children` sets the worker processes spawned per UDP listener and defaults to 8[^2]. 

OpenSIPS 4.0 changes connection handling by consolidating TCP and TLS processing into a single dedicated process with configurable worker threads, keeping TLS context local to that process[^31].

## Applicability

The deployment model is not covered by the sources below.

For Kamailio, evidence covers releases through v6.1.4 (released 2026-08-20) and maintenance release v6.0.8 (released 2026-09-16), with configuration and database schema compatibility preserved within the 6.1 branch[^19][^18]. For OpenSIPS, evidence reflects the master branch documentation and version 4.0[^20][^31].

## What remains uncertain

Whether Kamailio or OpenSIPS appears on certified SBC lists for Direct Routing is not covered by the sources below. Reference architectures for Kamailio or OpenSIPS as carrier edge or SBC front combining dispatcher, topoh, rtpengine, and pike are not covered by the sources below. RFC 3261 section 16 normative rules on when a proxy must be stateful regarding forking, CANCEL, and TCP are not covered by the sources below. Deployment of the rtpengine kernel forwarding module (xt_RTPENGINE or iptables) and fallback to userspace is not covered by the sources below. Kamailio flood and scanner protection via pike, secfilter, and htable ban patterns is not covered by the sources below. The behavior of the OpenSIPS topology_hiding module compared with Kamailio topoh and topos is not covered by the sources below. The Kamailio dialog module, dialog-based call limits, and accounting are not covered by the sources below. OpenSIPS registrar and usrloc behavior and cluster modes are not covered by the sources below.

## Sources

[^1]: Dispatcher algorithm numbers are not portable between Kamailio and OpenSIPS: for example, algorithm 8 is priority-ordered serial forking in Kamailio but first entry in the set in OpenSIPS, and algorithm 10 is call load distribution in Kamailio but an algo_route callback in OpenSIPS (inferred). Source: [DISPATCHER Module](https://www.kamailio.org/docs/modules/stable/modules/dispatcher.html), Section 4.1 ds_select_dst algorithm list, compared with the OpenSIPS dispatcher README ds_select_dst algorithm list. Checked 2026-09-24.
[^2]: The Kamailio core children parameter, the number of worker processes forked per UDP listening interface, defaults to 8. Source: [Core Cookbook - Kamailio Wiki Documentation](https://www.kamailio.org/wikidocs/cookbooks/6.1.x/core/), Core Parameters, children. Checked 2026-09-24.
[^3]: The Kamailio dispatcher module offers algorithms 0 to 14 plus 64, including 0 Call-ID hash, 4 round-robin, 8 priority-ordered serial forking, 9 weight-based, 10 call load distribution, 11 relative weight with congestion control, 12 parallel forking to all destinations, 13 latency-optimized and 64 round-robin with overload control. Source: [DISPATCHER Module](https://www.kamailio.org/docs/modules/stable/modules/dispatcher.html), Section 4.1 ds_select_dst, algorithm list. Checked 2026-09-24.
[^4]: In the Kamailio dispatcher, flag 2 of the flags parameter enables failover: the remaining destinations are stored so that ds_next_dst() can try the next one after a failure. Source: [DISPATCHER Module](https://www.kamailio.org/docs/modules/stable/modules/dispatcher.html), Section 3.10 flags. Checked 2026-09-24.
[^5]: Kamailio dispatcher ds_ping_interval sets how often a request is sent to gateways marked inactive, and setting it to 0 disables gateway pinging. Source: [DISPATCHER Module](https://www.kamailio.org/docs/modules/stable/modules/dispatcher.html), Section 3.21 ds_ping_interval. Checked 2026-09-24.
[^6]: Kamailio dispatcher ds_probing_mode 1 probes all gateways continuously and moves failed active gateways to the trying state, while mode 0 probes only gateways flagged for probing. Source: [DISPATCHER Module](https://www.kamailio.org/docs/modules/stable/modules/dispatcher.html), Section 3.26 ds_probing_mode. Checked 2026-09-24.
[^7]: In Kamailio, ds_select_dst() puts the chosen destination in the destination URI (outbound proxy), so it is not visible in the SIP request, while ds_select_domain() rewrites the host and port of the request URI. Source: [DISPATCHER Module](https://www.kamailio.org/docs/modules/stable/modules/dispatcher.html), Sections 4.1 ds_select_dst and 4.2 ds_select_domain. Checked 2026-09-24.
[^8]: Kamailio configuration scripts are organised into routing blocks including request_route, route, branch_route, failure_route, reply_route, onreply_route, onsend_route and event_route. Source: [Core Cookbook - Kamailio Wiki Documentation](https://www.kamailio.org/wikidocs/cookbooks/6.1.x/core/), Routing Blocks section. Checked 2026-09-24.
[^9]: Kamailio rtpengine flags include direction= or internal/external to bridge network interfaces, address-family= for IPv4 and IPv6 bridging, ICE=force/force-relay/remove, transport profiles such as RTP/SAVP and UDP/TLS/RTP/SAVPF, DTLS=, codec-transcode=, codec-strip= and record-call=on. Source: [RTPEngine Module](https://www.kamailio.org/docs/modules/6.1.x/modules/rtpengine.html), Functions, rtpengine_offer, flags list. Checked 2026-09-24.
[^10]: Kamailio rtpengine_offer() and rtpengine_answer() rewrite the offer and answer SDP so media flows through rtpengine, rtpengine_delete() ends the session, and rtpengine_manage() combines these operations in one call. Source: [RTPEngine Module](https://www.kamailio.org/docs/modules/6.1.x/modules/rtpengine.html), Functions, rtpengine_offer / rtpengine_answer / rtpengine_delete / rtpengine_manage. Checked 2026-09-24.
[^11]: The Kamailio rtpengine module keeps a hashtable mapping Call-ID to rtpengine node so that later operations on a call, such as delete, reach the same node as the offer, and it can replicate that table across a cluster with DMQ. Source: [RTPEngine Module](https://www.kamailio.org/docs/modules/6.1.x/modules/rtpengine.html), Overview / hashtable and DMQ parameters (hash_table_size, rtpengine_dmq). Checked 2026-09-24.
[^12]: The Kamailio rtpengine module is a modified version of the rtpproxy module that uses a new control protocol, and it is meant to drive Sipwise rtpengine. Source: [RTPEngine Module](https://www.kamailio.org/docs/modules/6.1.x/modules/rtpengine.html), Overview. Checked 2026-09-24.
[^13]: The Kamailio rtpengine_sock parameter accepts UDP (IPv4 or IPv6) and WebSocket or secure WebSocket control addresses, and it can define several sets of rtpengine instances with per-instance weights (default weight 1) for load balancing. Source: [RTPEngine Module](https://www.kamailio.org/docs/modules/6.1.x/modules/rtpengine.html), Parameters, rtpengine_sock. Checked 2026-09-24.
[^14]: The Kamailio topoh module hides topology by encoding the Via, Record-Route, Route and Contact headers, and optionally Call-ID, without any changes to the routing script. Source: [TOPOH Module](https://www.kamailio.org/docs/modules/6.1.x/modules/topoh.html), Overview. Checked 2026-09-24.
[^15]: Kamailio topoh encodes with the mask_key secret; servers sharing the same mask_key can restart without affecting ongoing calls, and mask_callid defaults to 0 (Call-ID not encoded). Source: [TOPOH Module](https://www.kamailio.org/docs/modules/6.1.x/modules/topoh.html), Overview; Parameters, mask_key and mask_callid. Checked 2026-09-24.
[^16]: Kamailio topos does not process REGISTER or PUBLISH requests. Source: [TOPOS Module](https://www.kamailio.org/docs/modules/6.1.x/modules/topos.html), Overview. Checked 2026-09-24.
[^17]: The Kamailio topos module strips SIP routing headers from messages and stores them so it can rebuild in-dialog messages, using a database by default or Redis or htable as alternatives, and it requires the rr module. Source: [TOPOS Module](https://www.kamailio.org/docs/modules/6.1.x/modules/topos.html), Overview; Dependencies; Parameters, storage. Checked 2026-09-24.
[^18]: The Kamailio v6.1.4 announcement says configuration file and database schema compatibility is preserved within the 6.1 branch, so updating from an earlier 6.1.x release needs no config or schema changes. Source: [Kamailio v6.1.4 Released](https://www.kamailio.org/w/2026/08/kamailio-v6-1-4-released/), Announcement body, compatibility paragraph. Checked 2026-09-24.
[^19]: As of 2026-09-24 the newest Kamailio stable release is v6.1.4, released 2026-08-20, and the 6.0 branch also received a maintenance release, v6.0.8, on 2026-09-16. Source: [Kamailio - The Open Source SIP Server (home page news list)](https://www.kamailio.org/w/), News list, 'Kamailio v6.1.4 Released' and 'Kamailio v6.0.8 Released'. Checked 2026-09-24.
[^20]: The OpenSIPS dispatcher module (master branch README) offers algorithms 0 to 10: 0 Call-ID hash, 1 From URI hash, 2 To URI hash, 3 request URI hash, 4 weighted round-robin, 5 authorization username hash, 6 random, 7 custom PV hash, 8 first entry in the set, 9 load-based via pvar_algo_pattern and 10 ordering by an algo_route callback. Source: [opensips/modules/dispatcher (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/dispatcher), Exported Functions, ds_select_dst, algorithm list. Checked 2026-09-24.
[^21]: OpenSIPS ds_next_dst() takes the next destination address from the AVPs and sets it as the destination URI, which gives serial failover when ds_select_dst() was called with the failover flag. Source: [opensips/modules/dispatcher (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/dispatcher), Exported Functions, ds_next_dst. Checked 2026-09-24.
[^22]: The OpenSIPS dispatcher groups destination sets into partitions, each with its own database URL, table, AVPs, blacklists, ping_from, ping_method and persistent_state settings. Source: [opensips/modules/dispatcher (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/dispatcher), Overview; Exported Parameters, partition. Checked 2026-09-24.
[^23]: OpenSIPS dispatcher ds_ping_interval sets how often failed gateways are pinged, works only when the TM module is loaded, and defaults to 0 (pinging disabled). Source: [opensips/modules/dispatcher (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/dispatcher), Exported Parameters, ds_ping_interval. Checked 2026-09-24.
[^24]: OpenSIPS ds_select_dst() picks a destination from a set and overwrites the destination URI ($du) of the request, and it accepts optional flags (failover, user-only, default, append), a partition name and a maximum result count. Source: [opensips/modules/dispatcher (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/dispatcher), Exported Functions, ds_select_dst. Checked 2026-09-24.
[^25]: OpenSIPS load_balancer uses a preconfigured maximum capacity per destination and resource, and it picks the destination with the most free capacity rather than the fewest absolute calls. Source: [opensips/modules/load_balancer (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/load_balancer), Section 1 Overview. Checked 2026-09-24.
[^26]: The OpenSIPS load_balancer module needs the dialog module to count ongoing calls per destination, needs tm only for probing, and needs a database module for its rules. Source: [opensips/modules/load_balancer (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/load_balancer), Section 2.1 Dependencies, OpenSIPS Modules. Checked 2026-09-24.
[^27]: OpenSIPS lb_start(grp, resources[, flags][, attrs]) returns 1 when a destination is set, -1 on internal error, -2 when no capacity is available, -3 when no destination matches and -4 for invalid resources. Source: [opensips/modules/load_balancer (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/load_balancer), Exported Functions, lb_start, return values. Checked 2026-09-24.
[^28]: OpenSIPS documentation contrasts its two balancers: dispatcher has no load information and spreads calls by probabilistic dispersion, while load_balancer routes mainly on load information. Source: [Load Balancing | OpenSIPS](https://docs.opensips.org/tutorials/loadbalancing/), Introduction / dispatcher versus load balancer comparison. Checked 2026-09-24.
[^29]: OpenSIPS can define several sets of rtpengine instances, balances by weight within a set, selects a set with rtpengine_use_set() or the setid_avp parameter, and keeps set 0 as the default for backward compatibility. Source: [opensips/modules/rtpengine (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/rtpengine), Section 3 Multiple RTP proxy usage. Checked 2026-09-24.
[^30]: The OpenSIPS rtpengine module README says that only RTP proxies supporting its control protocol work with it, specifically Sipwise rtpengine. Source: [opensips/modules/rtpengine (rendered README)](https://github.com/OpenSIPS/opensips/tree/master/modules/rtpengine), Section 1 Overview. Checked 2026-09-24.
[^31]: OpenSIPS 4.0 replaces the multi-process TCP/TLS model with a single dedicated TCP process that runs configurable threads, and it keeps the TLS (SSL) context local to that process. Source: [TCP/TLS rework in OpenSIPS 4.0](https://blog.opensips.org/2026/04/08/tcp-tls-rework-in-opensips-4-0/), Body, description of the new architecture. Checked 2026-09-24.
[^32]: The Kamailio registrar module processes REGISTER requests but keeps the location data in the usrloc module, and it requires both usrloc and sl. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Overview; Dependencies. Checked 2026-09-24.
[^33]: Kamailio registrar defaults are default_expires 3600 seconds and min_expires 60 seconds, and max_expires 0, which disables the upper bound. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Parameters, default_expires / min_expires / max_expires. Checked 2026-09-24.
[^34]: The Kamailio registrar supports GRUU (RFC 5627), with public GRUUs built from the +sip.instance value, and SIP Outbound (RFC 5626), controlled by an outbound mode parameter with values 0 to 2. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Parameters, gruu_enabled / outbound_mode. Checked 2026-09-24.
[^35]: Kamailio registrar lookup() returns 1 when contacts are found, -1 when none are found, -2 when the method is not supported and -3 on internal error. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Functions, lookup(domain [, uri]), return codes. Checked 2026-09-24.
[^36]: The Kamailio registrar lookup() function finds contacts in usrloc for the request URI's user and domain and overwrites the request URI with the contact that has the highest q value. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Functions, lookup(domain [, uri]). Checked 2026-09-24.
[^37]: The Kamailio registrar max_contacts parameter defaults to 0, which means no limit on contacts per AOR. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Parameters, max_contacts. Checked 2026-09-24.
[^38]: The Kamailio registrar supports the RFC 3327 Path header in off, lazy and strict modes; strict mode rejects registrations whose client does not indicate Path support with 420 Bad Extension. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Parameters, use_path / path_mode. Checked 2026-09-24.
[^39]: The Kamailio registrar save() function adds, removes or modifies location records from a REGISTER and on success replies 200 OK listing all current contacts; flag 0x04 restricts the AOR to a single contact. Source: [Registrar Module](https://www.kamailio.org/docs/modules/6.1.x/modules/registrar.html), Functions, save(domain, [flags [, uri]]). Checked 2026-09-24.
[^40]: RFC 3261 defines a stateful proxy as one that maintains the client and server transaction state machines while processing a request, also called a transaction stateful proxy. Source: [RFC 3261 — SIP: Session Initiation Protocol](https://www.rfc-editor.org/rfc/rfc3261.html), Section 6 Definitions, 'Stateful Proxy'. Checked 2026-09-24.
[^41]: RFC 3261 defines a stateless proxy as a logical entity that does not maintain the client or server transaction state machines and forwards every request downstream and every response upstream. Source: [RFC 3261 — SIP: Session Initiation Protocol](https://www.rfc-editor.org/rfc/rfc3261.html), Section 6 Definitions, 'Stateless Proxy'. Checked 2026-09-24.
[^42]: Sipwise rtpengine is a proxy for RTP and other UDP-based media that runs only on GNU/Linux and can forward packets in the kernel for low latency and low CPU use. Source: [rtpengine Overview](https://rtpengine.readthedocs.io/en/latest/overview.html), Overview; Features, in-kernel packet forwarding. Checked 2026-09-24.
[^43]: rtpengine uses bencode dictionaries natively in the NG protocol and also accepts JSON, which it converts internally. Source: [The NG Control Protocol](https://rtpengine.readthedocs.io/en/latest/ng_control_protocol.html), Message encoding section. Checked 2026-09-24.
[^44]: NG protocol commands include ping, offer, answer, delete, query, start/stop/pause recording, block/unblock media, play DTMF, play media, start/stop forwarding and statistics. Source: [The NG Control Protocol](https://rtpengine.readthedocs.io/en/latest/ng_control_protocol.html), Command list (per-command headings). Checked 2026-09-24.
[^45]: The rtpengine NG control protocol runs over plain UDP, plain TCP, HTTP or WebSocket, and each message is a unique cookie, a single space and then the payload, so replies can be matched and retransmissions detected. Source: [The NG Control Protocol](https://rtpengine.readthedocs.io/en/latest/ng_control_protocol.html), Introduction / message format. Checked 2026-09-24.
[^46]: Sipwise rtpengine supports ICE (RFC 8445, including trickle ICE and ICE-lite), SRTP via SDES and DTLS-SRTP, bridging between ICE-aware and ICE-unaware endpoints and between IPv4 and IPv6, codec transcoding and media recording. Source: [rtpengine Overview](https://rtpengine.readthedocs.io/en/latest/overview.html), Features list. Checked 2026-09-24.
[^47]: Kamailio's documented modules cover the main functions of an SBC-front or carrier-edge role: dispatcher for load balancing and failover, topoh or topos for topology hiding, and rtpengine for media anchoring and SRTP or ICE interworking. They are separate modules that the routing script composes; there is no single SBC feature (inferred). Source: [TOPOH Module](https://www.kamailio.org/docs/modules/6.1.x/modules/topoh.html), Overview (topology hiding), read together with the dispatcher and rtpengine module overviews. Checked 2026-09-24.
[^48]: The Kamailio sl module adds a signature to the to-tag of local stateless replies to INVITE so that the matching ACKs can be filtered instead of forwarded downstream, and after a timeout all ACKs are let through. Source: [SL Module](https://www.kamailio.org/docs/modules/6.1.x/modules/sl.html), Overview (ACK filtering paragraph). Checked 2026-09-24.
[^49]: Kamailio sl_send_reply() sends replies statelessly, independent of the tm module, and does not retransmit replies to INVITE. Source: [SL Module](https://www.kamailio.org/docs/modules/6.1.x/modules/sl.html), Functions, sl_send_reply(code, reason). Checked 2026-09-24.
[^50]: The Kamailio send_reply() function replies statefully if a tm transaction exists for the request and statelessly otherwise. Source: [SL Module](https://www.kamailio.org/docs/modules/6.1.x/modules/sl.html), Functions, send_reply(code, reason). Checked 2026-09-24.
[^51]: The Kamailio sl module lets the server act as a stateless UA server and generate replies to SIP requests without keeping state. Source: [SL Module](https://www.kamailio.org/docs/modules/6.1.x/modules/sl.html), Overview. Checked 2026-09-24.
[^52]: In Kamailio, t_on_failure() names a failure_route block that runs after a transaction completes with a negative result but before the final reply is sent upstream, which is how serial failover such as forward-on-no-reply is scripted. Source: [TM Module](https://www.kamailio.org/docs/modules/6.1.x/modules/tm.html), Functions, t_on_failure(failure_route). Checked 2026-09-24.
[^53]: The Kamailio tm parameter fr_inv_timer (INVITE final-response timeout after a provisional reply has been received) defaults to 120000 ms. Source: [TM Module](https://www.kamailio.org/docs/modules/6.1.x/modules/tm.html), Parameters, fr_inv_timer. Checked 2026-09-24.
[^54]: The Kamailio tm parameter fr_timer (final-response timeout for non-INVITE requests, and for INVITE before any provisional reply) defaults to 30000 ms. Source: [TM Module](https://www.kamailio.org/docs/modules/6.1.x/modules/tm.html), Parameters, fr_timer. Checked 2026-09-24.
[^55]: The Kamailio tm module provides stateful SIP transaction processing: it creates transaction state, absorbs upstream retransmissions, generates downstream retransmissions and correlates replies with requests. Source: [TM Module](https://www.kamailio.org/docs/modules/6.1.x/modules/tm.html), Overview. Checked 2026-09-24.
[^56]: In Kamailio, t_newtran() creates a new transaction without relaying and is typically used when Kamailio acts as a UAS. Source: [TM Module](https://www.kamailio.org/docs/modules/6.1.x/modules/tm.html), Functions, t_newtran(). Checked 2026-09-24.
[^57]: In Kamailio, t_relay() creates the SIP transaction if none exists yet and relays the request statefully to the current request URI or a given destination. Source: [TM Module](https://www.kamailio.org/docs/modules/6.1.x/modules/tm.html), Functions, t_relay([host, port]). Checked 2026-09-24.
[^58]: Kamailio usrloc db_mode has five values: 0 memory only, 1 write-through, 2 write-back on a timer, 3 DB-only with no memory cache, and 4 load from DB at startup, then run in memory without writing back. Source: [USRLOC Module](https://www.kamailio.org/docs/modules/6.1.x/modules/usrloc.html), Parameters, db_mode. Checked 2026-09-24.
[^59]: With Kamailio usrloc db_mode 0 (memory only), registrations do not survive a restart. Source: [USRLOC Module](https://www.kamailio.org/docs/modules/6.1.x/modules/usrloc.html), Parameters, db_mode (value 0). Checked 2026-09-24.
[^60]: Kamailio usrloc timer_interval, the period of the timer that expires contacts and syncs to the database, defaults to 60 seconds. Source: [USRLOC Module](https://www.kamailio.org/docs/modules/6.1.x/modules/usrloc.html), Parameters, timer_interval. Checked 2026-09-24.
