SIP Transports Refactoring

This document describes the design for refactoring the SIP transports in the SIP SIMPLE SDK core.

Rationale

Currently the Engine has a single UDP transports and a TCP factory and a TLS factory. This has worked for a while, but it has certain problems / limitations:

  • TLS settings apply to the factory itself, so every transport generated by this factory will use the TLS settings provided. This means that currently the TLS transport uses the TLS settings of the default account. A single CA list is loaded, and a single cert.
  • If a transport fails and the factory is restarted, all accounts are (potentially) affected, since they'll need to re-REGISTER, re-SUBSCRIBE and so on.

Possible solutions

PJSIP currently is very tied to the concept of having a single transport manager. There is one global PJSIP User Agent, which holds a single PJSIP Endpoint, which in turn creates the one and only transport manager.

There are 2 possible solutions to this problem:

  • Create multiple transport managers, one per account more precisely.
  • Modify the transport manager to allow registering multiple factories for the same type.

After some exploration the first approach was taken as the ultimate solution to the problem.

Solution outline

The basic idea is to create multiple transport managers (one per account) and pass them to the PJSIP APIs so they would be used to send a given request. At the transport layer things are pretty "transport-manager-agnostic". Once a pjsip_tx_data object is created, it holds a reference to the transport manager.

Things that need to be changed:

  • Remove current transport manager from pjsip_endpoint
  • Modify pjsip_endpt_create_request to get a transport manager instance as a parameter (other similar pjsip_endpt_* functions need this too)
  • The pjsip_dialog structure needs to be extended to keep a reference to the associated transport manager
  • pjsip_dlg_create_uac/s need to be extended to get a transport manager as a parameter and attach it to the dialog structure

Core and middleware changes

Engine

  • The engine will be the responsible for creating TransportManager objects
  • Settings related to SIP transports and ports are moved away from the Engine to Account

TransportManager

  • Entity resposible for starting transport for UDP, TCP and TLS
  • Instances of this class are passed to underlying core components such as Invitation, Subscription, Request.
  • Notifications are posted when a transport is connected and when it's disconnected: SIPTransportManagerTransportDidConnect/Disconnect.
  • Notifications are posted when an incoming request is received: SIPTransportManagerGotIncomingRequest
  • Ports of different transports can be set and queried

Account

  • Accounts hold on to an instance of TransportManager and listen for notifications sent by it
  • If settings change (CFGSettingsObjectDidChange), the account will change the transport settings accordingly by calling methods / setting properties on the transport manager
  • New per-account settings: sip.transport_list, sip.udp_port, sip.tcp_port, sip.tls_port
  • New notifications: SIPAccountGotIncomingRequest