Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#50 closed enhancement (worksforme)

Explicit use of transports

Reported by: bennylp Owned by: bennylp
Priority: normal Milestone: release-0.5.10
Component: pjsip Version: 0.5.9
Keywords: transport Cc:
Backport to 1.x milestone: Backported:

Description

Background

The rules regarding transports are quite complicated with SIP, so because of this, it was decided during design that transports are managed automatically by the stack.

This has benefit that application doesn't need to care about transport complexities, such as transport resolution, establishing/tearing-down transports, associating transport with destination, etc. With this approach, application should only need to care about the URI, and the stack will manage the transport to be used for that URI automatically.

This approach works fine for typical applications. However, some unusual applications need more refined control on the transport, e.g. they want to be able to use specific transport to send outgoing messages.

More over, the current transport design also has a limitation that currently only one transport type can be used per application. If application creates (for example) more than one UDP transports, the second one simply will not be used to send outgoing requests, although it can receive incoming requests.

The reason why the second transport will not be selected is related to how transports are stored in the transport hash tables. Currently, transports are hashed by their transport-type and remote address. So everytime the stack needs to send SIP message to remote destination, it looks up the transport hash table using the transport-type and remote address as the hash key. Because of this, there can only be one transport registered per one transport type and one remote address (note that connection-less transport such as UDP will register 0.0.0.0:0 as its remote address)

Proposed Changes

The proposed changes to the transport framework should support the following requirements:

  • allow more than one transport per transport type to be registered and used.
  • allow application to bind a request, transaction, and possibly dialog to specific listener.
  • also fix ticket #42 regarding shutting down transport.

A potential solution may look like this:

  • change the transport hash key from {type, remote-address} to {type, local-address, remote-address}.
  • each transport/listener will register itself twice to the hash table. First with its local address set to zero, and second with its actual local address. The first entry is used to match transport when application doesn't request for explicit binding, and the second when it does.
  • note that with above rule, it is possible that more than one transports may occupy a single hash table entry (for example, two UDP transports will occupy the same entry because both have the same transport type, local address (zero), and remote address (zero)). Because of this, hash entry may need to be made as a list.
  • added API to allow binding request, transaction, or dialog with specific transport. If this binding is not established, zero address will be used to match the transport.

Change History (5)

comment:1 Changed 13 years ago by anonymous

Alternative Solution

Rather than binding a {request, transaction, dialog} to a local address, the binding API can also bind it to the actual transport/listener instance, with incrementing the reference counter as necessary.

With this approach, the transport lookup will bypass the hash table lookup and rather use the actual bound transport to send the message.

comment:2 Changed 13 years ago by bennylp

There could be a simpler workaround, something like this.

  1. So basically, the stack only uses single UDP transport to send outgoing messages.
  2. Add functions to manually override the Via sent-by values (address and port), something like:
      pj_status_t pjsip_tsx_set_via(pjsip_transaction *tsx, const pj_str_t *host, int port);
      pj_status_t pjsip_dlg_set_via(pjsip_dialog *dlg, const pj_str_t *host, int port);
    
  3. Make sure that the transport (sip_transport.c) doesn't change the Via address if the address is already present.

comment:3 Changed 13 years ago by bennylp

  • Status changed from new to assigned

Workaround!

Implemented in r879:

  • pjsip_tsx_set_transport()
  • pjsip_dlg_set_transport()
  • pjsip_regc_set_transport()

It hasn't been tested yet, and the corresponding PJSUA-API for binding account to specific transport hasn't been implemented.

comment:4 Changed 13 years ago by bennylp

  • Resolution set to worksforme
  • Status changed from assigned to closed

Implemented in r881:
PJSUA-API level implementation of explicit transport binding. Also minor bug fix (adding error message for the new transport error code).

comment:5 Changed 13 years ago by bennylp

Implemented in r882:

Make the explicit transport binding works for sending response too. So now the rule regarding selection of transport when sending response is like this (these will be applied in order):

  1. if request was received on reliable transport, send response with that transport.
  2. if the request has maddr parameter in top-most Via, send the response to the specified address in the maddr parameter. If the tp_sel field of the response tdata is set (either by transaction, using pjsip_tsx_set_transport(), or manually with pjsip_tx_data_set_transport() when sending stateless response), then the response is sent using the selected transport. Otherwise transport hash table will be queried to get the transport.
  3. if request has ;rport parameter in top-most Via, send response using the transport where the request was received.
  4. If the tp_sel field of the response tdata is set (either by transaction, using pjsip_tsx_set_transport(), or manually with pjsip_tx_data_set_transport() when sending stateless response), then the response is sent using the selected transport.
  5. otherwise query the hash table as usual.
Note: See TracTickets for help on using tickets.