tport.docs 8.98 KB
Newer Older
1
/**@MODULEPAGE "tport" - Transport Module
Pekka Pessi's avatar
Pekka Pessi committed
2 3 4 5 6

@section tport_meta Module Information

The @b tport module contains a generic transport interface used by SIP,
RTSP, and HTTP protocols. It is an abstraction layer between a protocol
7 8 9
stack and a transport protocol implementation. The interface is implemented
via transport objects. The tag parameters for transport objects are defined
in <sofia-sip/tport_tag.h>.
Pekka Pessi's avatar
Pekka Pessi committed
10 11 12

@CONTACT Pekka.Pessi@nokia.com

13 14
@STATUS @SofiaSIP Core library

Pekka Pessi's avatar
Pekka Pessi committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
@LICENSE LGPL

@section tp_primary Master, Primary and Secondary Transport Objects

A transport object can be used in three roles. Master transport object
represents all available transport. It is used to store stack and root
interface as well as common data such as SigComp state handler. The primary
transport objects represent available transports. The secondary transports
represent actual transport connections.

A protocol stack first creates a @e master @e transport object and binds a
number of primary transport objects (each representing a transport protocol
such as UDP, TCP, TLS/TCP, SCTP, etc). The binding process creates a new
primary transport object for each transport supported. If the protocol stack
is used as a server, the binding process also creates the necessary server
sockets and binds them to the specified server ports.

Secondary transport objects are created for each transport-level
connection. The @b tport module takes care of automatically creating them
and discarding them when they are no more used. The secondary transport
objects are required to transmit messages when a connection-oriented
transport protocol is used.

A secondary transport object can be created for two reasons. A server may
accept a new connection from a client, or a client may connect to a
server. When the connection belonging to a secondary transport has been
established, the protocol stack can send or receive messages through it.

@section tp_init Initializing Transports

When the primary transport object is created with tport_tcreate(), the
protocol stack must pass a #tport_stack_class_t structure containing
function pointers to the new transport object. These function pointers
are used to

-# create new message objects used to store received messages
-# pass received messages to the protocol stack, and
-# report transport errors to the protocol stack.

The transport protocols are bound to the primary transport objects with
the method tport_tbind(). The protocol stack gives the desired server
transport name (transport name is a structure containing a text-formatted
socket address along with transport name) along with the list of
transport protocols supported by the stack. The function tport_tbind()
can be called multiple times, if, for example, the server port(s) used by
transport protocol differ (for example, default TCP port for SIP is 5060,
and default TLS port is 5061).

@subsection tp_connect Connection-Oriented and Connection-Less Transports

A secondary transport objects is created for each transport-level
connection. The tport module takes care of automatically creating them,
and discarding them when they are no more used. The secondary transport
objects are required to transmit messages when a connection-oriented
transport protocol is used.

A secondary transport can be created for two reasons. A server may accept
a new connection from a client, or a client may connect to a server. When
the connection belonging to a secondary transport has been established,
the protocol stack can send or receive messages through it.

@par Connection-Oriented and Connection-Less Transports

A transport can be connection-oriented (TCP, SCTP) or connectionless
(UDP). A connection-oriented transport needs a connection to be
established before messages can be sent. It can also send messages only
to a single destination. For a connectionless transport, a destination
address must always be given.

A connectionless transport can be used to send messages to several
distinct destinations. The destination address must be given to the
kernel whenever a message is sent using connectionless transport.

Note that UDP can be used in connection-oriented manner (client does not
use sendto(), but connect() and then send()), if tport_set_params() is
called with TPTAG_CONNECT(1) argument.

@subsection tp_stream Stream and Datagram Transports

A connection-oriented transport can also be stream-based (TCP, SCTP) or
packet-based (UDP, SCTP). A stream-based transport protocol takes care of
ordering the data within a stream, a data chunk sent earlier is always
delivered before chunks sent after it. A packet-based transport delivers
data chunks independent of each other and does not maintain the relative
order, for instance, if a data chunk is lost by the network and then
retransmitted, application can receive it later than a data chunk that
was sent after lost one but did not need any retransmissions.

103
@subsection tp_magic Transport Magic
Pekka Pessi's avatar
Pekka Pessi committed
104 105 106 107

Transport magic is a cookie, a piece of data specified by stack that can
be associated with a transport (e.g., a Via header). The protocol stack
can change the type of transport magic by defining the macro
108
#TP_MAGIC_T before including <sofia-sip/tport.h>.
Pekka Pessi's avatar
Pekka Pessi committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

@section tp_op Transport Operations

@subsection tp_send Sending Messages

A message can be sent by the tport_tsend() method. The method can be
called either from the primary or from the secondary transport. If a
secondary transport is needed to send the message, it is created and
connected automatically.

The transport gets the data to be sent from the message object with
msg_iovec() call. The transport tries to send all the data using one
su_vsend() call. If the call would fail, for instance, because the send
buffer is too short, the transport object would create a reference to the
message and queue it in its own queue.

@subsection tp_recv Receiving Messages

When a primary connectionless transport object or a secondary transport
object receives new data, it allocates a new message object. The message
object is created using the factory function tpac_alloc() provided by the
protocl stack. The incoming data is passed to the message object, data is
parsed and when a message is complete, it is passed to the application
using the tpac_recv() function provided when the transport was created.

@subsection tp_refcnt Reference Counting

In order to destroy unused connections, each secondary transport object
needs to know if there is a reference to it from the stack. A protocol
stack creates a reference to a transport when it receives an incoming
request and needs to send the response using the same transport, or when
it expects a reply from the server coming on the connection used to send
the request.

@note While the reference counting has been implemented in the tport
module, the transport objects are not destroyed by timers by default as
145
all the protocol stacks do @b not properly handle the reference counting.
Pekka Pessi's avatar
Pekka Pessi committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
Timers are activated when the tag TPTAG_IDLE() is used.

@subsection tp_pend Pending Requests

The protocol stack can mark requests as @e pending using tport_pend()
function. The tport_pend() function associates a request message with a
callback and a handle to a client object. When a transport error occurs,
it is reported to the client object using the associated callback
function.

When the stack receives a response to the request it has marked as
pending, it calls tport_release(). The request can be still considered
pending, if the response was a preliminary one. In this case, the @a
still_pending argument is true. The function tport_release() is also
called without response message, if the stack is no more interested in
the response, for instance, after a timeout.

@subsection tp_queue Send Queue

Each stream-based transport also supports send queue. The queue can be
used either to queue messages during congestion, or to maintain the
relative ordering of responses. Usually, queue is used implicitly for the
first purpose, e.g., if a transport is busy sending a message it queues
further messages when tport_tsend() is called.

Explicit queueing is needed when the protocol (like HTTP/1.1) requires
that the relative order of responses is maintained. When the protocol
stack receives a request, it queues an empty response message to the
transport with tport_tqueue(). Such an empty response is marked as
incomplete, not ready to send. When application responds to the request
via tport_tqsend(), the transport object marks the message ready to send
and, if there are no other queued responses before it, sends it.

@section tp_debug Logging and Dumping Messages

Seeing message contents and network events is extremely useful when
debugging protocols. There are environment variables that are used to
activate message logging within @b tport module.
<dl compact>
<dt>@b #TPORT_LOG
186
   <dd>if set, tport module prints out the message contents
Pekka Pessi's avatar
Pekka Pessi committed
187 188 189
       after parsing
<dt>@b #TPORT_DUMP
   <dd>contains dump file name - incoming data is written
190
       dump file @e before parsing
Pekka Pessi's avatar
Pekka Pessi committed
191 192 193 194 195 196
<dt>@b #TPORT_DEBUG
   <dd>integer in range -1..9 controlling amount of
       debugging printout from @b tport module. See also #tport_log.
</dl>
 */