# &adminguide;

## Overview

The peerstate module provides peer state tracking for the Kamailio SIP proxy. It monitors both dialog events (call states) and registration events (usrloc) to maintain an accurate view of each peer's current status.

For example, a common need in call center applications is to track agent availability in real-time. In order to monitor agent states, it is necessary for the proxy to be aware of both call activity and registration status. This is just one common application; there are many others such as presence services, load balancing, and concurrent call limiting.

The module exports RPC commands for monitoring and management, provides an event route mechanism for custom logic execution, and offers a callback API for other Kamailio modules.

## How it works

The peerstate module registers callbacks with the dialog and usrloc modules. When dialog state changes (EARLY, CONFIRMED, TERMINATED) or registration events (REGISTER/UNREGISTER) occur, the module updates its internal cache and determines if a peer's state has changed.

Peer state is maintained in a shared memory hash table. Each peer entry contains current state, active call count, registration flag, and timestamp.

State transitions:

- EARLY events increment call count and set peer to RINGING (or keep INUSE if already in call)

- CONFIRMED events set peer to INUSE

- TERMINATED events decrement call count; peer returns to NOT_INUSE (if registered) or UNAVAILABLE (if not registered) when call count reaches zero

- REGISTER events set registration flag and may transition from UNAVAILABLE to NOT_INUSE

- UNREGISTER events clear registration flag and may transition from NOT_INUSE to UNAVAILABLE (if no active calls)

When a peer's state changes, the module triggers notifications via event routes and callback functions.

## Peer states

Peer states tracked by the module:

- 0 : NOT_INUSE - Peer is registered and idle (no active calls)

- 1 : INUSE - Peer is in an active call (dialog confirmed)

- 2 : RINGING - Peer has incoming or outgoing call ringing (early dialog)

- 3 : UNAVAILABLE - Peer is not registered

- 4 : NA - Not applicable or unknown state

State transitions are designed to accurately reflect the peer's availability:

- A peer transitions to RINGING when receiving or making a call

- A peer transitions to INUSE when the call is answered

- A peer returns to NOT_INUSE when all calls end and the peer is still registered

- A peer transitions to UNAVAILABLE when unregistering with no active calls

- Active calls are preserved during registration changes

## Dependencies

### &kamailio; Modules

The following modules must be loaded before this module:

- Dialog - Dialog tracking module

- Usrloc - User location module

### External Libraries or Applications

The following libraries or applications must be installed before running &kamailio; with this module loaded:

- None.

## Parameters

### `cache_hash_size` (integer)

The size of the hash table internally used to keep the peer state information. A larger table is much faster but consumes more memory. The hash size must be a power of two.

Default value is 4096.

#### Set `cache_hash_size` parameter

    ...
    modparam("peerstate", "cache_hash_size", 8192)
    ...

### `cache_expire` (integer)

The time in seconds after which inactive peer entries are removed from the cache. Set to 0 to disable automatic expiration. This helps conserve memory by removing stale peer information. Minimum allowed value is 60 seconds (when enabled).

Default value is 3600 (1 hour).

#### Set `cache_expire` parameter

    ...
    modparam("peerstate", "cache_expire", 7200)
    ...

### `cache_cleanup_interval` (integer)

The interval in seconds between automatic cache cleanup runs. Must be less than or equal to cache_expire. Set to 0 to disable automatic cleanup. During cleanup, expired entries are removed from the cache. Minimum allowed value is 10 seconds (when enabled).

Default value is 300 (5 minutes).

#### Set `cache_cleanup_interval` parameter

    ...
    modparam("peerstate", "cache_cleanup_interval", 600)
    ...

### `use_avps` (integer)

Enable or disable the use of AVPs for peer identification instead of extracting peer information from SIP headers. When enabled, the module will use the AVPs specified by caller_avp, callee_avp, and reg_avp parameters to identify peers.

If set to 0, the module extracts peer information from From/To headers. If set to 1, AVPs must be set by the routing script.

Default value is 0 (disabled).

#### Set `use_avps` parameter

    ...
    modparam("peerstate", "use_avps", 1)
    ...

### `caller_avp` (string)

The specification of an AVP that contains the caller's peer identifier. Only used when use_avps is set to 1. The AVP should contain the peer identifier in the format "peer@domain".

Default value is NULL.

#### Set `caller_avp` parameter

    ...
    modparam("peerstate", "caller_avp", "$avp(caller_peer)")
    ...

### `callee_avp` (string)

The specification of an AVP that contains the callee's peer identifier. Only used when use_avps is set to 1. The AVP should contain the peer identifier in the format "peer@domain".

Default value is NULL.

#### Set `callee_avp` parameter

    ...
    modparam("peerstate", "callee_avp", "$avp(callee_peer)")
    ...

### `reg_avp` (string)

The specification of an AVP that contains the registered peer identifier for usrloc events. Only used when use_avps is set to 1.

Default value is NULL.

#### Set `reg_avp` parameter

    ...
    modparam("peerstate", "reg_avp", "$avp(reg_peer)")
    ...

### `enable_notify_on_trying` (integer)

Enable state change notifications for dialog TRYING state. By default, only EARLY, CONFIRMED, and TERMINATED states trigger notifications. When enabled, TRYING state will also trigger notifications.

Default value is 0 (disabled).

#### Set `enable_notify_on_trying` parameter

    ...
    modparam("peerstate", "enable_notify_on_trying", 1)
    ...

### `disable_caller_notify_flag` (integer)

Message flag to disable caller state change notifications for specific calls. When this flag is set on a message, state changes for the caller will not trigger notifications. Set to -1 to disable this feature.

Default value is -1 (feature disabled).

#### Set `disable_caller_notify_flag` parameter

    ...
    modparam("peerstate", "disable_caller_notify_flag", 10)
    ...
    # In routing script:
    if ($rU == "1234567890") {
        setflag(10);  # Don't notify about emergency call callers
    }
    ...

### `disable_callee_notify_flag` (integer)

Message flag to disable callee state change notifications for specific calls. When this flag is set on a message, state changes for the callee will not trigger notifications. Set to -1 to disable this feature.

Default value is -1 (feature disabled).

#### Set `disable_callee_notify_flag` parameter

    ...
    modparam("peerstate", "disable_callee_notify_flag", 11)
    ...

### `disable_reg_notify` (integer)

Globally disable registration event processing. When set to 1, the module will not register callbacks with the usrloc module and will not process registration events.

Default value is 0 (process registration events).

#### Set `disable_reg_notify` parameter

    ...
    modparam("peerstate", "disable_reg_notify", 1)
    ...

### `disable_dlg_notify` (integer)

Globally disable dialog event processing. When set to 1, the module will not register callbacks with the dialog module and will not process dialog events.

Default value is 0 (process dialog events).

#### Set `disable_dlg_notify` parameter

    ...
    modparam("peerstate", "disable_dlg_notify", 1)
    ...

## RPC Commands

### `peerstate.get_peer`

Get detailed state information for a specific peer. Returns the peer's current state, active call count, and registration status.

Name: peerstate.get_peer

Parameters:

- peer - peer identifier in the format "peer@domain"

RPC Command Format:

    ...
    kamctl rpc peerstate.get_peer 1000@192.168.1.100
    ...

The command returns a structure containing:

- peer - peer identifier

- state - current state (NOT_INUSE, INUSE, RINGING, UNAVAILABLE)

- call_count - number of active calls

- registered - registration status ("yes" or "no")

### `peerstate.stats`

Get global cache statistics including total number of peers, number of peers in active calls, and number of registered peers.

Name: peerstate.stats

Parameters: none

RPC Command Format:

    ...
    kamctl rpc peerstate.stats
    ...

The command returns a structure containing:

- total_peers - total number of peers in cache

- incall_peers - number of peers in INUSE or RINGING state

- registered_peers - number of registered peers

### `peerstate.list`

List all peers in a specific state. This command is useful for monitoring which peers are currently in a particular state.

Name: peerstate.list

Parameters:

- state - state filter (NOT_INUSE, INUSE, RINGING, or UNAVAILABLE)

RPC Command Format:

    ...
    kamctl rpc peerstate.list INUSE
    ...

The command returns a structure containing:

- count - number of peers in the specified state

- state - the state filter used

- Peer - array of peer objects with name, state, call_count, and registered status

### `peerstate.dump`

Dump all peers from the cache regardless of state. This command provides a complete view of all tracked peers.

Name: peerstate.dump

Parameters: none

RPC Command Format:

    ...
    kamctl rpc peerstate.dump
    ...

The command returns a structure containing:

- count - total number of peers

- Peer - array of peer objects with name, state, call_count, and registered status

## Event Routes

### `event_route[peerstate:state_changed]`

Executed when a peer's state changes. Provides access to state change information through AVP pseudo-variables.

Available pseudo-variables:

- $avp(ps_peer) - Peer identifier

- $avp(ps_state) - Current state (NOT_INUSE, INUSE, RINGING, UNAVAILABLE)

- $avp(ps_prev_state) - Previous state

- $avp(ps_uniq_id) - Call-ID or RUID

#### `event_route[peerstate:state_changed]` usage

    ...
    event_route[peerstate:state_changed] {
        xlog("L_INFO", "Peer $avp(ps_peer): $avp(ps_prev_state) -> $avp(ps_state)");

        # HTTP notification
        if ($avp(ps_state) == "INUSE") {
            http_async_query("http://api.local/state", "peer=$avp(ps_peer)&state=busy", "HTTP_REPLY");
        }
    }
    ...