Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / docs / design.txt
1 Nice: Design documentation
2 ==========================
3
4 Socket ownership
5 ----------------
6
7 For UDP candidates, one socket is created for each component and bound
8 to INADDR_ANY. The same local socket is used for the host candidate,
9 STUN candidate as well as the TURN candidate. The socket handles are
10 stored to the Component structure.
11
12 The library will use the source address of incoming packets in order
13 to identify from which remote candidates, if any (peer-derived
14 candidates), packets were sent.
15
16 XXX: Describe the subtle issues with ICMP error handling when one
17 socket is used to send to multiple destinations.
18
19 Real-time considerations
20 ------------------------
21
22 One potential use for libnice code is providing network connectivity
23 for media transport in voice and video telephony applications. This
24 means that the libnice code is potentially run in real-time context
25 (for instance under POSIX SCHED_FIFO/SHCED_RR scheduling policy) and
26 ideally has deterministic execution time.
27
28 To be real-time friendly, operations with non-deterministic execution
29 time (dynamic memory allocation, file and other resource access) should
30 be done at startup/initialization phase. During an active session
31 (connectivity has been established and non-STUN traffic is being sent),
32 code should be as deterministic as possible.
33
34 Memory management
35 -----------------
36
37 To work on platforms where available memory may be constrained, libnice
38 should gracefully handle out of memory situations. If memory allocation
39 fails, the library should return an error via the originating public
40 library API function.
41
42 Use of glib creates some challenges to meet the above:
43
44 - A lot of glib's internal code assumes memory allocations will
45   always work. Use of these glib facilities should be limited.
46   While the glib default policy (see g_malloc() documentation) of terminating 
47   the process is ok for applications, this is not acceptable for library 
48   components.
49 - Glib has weak support for preallocating structures needed at
50   runtime (for instance use of timers creates a lot of memory 
51   allocation activity). 
52
53 To work around the above limitations, the following guidelines need
54 to be followed:
55
56 - Always check return values of glib functions.
57 - Use safe variants: g_malloc_try(), etc
58 - Current issues (last update 2007-05-04)
59      - g_slist_append() will crash if alloc fails
60
61 Timers
62 ------
63
64 Management of timers is handled by the 'agent' module. Other modules 
65 may use timer APIs to get timestamps, but they do not run timers. 
66
67 Glib's timer interface has some problems that have affected the design:
68
69  - an expired timer will destroy the source (a potentially costly
70    operation)
71  - it is not possible to cancel, or adjust the timer expiration
72    timer without destroying the associated source and creating 
73    a new one, which again causes malloc/frees and is potentially
74    a costly operation
75  - on Linux, glib uses gettimeofday() which is subject to clock
76    skew, and no monotonic timer API is available
77
78 Due to the above, 'agent' code runs fixed interval periodic timers
79 (started with g_timeout_add()) during candidate gathering, connectivity
80 check, and session keepalive phases. Timer frequency is set separately
81 for each phase of processing. A more elegant design would use dynamic
82 timeouts, but this would be too expensive with glib timer
83 infrastructure.
84
85 Control flow for NICE agent API (NiceAgentClass)
86 ------------------------------------------------
87
88 The main library interface for applications using libnice is the
89 NiceAgent GObject interface defined in 'nice/agent.h'.
90
91 The rough order of control follow is as follows:
92
93 - creation of NiceAgent object instance
94 - setting agent properties such as STUN and TURN server addresses
95 - connecting the GObject signals with g_signal_connect() to application
96   callback functions
97 - adding local interface addresses to use with
98   nice_agent_add_local_address()
99
100 And continues when making an initial offer:
101
102 - creating the streams with nice_agent_add_stream()
103 - attach the mainloop context to connect the NiceAgent sockets to
104   the application's event loop (using nice_agent_attach_recv())
105 - start candidate gathering by calling nice_agent_gather_candidates()
106 - the application should wait for the "candidate-gathering-done" signal
107   before going forward (so that ICE can gather the needed set of local
108   connectiviy candidates) 
109 - get the information needed for sending offer using
110   nice_agent_get_local_candidates() and
111   nice_agent_get_local_credentials()
112 - client should now send the session offer
113 - once it receives an answer, it can pass the information to NiceAgent
114   using nice_agent_set_remote_candidates() and
115   nice_agent_set_remote_credentials()
116
117 Alternatively, when answering to an initial offer:
118
119 - the first five steps are the same as above (making initial offer)
120 - pass the remote session information to NiceAgent using 
121   nice_agent_set_remote_candidates() and
122   nice_agent_set_remote_credentials()
123 - client can send the answer to session offer
124
125 Special considerations for a SIP client:
126
127 - Upon sending the initial offer/answer, client should pick one
128   local candidate as the default one, and encode it to the SDP
129   "m" and "c" lines, in addition to the ICE "a=candidate" lines.
130 - Client should connect to "new-selected-pair" signals. If this
131   signal is received, a new candidate pair has been set as 
132   a selected pair (highest priority nominated pair). See 
133   ICE specification for a definition of "nominated pairs". 
134 - Once all components of a stream have reached the
135   "NICE_COMPONENT_STATE_READY" state (as reported by 
136   "component-state-changed" signals), the client should check
137   whether its original default candidate matches the latest 
138   selected pair. If not, it needs to send an updated offer
139   it is in controlling mode. Before sending the offer, client
140   should check the "controlling-mode" property to check that
141   it still is in controlling mode (might change during ICE
142   processing due to ICE role conflicts).
143 - The "remote-attributes" SDP attribute can be created from
144   the information provided by "component-state-changed" (which
145   components are ready), "new-selected-pair" (which candidates
146   are selected) and "new-remote-candidate" (peer-reflexive
147   candidates discovered during processing) signals.
148 - Supporting forked calls is not yet supported by the API (multiple
149   sets of remote candidates for one local set of candidates).
150
151 Restarting ICE:
152
153 - ICE processing can be restarted by calling nice_agent_restart()
154 - Restart will clean the set of remote candidates, so client must
155   afterwards call nice_agent_set_remote_candidates() after receiving 
156   a new offer/answer for the restarted ICE session.
157 - Restart will reinitialize the local credentials (see 
158   nice_agent_get_local_credentials()).
159 - Note that to modify the set of local candidates, a new stream 
160   has to be created. For the remote party, this looks like a ICE
161   restart as well.
162
163 Handling fallback to non-ICE operation:
164
165 - If we are the offering party, and the remote party indicates
166   it doesn't support ICE, we can use nice_agent_set_selected_pair()
167   to force selection of a candidate pair (for remote party, 
168   the information on SDP 'm=' and 'c=' lines needs to be used
169   to generate one remote candidate for each component of the
170   streams). This function will halt all ICE processing (excluding
171   keepalives), while still allowing to send and receive media (assuming
172   NATs won't interfere).
173
174 Notes about sending media:
175
176 - Client may send media once all components of a stream have reached
177   state of NICE_COMPONENT_STATE_CONNECTED or NICE_COMPONENT_STATE_READY,
178   (as reported by "component-state-changed" signals), and a selected pair 
179   is set for all components (as reported by "new-selected-pair" signals).
180
181 STUN API
182 --------
183
184 The underlying STUN library takes care of formatting and parsing STUN
185 messages (lower layer),
186
187 Applications should only need to use the higher layer API which then
188 uses the lower layer API.
189
190 The following STUN usages are currently implemented by the
191 transaction layer:
192 - Binding discovery (RFC5389 with RFC3489 backward compatibility)
193 - Binding keep-alive
194 - ICE connectivity checks
195 - TURN
196 - STUN retransmission timers
197
198
199 STUN message API
200 ----------------
201
202 STUN message API provide thin wrappers to parse and format STUN
203 messages. To achieve maximum cross-architectures portability and retain
204 real-time friendliness, these functions are fully "computational" [1].
205 They also make no assumption about endianess or memory alignment
206 (reading single bytes or using memcpy()).
207
208 Message buffers are provided by the caller (so these can be
209 preallocated). Because STUN uses a relatively computer-friendly binary
210 format, STUN messages are stored in wire format within the buffers.
211 There is no intermediary translation, so the APIs can operate directly
212 with data received from or sent to the network.
213
214 [1] With one exception: The random number generated might access the
215 system entropy pool (/dev/urandom) if available.