Project

General

Profile

SipMiddlewareApi » History » Version 150

Tijmen de Mes, 04/19/2012 03:40 PM

1 147 Adrian Georgescu
h1. Middleware API
2 102 Adrian Georgescu
3 1 Adrian Georgescu
4
5
6 147 Adrian Georgescu
This chapter describes the _Middleware API_ for SIP SIMPLE client SDK that can be used for developing a user interface (e.g. Graphical User Interface). The Middleware provides a _non-blocking_ API  that communicates with the user interface asynchronously by using _Notifications_. For its configuration, the Middleware uses the [[SipConfigurationAPI|Configuration API]].
7 1 Adrian Georgescu
8 150 Tijmen de Mes
!={width:500px}sipsimple-middleware.png!
9 147 Adrian Georgescu
10
11
h2. SIPApplication
12
13
14 62 Luci Stanescu
Implemented in [browser:sipsimple/application.py]
15 1 Adrian Georgescu
16
Implements a high-level application responsable for starting and stopping various sub-systems required to implement a fully featured SIP User Agent application. The SIPApplication class is a Singleton and can be instantiated from any part of the code, obtaining a reference to the same object. The SIPApplication takes care of initializing the following components:
17 147 Adrian Georgescu
* the twisted thread
18
* the configuration system, via the [[SipConfigurationAPI#ConfigurationManager|ConfigurationManager]]
19
* the core [[SipCoreApiDocumentation#Engine|Engine]] using the settings in the configuration
20
* the [[SipMiddlewareApi#AccountManager|AccountManager]], using the accounts in the configuration
21
* the [[SipMiddlewareApi#SessionManager|SessionManager]], in order to handle incoming sessions
22
* two [[SipMiddlewareApi#AudioBridge|AudioBridges]], using the settings in the configuration
23 1 Adrian Georgescu
24
The attributes in this class can be set and accessed on both this class and its subclasses, as they are implemented using descriptors which keep single value for each attribute, irrespective of the class from which that attribute is set/accessed. Usually, all attributes should be considered read-only.
25
26
27 147 Adrian Georgescu
h4. methods 
28 1 Adrian Georgescu
29 62 Luci Stanescu
30 1 Adrian Georgescu
31 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_)
32
>Instantiates a new SIPApplication.
33 1 Adrian Georgescu
34 147 Adrian Georgescu
*start*(_self_, *storage*)
35
>Starts the @SIPApplication@ which initializes all the components in the correct order. The @storage@ is saved as an attribute which other entities like the @Configuration Manager@ will use to take the appropriate backend. If any error occurs with loading the configuration, the exception raised by the @ConfigurationManager@ is propagated by this method and @SIPApplication@ can be started again. After this, any fatal errors will result in the SIPApplication being stopped and unusable, which means the whole application will need to stop. This method returns as soon as the twisted thread has been started, which means the application must wait for the @SIPApplicationDidStart@ notification in order to know that the application started.
36 1 Adrian Georgescu
37 147 Adrian Georgescu
*stop*(_self_)
38
>Stop all the components started by the SIPApplication. This method returns immediately, but a @SIPApplicationDidEnd@ notification is sent when all the components have been stopped.
39 1 Adrian Georgescu
40
41 147 Adrian Georgescu
h4. attributes
42 1 Adrian Georgescu
43
44 62 Luci Stanescu
45 147 Adrian Georgescu
*running*
46
  @True@ if the SIPApplication is running (it has been started and it has not been told to stop), @False@ otherwise.
47 1 Adrian Georgescu
48 147 Adrian Georgescu
*storage*
49
>Holds an object which implements the @ISIPSimpleStorage@ interface which will be used to provide a storage facility to other middleware components.
50 1 Adrian Georgescu
51 147 Adrian Georgescu
*local_nat_type*
52
>String containing the detected local NAT type.
53 1 Adrian Georgescu
54 147 Adrian Georgescu
*alert_audio_mixer*
55
>The @AudioMixer@ object created on the alert audio device as defined by the configuration (by SIPSimpleSettings.audio.alert_device).
56 1 Adrian Georgescu
57 147 Adrian Georgescu
*alert_audio_bridge*
58
>An @AudioBridge@ where @IAudioPort@ objects can be added to playback sound to the alert device.
59 1 Adrian Georgescu
60 147 Adrian Georgescu
*alert_audio_device*
61
>An @AudioDevice@ which corresponds to the alert device as defined by the configuration. This will always be part of the alert_audio_bridge.
62 1 Adrian Georgescu
63 147 Adrian Georgescu
*voice_audio_mixer*
64
>The @AudioMixer@ object created on the voice audio device as defined by the configuration (by SIPSimpleSettings.audio.input_device and SIPSimpleSettings.audio.output_device).
65 1 Adrian Georgescu
66 147 Adrian Georgescu
*voice_audio_bridge*
67
>An @AudioBridge@ where @IAudioPort@ objects can be added to playback sound to the output device or record sound from the input device.
68 1 Adrian Georgescu
69 147 Adrian Georgescu
*voice_audio_device*
70
>An @AudioDevice@ which corresponds to the voice device as defined by the configuration. This will always be part of the voice_audio_bridge.
71 1 Adrian Georgescu
72
73 147 Adrian Georgescu
h4. notifications 
74 1 Adrian Georgescu
75
76
77 147 Adrian Georgescu
*SIPApplicationWillStart*
78
>This notification is sent just after the configuration has been loaded and the twisted thread started, but before any other components have been initialized.
79
  
80
timestamp:
81 1 Adrian Georgescu
82 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
83 1 Adrian Georgescu
84 147 Adrian Georgescu
*SIPApplicationDidStart*
85
>This notification is sent when all the components have been initialized. Note: it doesn't mean that all components have succeeded, for example, the account might not have registered by this time, but the registration process will have started.
86
  
87
timestamp:
88 1 Adrian Georgescu
89 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
90 1 Adrian Georgescu
91 147 Adrian Georgescu
*SIPApplicationWillEnd*
92
>This notification is sent as soon as the @stop()@ method has been called.
93
  
94
timestamp:
95 1 Adrian Georgescu
96 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
97 1 Adrian Georgescu
98 147 Adrian Georgescu
*SIPApplicationDidEnd*
99
>This notification is sent when all the components have been stopped. All components have been given reasonable time to shutdown gracefully, such as the account unregistering. However, because of factors outside the control of the middleware, such as network problems, some components might not have actually shutdown gracefully; this is needed because otherwise the SIPApplication could hang indefinitely (for example because the system is no longer connected to a network and it cannot be determined when it will be again).
100
  
101
timestamp:
102 1 Adrian Georgescu
103 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
104 63 Luci Stanescu
105 147 Adrian Georgescu
*SIPApplicationFailedToStartTLS*
106
>This notification is sent when a problem arises with initializing the TLS transport. In this case, the Engine will be started without TLS support and this notification contains the error which identifies the cause for not being able to start the TLS transport.
107
  
108
timestamp:
109 1 Adrian Georgescu
110 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
111
  
112
error:
113 1 Adrian Georgescu
114 147 Adrian Georgescu
>The exception raised by the Engine which identifies the cause for not being able to start the TLS transport.
115 1 Adrian Georgescu
116
117
118 147 Adrian Georgescu
h2. Storage API
119
120
121
Different middleware components may need to store data, i.e. configuration files or XCAP documents. The @Storage API@ defines a collection of backends which other components will use to store their data.
122
123
124
h3. API Definition
125
126
127
The @Storage API@ currently requires the following attributes to be defined as per the @ISIPSimpleStorage@ interface:
128
129
*configuration_backend*
130
>The backend used for storing the configuration.
131
132
*xcap_storage_factory*
133
>Factory used to create XCAP storage backends for each account.
134
135
136
h3. Provided implementations
137
138
139
Two storage implementations are provided: *FileStorage* and *MemoryStorage* both located in the *sipsimple.storage* module.
140
141
142
h2. SIP Sessions
143
144
145
SIP sessions are supported by the @sipsimple.session.Session@ class and independent stream classes, which need to implement the @sipsimple.streams.IMediaStream@ interface. The @Session@ class takes care of the signalling, while the streams offer the actual media support which is negotiated by the @Session@. The streams which are implemented in the SIP SIMPLE middleware are provided in modules within the @sipsimple.streams@ package, but they are accessible for import directly from @sipsimple.streams@. Currently, the middleware implements two types of streams, one for RTP data, with a concrete implementation in the @AudioStream@ class, and one for MSRP sessions, with concrete implementations in the @ChatStream@, @FileTransferStream@ and @DesktopSharingStream@ classes. However, the application can provide its own stream implementation, provided they respect the @IMediaStream@ interface.
146
147
The @sipsimple.streams@ module also provides a mechanism for automatically registering media streams in order for them to be used for incoming sessions. This is explained in more detail in [[SipMiddlewareApi#MediaStreamRegistry|MediaStreamRegistry]].
148
149
150
151
h3. SessionManager
152
153
154 1 Adrian Georgescu
Implemented in [browser:sipsimple/session.py]
155
156 147 Adrian Georgescu
The @sipsimple.session.SessionManager@ class is a singleton, which acts as the central aggregation point for sessions within the middleware.
157 1 Adrian Georgescu
Although it is mainly used internally, the application can use it to query information about all active sessions.
158
The SessionManager is implemented as a singleton, meaning that only one instance of this class exists within the middleware. The SessionManager is started by the SIPApplication and takes care of handling incoming sessions and closing all sessions when SIPApplication is stopped.
159
160
161 147 Adrian Georgescu
h4. attributes
162 1 Adrian Georgescu
163
164
165 147 Adrian Georgescu
*sessions*
166
>A property providing a copy of the list of all active @Sesssion@ objects within the application, meaning any @Session@ object that exists globally within the application and is not in the @NULL@ or @TERMINATED@ state.
167 1 Adrian Georgescu
168
169 147 Adrian Georgescu
h4. methods
170 1 Adrian Georgescu
171
172
173 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_)
174
>Instantiate a new @SessionManager@ object.
175 1 Adrian Georgescu
176 147 Adrian Georgescu
177
*start*(_self_)
178
>Start the @SessionManager@ in order to be able to handle incoming sessions. This method is called automatically when SIPApplication is started. The application should not call this method directly.
179
180
*stop*(_self_)
181
>End all connected sessions. This method is called automatically when SIPApplication is stopped. The application should not call this method directly.
182
183
184
h3. Session
185
186
187 1 Adrian Georgescu
Implemented in [browser:sipsimple/session.py]
188
189 147 Adrian Georgescu
A @sipsimple.session.Session@ object represents a complete SIP session between the local and a remote endpoints. Both incoming and outgoing sessions are represented by this class.
190 1 Adrian Georgescu
191 147 Adrian Georgescu
A @Session@ instance is a stateful object, meaning that it has a @state@ attribute and that the lifetime of the session traverses different states, from session creation to termination.
192 1 Adrian Georgescu
State changes are triggered by methods called on the object by the application or by received network events.
193
These states and their transitions are represented in the following diagram:
194
195 147 Adrian Georgescu
!{}/raw-attachment/wiki/SipCoreApiDocumentation/sipsimple-core-invite-state-machine.png!
196 1 Adrian Georgescu
197 147 Adrian Georgescu
Although these states are crucial to the correct operation of the @Session@ object, an application using this object does not need to keep track of these states, as a set of notifications is also emitted, which provide all the necessary information to the application.
198 1 Adrian Georgescu
199 147 Adrian Georgescu
The @Session@ is completely independent of the streams it contains, which need to be implementations of the @sipsimple.streams.IMediaStream@ interface. This interface provides the API by which the @Session@ communicates with the streams. This API should not be used by the application, unless it also provides stream implementations or a SIP INVITE session implementation.
200 1 Adrian Georgescu
201
202 147 Adrian Georgescu
h4. methods
203 1 Adrian Georgescu
204
205
206 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *account*)
207
>Creates a new @Session@ object in the @None@ state.
208
  
209
>+_account_+:
210 1 Adrian Georgescu
211 147 Adrian Georgescu
>The local account to be associated with this @Session@.
212 1 Adrian Georgescu
213 147 Adrian Georgescu
*connect*(_self_, *to_header*, *routes*, *streams*, *is_focus*=@False@, *subject*=@None@)
214
>Will set up the @Session@ as outbound and propose the new session to the specified remote party and move the state machine to the @outgoing@ state.
215
>Before contacting the remote party, a @SIPSessionNewOutgoing@ notification will be emitted.
216
>If there is a failure or the remote party rejected the offer, a @SIPSessionDidFail@ notification will be sent.
217
>Any time a ringing indication is received from the remote party, a @SIPSessionGotRingIndication@ notification is sent.
218
>If the remote party accepted the session, a @SIPSessionWillStart@ notification will be sent, followed by a @SIPSessionDidStart@ notification when the session is actually established.
219
>This method may only be called while in the @None@ state.
220
  
221
>+_to_header_+:
222 1 Adrian Georgescu
223 147 Adrian Georgescu
>A @sipsimple.core.ToHeader@ object representing the remote identity to initiate the session to.
224
  
225
>+_routes_+:
226 1 Adrian Georgescu
227 147 Adrian Georgescu
>An iterable of @sipsimple.util.Route@ objects, specifying the IP, port and transport to the outbound proxy.
228
>These routes will be tried in order, until one of them succeeds.
229
  
230
>+_streams_+:
231 1 Adrian Georgescu
232 147 Adrian Georgescu
>A list of stream objects which will be offered to the remote endpoint.
233
  
234
>+_is_focus_+:
235 1 Adrian Georgescu
236 147 Adrian Georgescu
>Boolean flag indicating if the @isfocus@ parameter should be added to the @Contact@ header according to RFC 4579.
237
  
238
>+_subject_+:
239 1 Adrian Georgescu
240 147 Adrian Georgescu
>Session subject. If not None a @Subject@ header will be added with the specified value.
241 1 Adrian Georgescu
242 147 Adrian Georgescu
*send_ring_indication*(_self_)
243
>Sends a 180 provisional response in the case of an incoming session.
244 1 Adrian Georgescu
245 147 Adrian Georgescu
*accept*(_self_, *streams*)
246
>Calling this methods will accept an incoming session and move the state machine to the @accepting@ state.
247
>When there is a new incoming session, a @SIPSessionNewIncoming@ notification is sent, after which the application can call this method on the sender of the notification.
248
>After this method is called, @SIPSessionWillStart@ followed by @SIPSessionDidStart@ will be emitted, or @SIPSessionDidFail@ on an error.
249
>This method may only be called while in the @incoming@ state.
250
  
251
>+_streams_+:
252 1 Adrian Georgescu
253 147 Adrian Georgescu
>A list of streams which needs to be a subset of the proposed streams which indicates which streams are to be accepted. All the other proposed streams will be rejected.
254 1 Adrian Georgescu
255 147 Adrian Georgescu
*reject*(_self_, *code*=@603@, *reason*=@None@)
256
>Reject an incoming session and move it to the @terminating@ state, which eventually leads to the @terminated@ state.
257
>Calling this method will cause the @Session@ object to emit a @SIPSessionDidFail@ notification once the session has been rejected.
258
>This method may only be called while in the @incoming@ state.
259
  
260
>+_code_+:
261 1 Adrian Georgescu
262 147 Adrian Georgescu
>An integer which represents the SIP status code in the response which is to be sent. Usually, this is either 486 (Busy) or 603 (Decline/Busy Everywhere).
263
  
264
>+_reason_+:
265 1 Adrian Georgescu
266 147 Adrian Georgescu
>The string which is to be sent as the SIP status reason in the response, or None if PJSIP's default reason for the specified code is to be sent.
267 1 Adrian Georgescu
268 147 Adrian Georgescu
*accept_proposal*(_self_, *streams*)
269
>When the remote party proposes to add some new streams, signaled by the @SIPSessionGotProposal@ notification, the application can use this method to accept the stream(s) being proposed.
270
>After calling this method a @SIPSessionGotAcceptProposal@ notification is sent, unless an error occurs while setting up the new stream, in which case a @SIPSessionHadProposalFailure@ notification is sent and a rejection is sent to the remote party. As with any action which causes the streams in the session to change, a @SIPSessionDidRenegotiateStreams@ notification is also sent.
271
>This method may only be called while in the @received_proposal@ state.
272
  
273
>+_streams_+:
274 1 Adrian Georgescu
275 147 Adrian Georgescu
>A list of streams which needs to be a subset of the proposed streams which indicates which streams are to be accepted. All the other proposed streams will be rejected.
276 1 Adrian Georgescu
277 147 Adrian Georgescu
*reject_proposal*(_self_, *code*=@488@, *reason*=@None@)
278
>When the remote party proposes new streams that the application does not want to accept, this method can be used to reject the proposal, after which a @SIPSessionGotRejectProposal@ or @SIPSessionHadProposalFailure@ notification is sent.
279
>This method may only be called while in the @received_proposal@ state.
280
  
281
>+_code_+:
282 1 Adrian Georgescu
283 147 Adrian Georgescu
>An integer which represents the SIP status code in the response which is to be sent. Usually, this is 488 (Not Acceptable Here).
284
  
285
>+_reason_+:
286 1 Adrian Georgescu
287 147 Adrian Georgescu
>The string which is to be sent as the SIP status reason in the response, or None if PJSIP's default reason for the specified code is to be sent.
288 1 Adrian Georgescu
289 147 Adrian Georgescu
*add_stream*(_self_, *stream*)
290
>Proposes a new stream to the remote party.
291
>Calling this method will cause a @SIPSessionGotProposal@ notification to be emitted.
292
>After this, the state machine will move into the @sending_proposal@ state until either a @SIPSessionGotAcceptProposal@, @SIPSessionGotRejectProposal@ or @SIPSessionHadProposalFailure@ notification is sent, informing the application if the remote party accepted the proposal. As with any action which causes the streams in the session to change, a @SIPSessionDidRenegotiateStreams@ notification is also sent.
293
>This method may only be called while in the @connected@ state.
294 1 Adrian Georgescu
295 147 Adrian Georgescu
*remove_stream*(_self_, *stream*)
296
>Stop the stream and remove it from the session, informing the remote party of this. Although technically this is also done via an SDP negotiation which may fail, the stream will always get remove (if the remote party refuses the re-INVITE, the result will be that the remote party will have a different view of the active streams than the local party).
297
>This method may only be called while in the @connected@ state.
298 1 Adrian Georgescu
299 147 Adrian Georgescu
*cancel_proposal*(_self_)
300
>This method cancels a proposal of adding a stream to the session by sending a CANCEL request. A @SIPSessionGotRejectProposal@ notification will be sent with code 487.
301 1 Adrian Georgescu
302 147 Adrian Georgescu
*hold*(_self_)
303
>Put the streams of the session which support the notion of hold on hold.
304
>This will cause a @SIPSessionDidChangeHoldState@ notification to be sent.
305
>This method may be called in any state and will send the re-INVITE as soon as it is possible.
306 1 Adrian Georgescu
307 147 Adrian Georgescu
*unhold*(_self_)
308
>Take the streams of the session which support the notion of hold out of hold.
309
>This will cause a @SIPSessionDidChangeHoldState@ notification to be sent.
310
>This method may be called in any state and will send teh re-INVITE as soon as it is possible.
311 1 Adrian Georgescu
312 147 Adrian Georgescu
*end*(_self_)
313
>This method may be called any time after the @Session@ has started in order to terminate the session by sending a BYE request.
314
>Right before termination a @SIPSessionWillEnd@ notification is sent, after termination @SIPSessionDidEnd@ is sent.
315 1 Adrian Georgescu
316 147 Adrian Georgescu
*transfer*(_self_, *target_uri*,  *replaced_session*=@None@)
317
>Proposes a blind call transfer to a new target URI or assisted transfer to an URI belonging to an already established session. 
318 1 Adrian Georgescu
319 147 Adrian Georgescu
*accept_transfer*(_self_)
320
>Accepts an incoming call transfer request.
321 1 Adrian Georgescu
322 147 Adrian Georgescu
*reject_transfer*(_self_, *code*=@486@, *reason_=@None@)
323
>Rejects an incoming call transfer request.
324 1 Adrian Georgescu
325
326
327 147 Adrian Georgescu
h4. attributes
328 1 Adrian Georgescu
329
330
331 147 Adrian Georgescu
*state*
332
>The state the object is currently in, being one of the states from the diagram above.
333 1 Adrian Georgescu
334 147 Adrian Georgescu
*account*
335
>The @sipsimple.account.Account@ or @sipsimple.account.BonjourAccount@ object that the @Session@ is associated with.
336
>On an outbound session, this is the account the application specified on object instantiation.
337 1 Adrian Georgescu
338 147 Adrian Georgescu
*direction*
339
>A string indicating the direction of the initial negotiation of the session.
340
>This can be either @None@, "incoming" or "outgoing".
341 1 Adrian Georgescu
342 147 Adrian Georgescu
*transport*
343
>A string representing the transport this @Session@ is using: @"udp"@, @"tcp"@ or @"tls"@.
344 1 Adrian Georgescu
345 147 Adrian Georgescu
*start_time*
346
>The time the session started as a @datetime.datetime@ object, or @None@ if the session was not yet started.
347 1 Adrian Georgescu
348 147 Adrian Georgescu
*stop_time*
349
>The time the session stopped as a @datetime.datetime@ object, or @None@ if the session has not yet terminated.
350 1 Adrian Georgescu
351 147 Adrian Georgescu
*on_hold*
352
>Boolean indicating whether the session was put on hold, either by the local or the remote party.
353 1 Adrian Georgescu
354 147 Adrian Georgescu
*remote_user_agent*
355
>A string indicating the remote user agent, if it provided one.
356
>Initially this will be @None@, it will be set as soon as this information is received from the remote party (which may be never).
357 1 Adrian Georgescu
358 147 Adrian Georgescu
*local_identity*
359
>The @sipsimple.core.FrozenFromHeader@ or @sipsimple.core.FrozenToHeader@ identifying the local party, if the session is active, @None@ otherwise.
360 1 Adrian Georgescu
361 147 Adrian Georgescu
*remote_identity*
362
>The @sipsimple.core.FrozenFromHeader@ or @sipsimple.core.FrozenToHeader@ identifying the remote party, if the session is active, @None@ otherwise.
363 1 Adrian Georgescu
364 147 Adrian Georgescu
*streams*
365
>A list of the currently active streams in the @Session@.
366 1 Adrian Georgescu
367 147 Adrian Georgescu
*proposed_streams*
368
>A list of the currently proposed streams in the @Session@, or @None@ if there is no proposal in progress.
369 1 Adrian Georgescu
370 147 Adrian Georgescu
*conference*
371
>A @ConferenceHandler@ object instance (or Null). It can be later used to add/remove participants from a remote conference.
372 1 Adrian Georgescu
373 147 Adrian Georgescu
*subject*
374
>The session subject as a unicode object.
375 1 Adrian Georgescu
376 147 Adrian Georgescu
*replaced_session*
377
>A @Session@ object instance (or Null). It can be used for assisted call transfer.
378 1 Adrian Georgescu
379 147 Adrian Georgescu
*transfer_handler*
380
>A @TransferHandler@ object instance (or Null). It is used for managing the call transfer process.
381 1 Adrian Georgescu
382 147 Adrian Georgescu
*transfer_info*
383
>A @TransferInfo@ object instance (or Null). It is used for describing the details of a call transfer operation.
384 1 Adrian Georgescu
385
386 147 Adrian Georgescu
h4. notifications
387 1 Adrian Georgescu
388
389
390 147 Adrian Georgescu
*SIPSessionNewIncoming*
391
>Will be sent when a new incoming @Session@ is received.
392
>The application should listen for this notification to get informed of incoming sessions.
393
  
394
>+_timestamp_+:
395 1 Adrian Georgescu
396 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
397
  
398
>+_streams_+:
399 55 Adrian Georgescu
400 147 Adrian Georgescu
>A list of streams that were proposed by the remote party.
401 57 Adrian Georgescu
402 147 Adrian Georgescu
*SIPSessionNewOutgoing*
403
>Will be sent when the application requests a new outgoing @Session@.
404
  
405
>+_timestamp_+:
406 1 Adrian Georgescu
407 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
408
  
409
>+_streams_+:
410 1 Adrian Georgescu
411 147 Adrian Georgescu
>A list of streams that were proposed to the remote party.
412 1 Adrian Georgescu
413 147 Adrian Georgescu
*SIPSessionGotRingIndication*
414
>Will be sent when an outgoing @Session@ receives an indication that a remote device is ringing.
415
  
416
>+_timestamp_+:
417 67 Luci Stanescu
418 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
419 94 Adrian Georgescu
420 147 Adrian Georgescu
*SIPSessionGotProvisionalResponse*
421
>Will be sent whenever the @Session@ receives a provisional response as a result of sending a (re-)INVITE.
422
  
423
>+_timestamp_+:
424 67 Luci Stanescu
425 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
426
  
427
>+_code_+:
428 1 Adrian Georgescu
429 147 Adrian Georgescu
>The SIP status code received.
430
  
431
>+_reason_+:
432 94 Adrian Georgescu
433 147 Adrian Georgescu
>The SIP status reason received.
434 1 Adrian Georgescu
435 147 Adrian Georgescu
*SIPSessionWillStart*
436
>Will be sent just before a @Session@ completes negotiation.
437
>In terms of SIP, this is sent after the final response to the @INVITE@, but before the @ACK@.
438
  
439
>+_timestamp_+:
440 1 Adrian Georgescu
441 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
442 1 Adrian Georgescu
443 147 Adrian Georgescu
*SIPSessionDidStart*
444
>Will be sent when a @Session@ completes negotiation and all the streams have started.
445
>In terms of SIP this is sent after the @ACK@ was sent or received.
446
  
447
>+_timestamp_+:
448 1 Adrian Georgescu
449 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
450
  
451
>+_streams_+:
452 1 Adrian Georgescu
453 147 Adrian Georgescu
>The list of streams which now form the active streams of the @Session@.
454 1 Adrian Georgescu
455 147 Adrian Georgescu
*SIPSessionDidFail*
456
>This notification is sent whenever the session fails before it starts.
457
>The failure reason is included in the data attributes.
458
>This notification is never followed by @SIPSessionDidEnd@.
459
  
460
>+_timestamp_+:
461 1 Adrian Georgescu
462 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
463
  
464
>+_originator_+:
465 1 Adrian Georgescu
466 147 Adrian Georgescu
>A string indicating the originator of the @Session@. This will either be "local" or "remote".
467
  
468
>+_code_+:
469 1 Adrian Georgescu
470 147 Adrian Georgescu
>The SIP error code of the failure.
471
  
472
>+_reason_+:
473 1 Adrian Georgescu
474 147 Adrian Georgescu
>A SIP status reason.
475
  
476
>+_failure_reason_+:
477 1 Adrian Georgescu
478 147 Adrian Georgescu
>A string which represents the reason for the failure, such as @"user_request"@, @"missing ACK"@, @"SIP core error..."@.
479 1 Adrian Georgescu
480 147 Adrian Georgescu
*SIPSessionWillEnd*
481
>Will be sent just before terminating a @Session@.
482
  
483
>+_timestamp_+:
484 1 Adrian Georgescu
485 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
486 1 Adrian Georgescu
487 147 Adrian Georgescu
*SIPSessionDidEnd*
488
>Will be sent always when a @Session@ ends as a result of remote or local session termination.
489
  
490
>+_timestamp_+:
491 1 Adrian Georgescu
492 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
493
  
494
>+_originator_+:
495 1 Adrian Georgescu
496 147 Adrian Georgescu
>A string indicating who originated the termination. This will either be "local" or "remote".
497
  
498
>+_end_reason_+:
499 1 Adrian Georgescu
500 147 Adrian Georgescu
>A string representing the termination reason, such as @"user_request"@, @"SIP core error..."@.
501 1 Adrian Georgescu
502 147 Adrian Georgescu
*SIPSessionDidChangeHoldState*
503
>Will be sent when the session got put on hold or removed from hold, either by the local or the remote party.
504
  
505
>+_timestamp_+:
506 1 Adrian Georgescu
507 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
508
  
509
>+_originator_+:
510 1 Adrian Georgescu
511 147 Adrian Georgescu
>A string indicating who originated the hold request, and consequently in which direction the session got put on hold.
512
  
513
>+_on_hold_+:
514 1 Adrian Georgescu
515 147 Adrian Georgescu
  @True@ if there is at least one stream which is on hold and @False@ otherwise.
516
  
517
>+_partial_+:
518 1 Adrian Georgescu
519 147 Adrian Georgescu
  @True@ if there is at least one stream which is on hold and one stream which supports hold but is not on hold and @False@ otherwise.
520 1 Adrian Georgescu
521 147 Adrian Georgescu
*SIPSessionGotProposal*
522
>Will be sent when either the local or the remote party proposes to add streams to the session.
523
  
524
>+_timestamp_+:
525 1 Adrian Georgescu
526 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
527
  
528
>+_originator_+:
529 1 Adrian Georgescu
530 147 Adrian Georgescu
>The party that initiated the stream proposal, can be either "local" or "remote".
531
  
532
>+_streams_+:
533 1 Adrian Georgescu
534 147 Adrian Georgescu
>A list of streams that were proposed.
535 1 Adrian Georgescu
536 147 Adrian Georgescu
*SIPSessionGotRejectProposal*
537
>Will be sent when either the local or the remote party rejects a proposal to have streams added to the session.
538
  
539
>+_timestamp_+:
540 1 Adrian Georgescu
541 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
542
  
543
>+_originator_+:
544 1 Adrian Georgescu
545 147 Adrian Georgescu
>The party that initiated the stream proposal, can be either "local" or "remote".
546
  
547
>+_code_+:
548 1 Adrian Georgescu
549 147 Adrian Georgescu
>The code with which the proposal was rejected.
550
  
551
>+_reason_+:
552 1 Adrian Georgescu
553 147 Adrian Georgescu
>The reason for rejecting the stream proposal.
554
  
555
>+_streams_+:
556 1 Adrian Georgescu
557 147 Adrian Georgescu
>The list of streams which were rejected.
558 1 Adrian Georgescu
559 147 Adrian Georgescu
*SIPSessionGotAcceptProposal*
560
>Will be sent when either the local or the remote party accepts a proposal to have stream( added to the session.
561
  
562
>+_timestamp_+:
563 1 Adrian Georgescu
564 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
565
  
566
>+_originator_+:
567 1 Adrian Georgescu
568 147 Adrian Georgescu
>The party that initiated the stream proposal, can be either "local" or "remote".
569
  
570
>+_streams_+:
571
572
>The list of streams which were accepted.
573
  
574
>+_proposed_streams_+:
575
576
>The list of streams which were originally proposed.
577
578
*SIPSessionHadProposalFailure*
579
>Will be sent when a re-INVITE fails because of an internal reason (such as a stream not being able to start).
580
  
581
>+_timestamp_+:
582
583
>A @datetime.datetime@ object indicating when the notification was sent.
584
  
585
>+_failure_reason_+:
586
587
>The error which caused the proposal to fail.
588
  
589
>+_streams_+:
590
591
>The streams which were part of this proposal.
592
593
*SIPSessionDidRenegotiateStreams*
594
>Will be sent when a media stream is either activated or deactivated.
595
>An application should listen to this notification in order to know when a media stream can be used.
596
  
597
>+_timestamp_+:
598
599
>A @datetime.datetime@ object indicating when the notification was sent.
600
  
601
>+_action_+:
602
603
>A string which is either @"add"@ or @"remove"@ which specifies what happened to the streams the notificaton referes to
604
  
605
>+_streams_+:
606
607
>A list with the streams which were added or removed.
608
609
*SIPSessionDidProcessTransaction*
610
>Will be sent whenever a SIP transaction is complete in order to provide low-level details of the progress of the INVITE dialog.
611
  
612
>+_timestamp_+:
613
614
>A @datetime.datetime@ object indicating when the notification was sent.
615
  
616
>+_originator_+:
617
618
>The initiator of the transaction, @"local"@ or @"remote"@.
619
  
620
>+_method_+:
621
622
>The method of the request.
623
  
624
>+_code_+:
625
626
>The SIP status code of the response.
627
  
628
>+_reason_+:
629
630
>The SIP status reason of the response.
631
  
632
>+_ack_received_+:
633
634
>This attribute is only present for INVITE transactions and has one of the values @True@, @False@ or @"unknown"@. The last value may occur then PJSIP does not let us know whether the ACK was received or not.
635
636
*SIPSessionTransferNewOutgoing*
637
>Will be sent whenever a SIP session initiates an outgoing call transfer request.
638
  
639
>+_timestamp_+:
640
641
>A @datetime.datetime@ object indicating when the notification was sent.
642
  
643
>+_transfer_destination_+:
644
645
>The destination SIP URI of the call transfer request.
646
  
647
>+_transfer_source_+:
648
649
>The source SIP URI of the call transfer request.
650
651
*SIPSessionTransferDidStart*
652
>Will be sent whenever a call transfer has been started.
653
  
654
>+_timestamp_+:
655
656
>A @datetime.datetime@ object indicating when the notification was sent.
657
658
*SIPSessionTransferDidFail*
659
>Will be sent whenever a call transfer request has failed.
660
  
661
>+_timestamp_+:
662
663
>A @datetime.datetime@ object indicating when the notification was sent.
664
  
665
>+_code_+:
666
667
>The SIP failure code reported by the SIP stack.
668
  
669
>+_reason_+:
670
671
>The reason of the failure as a string.
672
673
674
As an example for how to use the @Session@ object, the following provides a basic Python program that initiates an outgoing SIP session request see [[SipSessionExample|Minimalist Session Example code]].
675
676
677
h3. IMediaStream
678
679
680
Implemented in [browser:sipsimple/streams/+init+.py]
681
682
This interface describes the API which the @Session@ uses to communicate with the streams. All streams used by the @Session@ +must+ respect this interface.
683
684
685
h4. methods
686
687
688
689
*<notextile>__init__</notextile>*(_self_, _account_)
690
>Initializes the generic stream instance.
691
692
*new_from_sdp*(_cls_, _account_, _remote_sdp_, _stream_index_)
693
>A classmethod which returns an instance of this stream implementation if the sdp is accepted by the stream or None otherwise.
694
  
695
account:
696
697
>The @sipsimple.account.Account@ or @sipsimple.account.BonjourAccount@ object the session which this stream would be part of is associated with.
698
  
699
remote_sdp:
700
701
>The @FrozenSDPSession@ which was received by the remote offer.
702
  
703
stream_index:
704
705
>An integer representing the index within the list of media streams within the whole SDP which this stream would be instantiated for. 
706
707
*get_local_media*(_self_, _for_offer_)
708
>Return an @SDPMediaStream@ which represents an offer for using this stream if @for_offer@ is @True@ and a response to an SDP proposal otherwise.
709
  
710
for_offer:
711
712
  @True@ if the @SDPMediaStream@ will be used for an SDP proposal and @False@ if for a response.
713
714
*initialize*(_self_, _session_, _direction_)
715
>Initializes the stream. This method will get called as soon as the stream is known to be at least offered as part of the @Session@. If initialization goes fine, the stream must send a @MediaStreamDidInitialize@ notification or a @MediaStreamDidFail@ notification otherwise.
716
  
717
session:
718
719
>The @Session@ object this stream will be part of.
720
  
721
direction:
722
723
  @"incoming"@ if the stream was created because of a received proposal and @"outgoing"@ if a proposal was sent. Note that this need not be the same as the initial direction of the @Session@ since streams can be proposed in either way using re-INVITEs.
724
725
*start*(_self_, _local_sdp_, _remote_sdp_, _stream_index_)
726
>Starts the stream. This method will be called as soon is known to be used in the @Session@ (eg. only called for an incoming proposal if the local party accepts the proposed stream). If starting succeeds, the stream must send a @MediaStreamDidStart@ notification or a @MediaStreamDidFail@ notification otherwise.
727
  
728
local_sdp:
729
730
>The @FrozenSDPSession@ which is used by the local endpoint.
731
  
732
remote_sdp:
733
734
>The @FrozenSDPSession@ which is used by the remote endpoint.
735
  
736
stream_index:
737
738
>An integer representing the index within the list of media streams within the whole SDP which this stream is represented by. 
739
740
*validate_update*(_self_, _remote_sdp_, _stream_index_)
741
>This method will be called when a re-INVITE is received which changes the parameters of the stream within the SDP. The stream must return @True@ if the changes are acceptable or @False@ otherwise. If any changed streams return @False@ for a re-INVITE, the re-INVITE will be refused with a negative response. This means that streams must not changed any internal data when this method is called as the update is not guaranteed to be applied even if the stream returns @True@. 
742
  
743
remote_sdp:
744
745
>The @FrozenSDPSession@ which is used by the remote endpoint.
746
  
747
stream_index:
748
749
>An integer representing the index within the list of media streams within the whole SDP which this stream is represented by. 
750
751
*update*(_self_, _local_sdp_, _remote_sdp_, _stream_index_)
752
>This method is called when the an SDP negotiation initiated by either the local party or the remote party succeeds. The stream must update its internal state according to the new SDP in use.
753
  
754
local_sdp:
755
756
>The @FrozenSDPSession@ which is used by the local endpoint.
757
  
758
remote_sdp:
759
760
>The @FrozenSDPSession@ which is used by the remote endpoint.
761
  
762
stream_index:
763
764
>An integer representing the index within the list of media streams within the whole SDP which this stream is represented by. 
765
766
*hold*(_self_)
767
>Puts the stream on hold if supported by the stream. Typically used by audio and video streams. The stream must immediately stop sending/receiving data and calls to @get_local_media()@ following calls to this method must return an SDP which reflects the new hold state.
768
769
*unhold*(_self_)
770
>Takes the stream off hold. Typically used by audio and video streams. Calls to @get_local_media()@ following calls to this method must return an SDP which reflects the new hold state.
771
772
*deactivate*(_self_)
773
>This method is called on a stream just before the stream will be removed from the @Session@ (either as a result of a re-INVITE or a BYE). This method is needed because it avoids a race condition with streams using stateful protocols such as TCP: the stream connection might be terminated before the SIP signalling announces this due to network routing inconsistencies and the other endpoint would not be able to distinguish between this case and an error which caused the stream transport to fail. The stream must not take any action, but must consider that the transport being closed by the other endpoint after this method was called as a normal situation rather than an error condition.
774
775
*end*(_self_)
776
>Ends the stream. This must close the underlying transport connection. The stream must send a @MediaStreamWillEnd@ just after this method is called and a @MediaStreamDidEnd@ as soon as the operation is complete. This method is always be called by the @Session@ on the stream if at least the @initialize()@ method has been called. This means that once a stream sends the @MediaStreamDidFail@ notification, the @Session@ will still call this method.
777
778
779
h4. attributes
780
781
782
783
*type* (class attribute)
784
>A string identifying the stream type (eg: @"audio"@, @"video"@).
785
786
*priority* (class attribute)
787
>An integer value indicating the stream priority relative to the other streams types (higher numbers have higher priority).
788
789
*hold_supported*
790
>True if the stream supports hold
791
792
*on_hold_by_local*
793
>True if the stream is on hold by the local party
794
795
*on_hold_by_remote*
796
>True if the stream is on hold by the remote
797
798
*on_hold*
799
>True if either on_hold_by_local or on_hold_by_remote is true
800
801
802
h4. notifications
803
804
805
These notifications must be generated by all streams in order for the @Session@ to know the state of the stream.
806
807
808
*MediaStreamDidInitialize*
809
>Sent when the stream has been successfully initialized.
810
811
*MediaStreamDidStart*
812
>Sent when the stream has been successfully started.
813
814
*MediaStreamDidFail*
815
>Sent when the stream has failed either as a result of calling one of its methods, or during the normal operation of the stream (such as the transport connection being closed).
816
817
*MediaStreamWillEnd*
818
>Sent immediately after the @end()@ method is called.
819
820
*MediaStreamDidEnd*
821
>Sent when the @end()@ method finished closing the stream.
822
823
824
h3. MediaStreamRegistry
825
826
827
The MediaStream registry is a collection of classes which implement @IMediaStream@. This collection is used by the @Session@ to select a stream class for instantiation in the case of an incomming session. The streams are included in the collection in the descending order of their priority. Thus, streams with a higher priority will be tried first by the @Session@. This object is a Singleton so references to the same object can be obtained by a simple instantiation.
828
829
There are several pre-built streams based on the @IMediaStream@ API:
830
* @sipsimple.streams.rtp.AudioStream@ - Audio stream based on RTP
831
* @sipsimple.streams.msrp.ChatStream@ - Chat stream based on MSRP 
832
* @sipsimple.streams.msrp.FileTransferStream@ - File Transfer stream based on MSRP 
833
* @sipsimple.streams.msrp.DesktopSharingStream@ -  Desktop Sharing stream based on VNC over MSRP
834
835
Other streams which are created by the application must be registered in this registry. For a simple way of doing this, see [[SipMiddlewareApi#MediaStreamRegistrar|MediaStreamRegistrar]].
836
837
838
h4. methods
839
840
841
842
*<notextile>__init__</notextile>*(_self_)
843
>Instantiate the MediaStreamRegistry. This will be called just once when first (and only) instance is created.
844
845
*<notextile>__iter__</notextile>*(_self_)
846
>This method allows the registry to be iterated through and will return classes which were registered to it.
847
848
*add*(_self_, *cls*)
849
>Add @cls@ to the registry of streams. The class must implement the @IMediaStream@ interface.
850
851
852
h3. MediaStreamRegistrar
853
854
855
This is a convenience metaclass which automatically registers a defined class with the @MediaStreamRegistry@. In order to use this class, one simply needs to use it as the metaclass of the new stream.
856
857
<pre>
858 1 Adrian Georgescu
from zope.interface import implements
859
860
from sipsimple.streams import IMediaStream, MediaStreamRegistrar
861
862
863
class MyStream(object):
864
  __metaclass__ = MediaStreamRegistrar
865
866
  implements(IMediaStream)
867
  
868
[...] 
869 147 Adrian Georgescu
</pre>
870 1 Adrian Georgescu
871
872 147 Adrian Georgescu
h3. AudioStream
873
874
875 1 Adrian Georgescu
Implemented in [browser:sipsimple/streams/rtp.py]
876
877 147 Adrian Georgescu
The @AudioStream@ is an implementation of @IMediaStream@ which supports audio data using the @AudioTransport@ and @RTPTransport@ of the SIP core. As such, it provides all features of these objects, including ICE negotiation. An example SDP created using the @AudioStream@ is provided below:
878 1 Adrian Georgescu
879 147 Adrian Georgescu
<pre>
880 1 Adrian Georgescu
Content-Type: application/sdp
881
Content-Length:  1093
882
883
v=0
884
o=- 3467525278 3467525278 IN IP4 192.168.1.6
885
s=blink-0.10.7-beta
886
c=IN IP4 80.101.96.20
887
t=0 0
888
m=audio 55328 RTP/AVP 104 103 102 3 9 0 8 101
889
a=rtcp:55329 IN IP4 80.101.96.20
890
a=rtpmap:104 speex/32000
891
a=rtpmap:103 speex/16000
892
a=rtpmap:102 speex/8000
893
a=rtpmap:3 GSM/8000
894
a=rtpmap:9 G722/8000
895
a=rtpmap:0 PCMU/8000
896
a=rtpmap:8 PCMA/8000
897
a=rtpmap:101 telephone-event/8000
898
a=fmtp:101 0-15
899
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:esI6DbLY1+Aceu0JNswN9Z10DcFx5cZwqJcu91jb
900
a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:SHuEMm1BYJqOF4udKl73EaCwnsI57pO86bYKsg70
901
a=ice-ufrag:2701ed80
902
a=ice-pwd:6f8f8281
903
a=candidate:S 1 UDP 31 80.101.96.20 55328 typ srflx raddr 192.168.1.6 rport 55328
904
a=candidate:H 1 UDP 23 192.168.1.6 55328 typ host
905
a=candidate:H 1 UDP 23 10.211.55.2 55328 typ host
906
a=candidate:H 1 UDP 23 10.37.129.2 55328 typ host
907
a=candidate:S 2 UDP 30 80.101.96.20 55329 typ srflx raddr 192.168.1.6 rport 55329
908
a=candidate:H 2 UDP 22 192.168.1.6 55329 typ host
909
a=candidate:H 2 UDP 22 10.211.55.2 55329 typ host
910
a=candidate:H 2 UDP 22 10.37.129.2 55329 typ host
911
a=sendrecv
912 147 Adrian Georgescu
</pre>
913 1 Adrian Georgescu
914 147 Adrian Georgescu
As an implementation of @IAudioPort@, an @AudioStream@ can be added to an @AudioBridge@ to send or to read audio data to/from other audio objects. It is connected to the voice @AudioMixer@ (@SIPApplication.voice_audio_mixer@) so it can only be added to bridges using the same @AudioMixer@. It also contains an @AudioBridge@ on the @bridge@ attribute which always contains an @AudioDevice@ corresponding to the input and output devices; when the stream is active (started and not on hold), the bridge also contains the stream itself and when recording is active, the stream contains a @WaveRecorder@ which records audio data.
915 1 Adrian Georgescu
916
917 147 Adrian Georgescu
h4. methods
918 1 Adrian Georgescu
919
920
921 147 Adrian Georgescu
*start_recording*(_self_, *filename*=@None@)
922
>If an audio stream is present within this session, calling this method will record the audio to a @.wav@ file.
923
>Note that when the session is on hold, nothing will be recorded to the file.
924
>Right before starting the recording a @SIPSessionWillStartRecordingAudio@ notification will be emitted, followed by a @SIPSessionDidStartRecordingAudio@.
925
>This method may only be called while the stream is started.
926
  
927
>+_filename_+:
928 1 Adrian Georgescu
929 147 Adrian Georgescu
>The name of the @.wav@ file to record to.
930
>If this is set to @None@, a default file name including the session participants and the timestamp will be generated using the directory defined in the configuration.
931 1 Adrian Georgescu
932 147 Adrian Georgescu
*stop_recording*(_self_)
933
>This will stop a previously started recording.
934
>Before stopping, a @SIPSessionWillStopRecordingAudio@ notification will be sent, followed by a @SIPSessionDidStopRecordingAudio@.
935 1 Adrian Georgescu
936 147 Adrian Georgescu
*send_dtmf*(_self_, *digit*)
937
>If the audio stream is started, sends a DTMF digit to the remote party.
938
  
939
>+_digit_+:
940 1 Adrian Georgescu
941 147 Adrian Georgescu
>This should a string of length 1, containing a valid DTMF digit value (0-9, A-D, * or #).
942 1 Adrian Georgescu
943
944 147 Adrian Georgescu
h4. attributes
945 1 Adrian Georgescu
946
947
948 147 Adrian Georgescu
*sample_rate*
949
>If the audio stream was started, this attribute contains the sample rate of the audio negotiated.
950 1 Adrian Georgescu
951 147 Adrian Georgescu
*codec*
952
>If the audio stream was started, this attribute contains the name of the audio codec that was negotiated.
953 1 Adrian Georgescu
954 147 Adrian Georgescu
*srtp_active*
955
>If the audio stream was started, this boolean attribute indicates if SRTP is currently being used on the stream.
956 1 Adrian Georgescu
957 147 Adrian Georgescu
*ice_active*
958
  @True@ if the ICE candidates negotiated are being used, @False@ otherwise.
959 1 Adrian Georgescu
960 147 Adrian Georgescu
*local_rtp_address*
961
>If an audio stream is present within the session, this attribute contains the local IP address used for the audio stream.
962 1 Adrian Georgescu
963 147 Adrian Georgescu
*local_rtp_port*
964
>If an audio stream is present within the session, this attribute contains the local UDP port used for the audio stream.
965 1 Adrian Georgescu
966 147 Adrian Georgescu
*remote_rtp_address_sdp*
967
>If the audio stream was started, this attribute contains the IP address that the remote party gave to send audio to.
968 1 Adrian Georgescu
969 147 Adrian Georgescu
*remote_rtp_port_sdp*
970
>If the audio stream was started, this attribute contains the UDP port that the remote party gave to send audio to.
971 1 Adrian Georgescu
972 147 Adrian Georgescu
*remote_rtp_address_received*
973
>If the audio stream was started, this attribute contains the remote IP address from which the audio stream is being received.
974 1 Adrian Georgescu
975 147 Adrian Georgescu
*remote_rtp_port_received*
976
>If the audio stream was started, this attribute contains the remote UDP port from which the audio stream is being received.
977 1 Adrian Georgescu
978 147 Adrian Georgescu
*local_rtp_candidate_type*
979
>The local ICE candidate type which was selected by the ICE negotiation if it succeeded and @None@ otherwise.
980 1 Adrian Georgescu
981 147 Adrian Georgescu
*remote_rtp_candidate_type*
982
>The remote ICE candidate type which was selected by the ICE negotiation if it succeeded and @None@ otherwise.
983 1 Adrian Georgescu
984 147 Adrian Georgescu
*recording_filename*
985
>If the audio stream is currently being recorded to disk, this property contains the name of the @.wav@ file being recorded to.
986 1 Adrian Georgescu
987
988 147 Adrian Georgescu
h4. notifications
989 1 Adrian Georgescu
990
991
992 147 Adrian Georgescu
*AudioStreamDidChangeHoldState*
993
>Will be sent when the hold state is changed as a result of either a SIP message received on the network or the application calling the @hold()/unhold()@ methods on the @Session@ this stream is part of.
994
  
995
>+_timestamp_+:
996 1 Adrian Georgescu
997 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
998
  
999
originator:
1000 1 Adrian Georgescu
1001 147 Adrian Georgescu
>A string representing the party which requested the hold change, @"local"@ or @"remote"@
1002
  
1003
on_hold:
1004 1 Adrian Georgescu
1005 147 Adrian Georgescu
>A boolean indicating the new hold state from the point of view of the originator.
1006 1 Adrian Georgescu
1007 147 Adrian Georgescu
*AudioStreamWillStartRecordingAudio_
1008
>Will be sent when the application requested that the audio stream be recorded to a @.wav@ file, just before recording starts.
1009
  
1010
>+_timestamp_+:
1011
1012
>A @datetime.datetime@ object indicating when the notification was sent.
1013
  
1014
>+_filename_+:
1015
1016
>The full path to the @.wav@ file being recorded to.
1017
1018
*AudioStreamDidStartRecordingAudio*
1019
>Will be sent when the application requested that the audio stream be recorded to a @.wav@ file, just after recording started.
1020
  
1021
>+_timestamp_+:
1022
1023
>A @datetime.datetime@ object indicating when the notification was sent.
1024
  
1025
>+_filename_+:
1026
1027
>The full path to the @.wav@ file being recorded to.
1028
1029
*AudioStreamWillStopRecordingAudio*
1030
>Will be sent when the application requested ending the recording to a @.wav@ file, just before recording stops.
1031
  
1032
>+_timestamp_+:
1033
1034
>A @datetime.datetime@ object indicating when the notification was sent.
1035
  
1036
>+_filename_+:
1037
1038
>The full path to the @.wav@ file being recorded to.
1039
1040
*AudioStreamDidStopRecordingAudio*
1041
>Will be sent when the application requested ending the recording to a @.wav@ file, just after recording stoped.
1042
  
1043
>+_timestamp_+:
1044
1045
>A @datetime.datetime@ object indicating when the notification was sent.
1046
  
1047
>+_filename_+:
1048
1049
>The full path to the @.wav@ file being recorded to.
1050
1051
*AudioStreamDidChangeRTPParameters*
1052
>This notification is sent when the RTP parameters are changed, such as codec, sample rate, RTP port etc.
1053
  
1054
>+_timestamp_+:
1055
1056
>A @datetime.datetime@ object indicating when the notification was sent.
1057
1058
*AudioStreamGotDTMF*
1059
>Will be send if there is a DMTF digit received from the remote party on the audio stream. 
1060
  
1061
>+_timestamp_+:
1062
1063
>A @datetime.datetime@ object indicating when the notification was sent.
1064
  
1065
>+_digit_+:
1066
1067
>The DTMF digit that was received, in the form of a string of length 1.
1068
1069
*AudioStreamICENegotiationStateDidChange*
1070
>This notification is proxied from the @RTPTransport@ and as such has the same data as the @RTPTransportICENegotiationStateDidChange@.
1071
1072
*AudioStreamICENegotiationDidSucceed*
1073
>This notification is proxied from the @RTPTransport@ and as such has the same data as the @RTPTransportICENegotiationDidSucceed@.
1074
1075
*AudioStreamICENegotiationDidFail*
1076
>This notification is proxied from the @RTPTransport@ and as such has the same data as the @RTPTransportICENegotiationDidFail@.
1077
1078
*AudioStreamDidTimeout*
1079
>This notification is proxied from the @RTPTransport@. It's sent when the RTP transport did not receive any data after the specified amount of time (rtp.timeout setting in the @Account@).
1080
1081
1082
h3. MSRPStreamBase
1083
1084
1085 1 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
1086
1087 147 Adrian Georgescu
The @MSRPStreamBase@ is used as a base class for streams using the MSRP protocol. Within the SIP SIMPLE middleware, this hold for the @ChatStream@, @FileTransferStream@ and @DesktopSharingStream@ classes, however the application can also make use of this class to implement some other streams based on the MSRP protocol as a transport.
1088 1 Adrian Georgescu
1089 147 Adrian Georgescu
1090
h4. methods
1091
1092 1 Adrian Georgescu
 
1093 147 Adrian Georgescu
Of the methods defined by the @IMediaStream@ interface, only the @new_from_sdp@ method is not implemented in this base class and needs to be provided by the subclasses. Also, the subclasses can defined methods of the form @_handle_XXX@, where XXX is a MSRP method name in order to handle incoming MSRP requests. Also, since this class registers as an observer for itself, it will receive the notifications it sends so subclasses can define methods having the signature @_NH_<notification name>(self, notification)@ as used throughout the middleware in order to do various things at the different points within the life-cycle of the stream.
1094 1 Adrian Georgescu
1095
1096 147 Adrian Georgescu
h4. attributes
1097 1 Adrian Georgescu
1098
1099 147 Adrian Georgescu
The attributes defined in the @IMediaStream@ interface which are not provided by this class are:
1100
* type
1101
* priority
1102 1 Adrian Georgescu
1103 147 Adrian Georgescu
In addition, the following attributes need to be defined in the subclass in order for the @MSRPStreamBase@ class to take the correct decisions
1104 1 Adrian Georgescu
1105 147 Adrian Georgescu
*media_type*
1106
>The media type as included in the SDP (eg. @"message"@, @"application"@).
1107 1 Adrian Georgescu
1108 147 Adrian Georgescu
*accept_types*
1109
>A list of the MIME types which should be accepted by the stream (this is also sent within the SDP).
1110 1 Adrian Georgescu
1111 147 Adrian Georgescu
*accept_wrapped_types*
1112
>A list of the MIME types which should be accepted by the stream while wrapped in a @message/cpim@ envelope.
1113 1 Adrian Georgescu
1114 147 Adrian Georgescu
*use_msrp_session*
1115
>A boolean indicating whether or not an @MSRPSession@ should be used.
1116 1 Adrian Georgescu
1117
1118 147 Adrian Georgescu
h4. notifications
1119 1 Adrian Georgescu
1120
1121 147 Adrian Georgescu
While not technically notifications of @MSRPStreamBase@, these notifications are sent from the middleware on behalf of the @MSRPTransport@ used by a stream in the former case, and anonymously in the latter.
1122 1 Adrian Georgescu
1123 147 Adrian Georgescu
1124
*MSRPTransportTrace*
1125
>This notification is sent when an MSRP message is received for logging purposes.
1126
  
1127
timestamp:
1128
1129
>A @datetime.datetime@ object indicating when the notification was sent.
1130
  
1131
direction:
1132
1133
>The direction of the message, @"incoming"@ or @"outgoing"@.
1134
  
1135
data:
1136
1137
>The MSRP message as a string.
1138
1139
*MSRPLibraryLog*
1140
>This notification is sent anonymously whenever the MSRP library needs to log any information.
1141
  
1142
timestamp:
1143
1144
>A @datetime.datetime@ object indicating when the notification was sent.
1145
  
1146
message:
1147
1148
>The log message as a string.
1149
  
1150
level:
1151
1152
>The log level at which the message was written. One of the levels @DEBUG@, @INFO@, @WARNING@, @ERROR@, @CRITICAL@ from the @application.log.level@ object which is part of the @python-application@ library.
1153
1154
1155
h3. ChatStream
1156
1157
1158 1 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
1159
1160 147 Adrian Georgescu
@sipsimple.streams.msrp.ChatStream@ implements session-based Instant Messaging (IM) over MSRP. This class performs the following functions:
1161 1 Adrian Georgescu
1162 147 Adrian Georgescu
* automatically wraps outgoing messages with Message/CPIM if that's necessary according to accept-types
1163
* unwraps incoming Message/CPIM messages; for each incoming message, the @ChatStreamGotMessage@ notification is posted
1164
* composes iscomposing payloads and reacts to those received by sending the @ChatStreamGotComposingIndication@ notification
1165 1 Adrian Georgescu
1166
An example of an SDP created using this class follows:
1167
1168 147 Adrian Georgescu
<pre>
1169 1 Adrian Georgescu
Content-Type: application/sdp
1170
Content-Length:   283
1171
1172
v=0
1173
o=- 3467525214 3467525214 IN IP4 192.168.1.6
1174
s=blink-0.10.7-beta
1175
c=IN IP4 192.168.1.6
1176
t=0 0
1177
m=message 2855 TCP/TLS/MSRP *
1178
a=path:msrps://192.168.1.6:2855/ca7940f12ddef14c3c32;tcp
1179
a=accept-types:message/cpim text/* application/im-iscomposing+xml
1180
a=accept-wrapped-types:*
1181 147 Adrian Georgescu
</pre>
1182 1 Adrian Georgescu
1183
1184 147 Adrian Georgescu
h4. methods
1185 1 Adrian Georgescu
1186
1187
1188 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *account*, *direction*=@'sendrecv'@)
1189
>Initializes the ChatStream instance.
1190 1 Adrian Georgescu
1191 147 Adrian Georgescu
1192
*send_message*(_self_, *content*, *content_type*=@'text/plain'@, *recipients*=@None@, *courtesy_recipients*=@None@, *subject*=@None@, _timestamp_=@None@, *required*=@None@, *additional_headers*=@None@)
1193
>Sends an IM message. Prefer Message/CPIM wrapper if it is supported. If called before the connection was established, the messages will be
1194
>queued until the stream starts.
1195
>Returns the generated MSRP message ID.
1196
  
1197
content:
1198
1199
>The content of the message.
1200
  
1201
content_type:
1202
1203
>Content-Type of wrapped message if Message/CPIM is used (Content-Type of MSRP message is always Message/CPIM in that case);
1204
>otherwise, Content-Type of MSRP message.
1205
  
1206
recipients:
1207
1208
>The list of @CPIMIdentity@ objects which will be used for the @To@ header of the CPIM wrapper. Used to override the default which depends on the remote identity.
1209
>May only differ from the default one if the remote party supports private messages. If it does not, a @ChatStreamError@ will be raised.
1210
  
1211
courtesy_recipients:
1212
1213
>The list of @CPIMIdentity@ objects which will be used for the @cc@ header of the CPIM wrapper.
1214
>May only be specified if the remote party supports private messages and CPIM is supported. If it does not, a @ChatStreamError@ will be raised.
1215
  
1216
subject:
1217
1218
>A string or @MultilingualText@ which specifies the subject and its translations to be added to the CPIM message. If CPIM is not supported, a @ChatStreamError@ will be raised.
1219
  
1220
required:
1221
1222
>A list of strings describing the required capabilities that the other endpoint must support in order to understand this CPIM message. If CPIM is not supported, a @ChatStreamError@ will be raised.
1223
  
1224
additional_headers:
1225
1226
>A list of MSRP header objects which will be added to this CPIM message. If CPIM is not supported, a @ChatStreamError@ will be raised.
1227
  
1228
timestamp:
1229
1230
>A @datetime.datetime@ object representing the timestamp to put on the CPIM wrapper of the message.
1231
>When set to @None@, a default one representing the current moment will be added.
1232
1233 1 Adrian Georgescu
 These MSRP headers are used to enable end-to-end success reports and to disable hop-to-hop successful responses:
1234 147 Adrian Georgescu
<pre>
1235 1 Adrian Georgescu
Failure-Report: partial
1236
Success-Report: yes
1237 147 Adrian Georgescu
</pre>
1238 1 Adrian Georgescu
1239
1240 147 Adrian Georgescu
*send_composing_indication*(_self_, _state_, _refresh_, _last_active=None_, _recipients=None_)
1241
>Sends an is-composing message to the listed recipients.
1242
  
1243
state:
1244 1 Adrian Georgescu
1245 147 Adrian Georgescu
>The state of the endpoint, @"active"@ or @"idle"@.
1246
  
1247
refresh:
1248 1 Adrian Georgescu
1249 147 Adrian Georgescu
>How often the local endpoint will send is-composing indications to keep the state from being reverted to @"idle"@.
1250
  
1251
last_active:
1252 1 Adrian Georgescu
1253 147 Adrian Georgescu
>A @datatime.datetime@ object representing the moment when the local endpoint was last active.
1254
  
1255
recipients:
1256 1 Adrian Georgescu
1257 147 Adrian Georgescu
>The list of @CPIMIdentity@ objects which will be used for the @To@ header of the CPIM wrapper. Used to override the default which depends on the remote identity.
1258
>May only differ from the default one if the remote party supports private messages. If it does not, a @ChatStreamError@ will be raised.
1259 1 Adrian Georgescu
1260
1261 147 Adrian Georgescu
h4. notifications
1262 1 Adrian Georgescu
1263
1264
1265 147 Adrian Georgescu
*ChatStreamGotMessage*
1266
>Sent whenever a new incoming message is received,
1267
  
1268
timestamp:
1269 1 Adrian Georgescu
1270 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
1271
  
1272
message:
1273 1 Adrian Georgescu
1274 147 Adrian Georgescu
>A @ChatMessage@ or @CPIMMessage@ instance, depending on whether a CPIM message was received or not.
1275 1 Adrian Georgescu
1276 147 Adrian Georgescu
*ChatStreamDidDeliverMessage*
1277
>Sent when a successful report is received.
1278
  
1279
timestamp:
1280 1 Adrian Georgescu
1281 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
1282
  
1283
message_id:
1284 1 Adrian Georgescu
1285 147 Adrian Georgescu
>Text identifier of the message.
1286
  
1287
code:
1288 1 Adrian Georgescu
1289 147 Adrian Georgescu
>The status code received. Will always be 200 for this notification.
1290
  
1291
reason:
1292 1 Adrian Georgescu
1293 147 Adrian Georgescu
>The status reason received.
1294
  
1295
chunk:
1296 1 Adrian Georgescu
1297 147 Adrian Georgescu
>A @msrplib.protocol.MSRPData@ instance providing all the MSRP information about the report.
1298 1 Adrian Georgescu
1299 147 Adrian Georgescu
*ChatStreamDidNotDeliverMessage*
1300
>Sent when a failure report is received.
1301
  
1302
timestamp:
1303 1 Adrian Georgescu
1304 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
1305
  
1306
message_id:
1307 1 Adrian Georgescu
1308 147 Adrian Georgescu
>Text identifier of the message.
1309
  
1310
code:
1311
1312
>The status code received.
1313
  
1314
reason:
1315
1316
>The status reason received.
1317
  
1318
chunk:
1319
1320
>A @msrplib.protocol.MSRPData@ instance providing all the MSRP information about the report.
1321
1322
*ChatStreamDidSendMessage*
1323
>Sent when an outgoing message has been sent.
1324
  
1325
timestamp:
1326
1327
>A @datetime.datetime@ object indicating when the notification was sent.
1328
  
1329
message:
1330
1331
>A @msrplib.protocol.MSRPData@ instance providing all the MSRP information about the sent message.
1332
1333
*ChatStreamGotComposingIndication*
1334
>Sent when a is-composing payload is received.
1335
  
1336
timestamp:
1337
1338
>A @datetime.datetime@ object indicating when the notification was sent.
1339
  
1340
state:
1341
1342
>The state of the endpoint, @"active"@ or @"idle"@.
1343
  
1344
refresh:
1345
1346
>How often the remote endpoint will send is-composing indications to keep the state from being reverted to @"idle"@. May be @None@.
1347
  
1348
last_active:
1349
1350
>A @datatime.datetime@ object representing the moment when the remote endpoint was last active. May be @None@.
1351
  
1352
content_type:
1353
1354
>The MIME type of message being composed. May be @None@.
1355
  
1356
sender:
1357
1358
>The @ChatIdentity@ or @CPIMIdentity@ instance which identifies the sender of the is-composing indication.
1359
  
1360
recipients:
1361
1362
>The @ChatIdentity@ or @CPIMIdentity@ instances list which identifies the recipients of the is-composing indication.
1363
1364
1365
h3. FileSelector
1366
1367
1368
The @FileSelector@ is used to contain information about a file tranfer using the @FileTransferStream@ documented below.
1369
1370
1371
h4. methods
1372
1373
1374
1375
*<notextile>__init__</notextile>*(_self_, *name*=@None@, *type*=@None@, *size*=@None@, *hash*=@None@, *fd*=@None@)
1376
>Instantiate a new @FileSelector@. All the arguments are also available as attributes.
1377
  
1378
name:
1379
1380
>The filename (should be just the base name).
1381
  
1382
type:
1383
1384
>The type of the file.
1385
  
1386
size:
1387
1388
>The size of the file in bytes.
1389
  
1390
hash:
1391
1392
>The hash of the file in the following format: @hash:sha-1:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX@, where @X@ is a hexadecimal digit. Currently, only SHA1 hashes are supported according to the RFC.
1393
  
1394
fd:
1395
1396
>A file descriptor if the application has already opened the file.
1397
1398
*parse*(_cls_, *string*)
1399
>Parses a file selector from the SDP @file-selector@ a attribute and returns a @FileSelector@ instance.
1400
1401
*for_file*(_cls_, *path*, *content_type*, *compute_hash*=@True@)
1402
>Returns a @FileSelector@ instance for the specified file. The file identified by the path must exist. Note that if @compute_hash@ is @True@ this method will block while the hash is computed, a potentially long operation for large files.
1403
  
1404
path:
1405
1406
>The full path to the file.
1407
  
1408
content_type:
1409
1410
>An optional MIME type which is to be included in the file-selector.
1411
  
1412
compute_hash:
1413
1414
>Whether or not this method should compute the hash of the file.
1415
1416
*compute_hash*(_self_)
1417
>Compute the hash for this file selector. This method will block while the hash is computed, a potentially long operation for large files. 
1418
1419
1420
h4. attributes
1421
1422
1423
1424
*sdp_repr*
1425
>The SDP representation of the file-selector according to the RFC. This should be the value of the @file-selector@ SDP attribute.
1426
1427
1428
h3. FileTransferStream
1429
1430
1431 1 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
1432
1433 147 Adrian Georgescu
The @FileTransferStream@ supports file transfer over MSRP according to RFC5547. An example of SDP constructed using this stream follows:
1434 1 Adrian Georgescu
1435 147 Adrian Georgescu
<pre>
1436 1 Adrian Georgescu
Content-Type: application/sdp
1437
Content-Length:   383
1438
1439
v=0
1440
o=- 3467525166 3467525166 IN IP4 192.168.1.6
1441
s=blink-0.10.7-beta
1442
c=IN IP4 192.168.1.6
1443
t=0 0
1444
m=message 2855 TCP/TLS/MSRP *
1445
a=path:msrps://192.168.1.6:2855/e593357dc9abe90754bd;tcp
1446
a=sendonly
1447
a=accept-types:*
1448
a=accept-wrapped-types:*
1449
a=file-selector:name:"reblink.pdf" type:com.adobe.pdf size:268759 hash:sha1:60:A1:BE:8D:71:DB:E3:8E:84:C9:2C:62:9E:F2:99:78:9D:68:79:F6
1450 147 Adrian Georgescu
</pre>
1451 1 Adrian Georgescu
1452
1453 147 Adrian Georgescu
h4. methods
1454 1 Adrian Georgescu
1455
1456
1457 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *account*, *file_selector*=@None@)
1458
>Instantiate a new @FileTransferStream@. If this is constructed by the application for an outgoing file transfer, the @file_selector@ argument must be present.
1459
  
1460
account:
1461 1 Adrian Georgescu
1462 147 Adrian Georgescu
>The @sipsimple.account.Account@ or @sipsimple.account.BonjourAccount@ instance which will be associated with the stream.
1463
  
1464
file_selector:
1465 1 Adrian Georgescu
1466 147 Adrian Georgescu
>The @FileSelector@ instance which represents the file which is to be transferred.
1467 1 Adrian Georgescu
1468
1469 147 Adrian Georgescu
h4. notifications
1470 1 Adrian Georgescu
1471
1472
1473 147 Adrian Georgescu
*FileTransferStreamDidDeliverChunk*
1474
>This notification is sent for an outgoing file transfer when a success report is received about part of the file being transferred.
1475
  
1476
timestamp:
1477 1 Adrian Georgescu
1478 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
1479
  
1480
message_id:
1481
1482
>The MSRP message ID of the file transfer session.
1483
  
1484
chunk:
1485
1486
>An @msrplib.protocol.MSRPData@ instance represented the received REPORT.
1487
  
1488
code:
1489
1490
>The status code received. Will always be 200 for this notification.
1491
  
1492
reason:
1493
1494
>The status reason received.
1495
  
1496
transferred_bytes:
1497
1498
>The number of bytes which have currently been successfully transferred.
1499
  
1500
file_size:
1501
1502
>The size of the file being transferred.
1503
1504
*FileTransferStreamDidNotDeliverChunk*
1505
  
1506
timestamp:
1507
1508
>A @datetime.datetime@ object indicating when the notification was sent.
1509
>This notification is sent for an outgoing file transfer when a failure report is received about part of the file being transferred.
1510
  
1511
message_id:
1512
1513
>The MSRP message ID of the file transfer session.
1514
  
1515
chunk:
1516
1517
>An @msrplib.protocol.MSRPData@ instance represented the received REPORT.
1518
  
1519
code:
1520
1521
>The status code received.
1522
  
1523
reason:
1524
1525
>The status reason received.
1526
1527
*FileTransferStreamDidFinish*
1528
>This notification is sent when the incoming or outgoing file transfer is finished.
1529
  
1530
timestamp:
1531
1532
>A @datetime.datetime@ object indicating when the notification was sent.
1533
1534
*FileTransferStreamGotChunk*
1535
>This notificaiton is sent for an incoming file transfer when a chunk of file data is received.
1536
  
1537
timestamp:
1538
1539
>A @datetime.datetime@ object indicating when the notification was sent.
1540
  
1541
content:
1542
1543
>The file part which was received, as a @str@.
1544
  
1545
content_type:
1546
1547
>The MIME type of the file which is being transferred.
1548
  
1549
transferred_bytes:
1550
1551
>The number of bytes which have currently been successfully transferred.
1552
  
1553
file_size:
1554
1555
>The size of the file being transferred.
1556
1557
1558
1559
h3. IDesktopSharingHandler
1560
1561
1562
This interface is used to describe the interface between a @IDesktopSharingHandler@, which is responsible for consuming and producing RFB data, and the @DesktopSharingStream@ which is responsible for transporting the RFB data over MSRP. The middleware provides four implementations of this interface:
1563
* InternalVNCViewerHandler
1564
* InternalVNCServerHandler
1565
* ExternalVNCViewerHandler
1566
* ExternalVNCServerHandler
1567
1568
1569
h4. methods
1570
1571 1 Adrian Georgescu
 
1572 72 Luci Stanescu
1573 147 Adrian Georgescu
*initialize*(_self_, *stream*)
1574
>This method will be called by the @DesktopSharingStream@ when the stream has been started and RFB data can be transported. The stream has two attributes which are relevant to the @IDesktopSharingHandler@: incoming_queue and outgoing_queue. These attributes are @eventlet.coros.queue@ instances which are used to transport RFB data between the stream and the handler.
1575 72 Luci Stanescu
1576 1 Adrian Georgescu
1577 147 Adrian Georgescu
h4. attributes
1578 1 Adrian Georgescu
1579
1580
1581 147 Adrian Georgescu
*type*
1582
  @"active"@ or @"passive"@ depending on whether the handler represents a VNC viewer or server respectively.
1583 1 Adrian Georgescu
1584 94 Adrian Georgescu
1585 147 Adrian Georgescu
h4. notifications
1586 1 Adrian Georgescu
1587
1588
1589 147 Adrian Georgescu
*DesktopSharingHandlerDidFail*
1590
>This notification must be sent by the handler when an error occurs to notify the stream that it should fail.
1591
  
1592
context:
1593 72 Luci Stanescu
1594 147 Adrian Georgescu
>A string describing when the handler failed, such as @"reading"@, @"sending"@ or @"connecting"@.
1595
  
1596
failure:
1597 72 Luci Stanescu
1598 147 Adrian Georgescu
>A @twisted.python.failure.Failure@ instance describing the exception which led to the failure.
1599
  
1600
reason:
1601 1 Adrian Georgescu
1602 147 Adrian Georgescu
>A string describing the failure reason.
1603 1 Adrian Georgescu
1604
1605 147 Adrian Georgescu
h3. InternalVNCViewerHandler
1606 1 Adrian Georgescu
1607
1608 147 Adrian Georgescu
This is a concrete implementation of the @IDesktopSharingHandler@ interface which can be used for a VNC viewer implemented within the application.
1609 1 Adrian Georgescu
1610
1611 147 Adrian Georgescu
h4. methods
1612 1 Adrian Georgescu
1613
1614
1615 147 Adrian Georgescu
*send*(_self_, *data*)
1616
>Sends the specified data to the stream in order for it to be transported over MSRP to the remote endpoint.
1617
  
1618
data:
1619 1 Adrian Georgescu
1620 147 Adrian Georgescu
>The RFB data to be transported over MSRP, in the form of a @str@.
1621 1 Adrian Georgescu
1622
1623 147 Adrian Georgescu
h4. notifications
1624 1 Adrian Georgescu
1625
1626
1627 147 Adrian Georgescu
*DesktopSharingStreamGotData*
1628
>This notification is sent when data is received over MSRP.
1629
  
1630
data:
1631 1 Adrian Georgescu
1632 147 Adrian Georgescu
>The RFB data from the remote endpoint, in the form of a @str@.
1633 1 Adrian Georgescu
1634
1635 147 Adrian Georgescu
h3. InternalVNCServerHandler
1636 1 Adrian Georgescu
1637
1638 147 Adrian Georgescu
This is a concrete implementation of the @IDesktopSharingHandler@ interface which can be used for a VNC server implemented within the application.
1639 1 Adrian Georgescu
1640
1641 147 Adrian Georgescu
h4. methods
1642 1 Adrian Georgescu
1643
1644
1645 147 Adrian Georgescu
*send*(_self_, *data*)
1646
>Sends the specified data to the stream in order for it to be transported over MSRP to the remote endpoint.
1647
  
1648
data:
1649
1650
>The RFB data to be transported over MSRP, in the form of a @str@.
1651
1652
1653
h4. notifications
1654
1655
1656
1657
*DesktopSharingStreamGotData*
1658
>This notification is sent when data is received over MSRP.
1659
  
1660
data:
1661
1662
>The RFB data from the remote endpoint, in the form of a @str@.
1663
1664
1665
h3. ExternalVNCViewerHandler
1666
1667
1668
This implementation of @IDesktopSharingHandler@ can be used for an external VNC viewer which connects to a VNC server using TCP.
1669
1670
1671
h4. methods
1672
1673
1674
1675
*<notextile>__init__</notextile>*(_self_, *address*=@("localhost", 0)@, *connect_timeout*=@3@)
1676
>This instantiates a new @ExternalVNCViewerHandler@ which is listening on the provided address, ready for the external VNC viewer to connect to it via TCP. After this method returns, the attribute @address@ can be used to find out exactly on what address and port the handler is listening on. The handler will only accept one conenction on this address.
1677
  
1678
address:
1679
1680
>A tuple containing an IP address/hostname and a port on which the handler should listen. Any data received on this socket will then be forwarded to the stream and any data received from the stream will be forwarded to this socket.
1681
1682
1683
h4. attributes
1684
1685
1686
1687
*address*
1688
>A tuple containing an IP address and a port on which the handler is listening.
1689
1690
1691
h3. ExternalVNCServerHandler
1692
1693
1694
This implementation of @IDesktopSharingHandler@ can be used for an external VNC server to which handler will connect using TCP.
1695
1696
1697
h4. methods
1698
1699
1700
1701
*<notextile>__init__</notextile>*(_self_, *address*, *connect_timeout*=@3@)
1702
>This instantiates a new @ExternalVNCServerHandler@ which will connect to the provided address on which a VNC server must be listening before the stream using this handler starts.
1703
  
1704
address:
1705
1706
>A tuple containing an IP address/hostname and a port on which the VNC server will be listening. Any data received on this socket will then be forwared to the stream and any data received form the stream will be forwarded to this socket.
1707
  
1708
connect_timeout:
1709
1710
>How long to wait to connect to the VNC server before giving up.
1711
1712
1713
1714
h3. DesktopSharingStream
1715
1716
1717 1 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
1718
1719
This stream implements desktop sharing using MSRP as a transport protocol for RFB data.
1720
1721 147 Adrian Georgescu
There is no standard defining this usage but is fairly easy to implement in clients that already support MSRP. To traverse a NAT-ed router, a "MSRP relay":http://msrprelay.org configured for the called party domain is needed. Below is an example of the Session Description Protocol used for establishing a Desktop sharing session:
1722 1 Adrian Georgescu
1723 147 Adrian Georgescu
<pre>
1724 1 Adrian Georgescu
m=application 2855 TCP/TLS/MSRP *
1725
a=path:msrps://10.0.1.19:2855/b599b22d1b1d6a3324c8;tcp
1726
a=accept-types:application/x-rfb
1727
a=rfbsetup:active
1728 147 Adrian Georgescu
</pre>
1729 1 Adrian Georgescu
1730
1731
1732 147 Adrian Georgescu
h4. methods
1733 1 Adrian Georgescu
1734
1735
1736 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *acount*, *handler*)
1737
>Instantiate a new @DesktopSharingStream@.
1738
  
1739
account:
1740 1 Adrian Georgescu
1741 147 Adrian Georgescu
>The @sipsimple.account.Account@ or @sipsimple.account.BonjourAccount@ instance this stream is associated with.
1742
  
1743
handler:
1744 1 Adrian Georgescu
1745 147 Adrian Georgescu
>An object implementing the @IDesktopSharingHandler@ interface which will act as the handler for RFB data.
1746 1 Adrian Georgescu
1747
1748 147 Adrian Georgescu
h4. attributes
1749 1 Adrian Georgescu
1750
1751
1752 147 Adrian Georgescu
*handler*
1753
>This is a writable property which can be used to get or set the object implementing @IDesktopSharingHandler@ which acts as the handler for RFB data. For incoming @DesktopSharingStreams@, this must be set by the application before the stream starts.
1754 1 Adrian Georgescu
1755 147 Adrian Georgescu
*incoming_queue*
1756
>A @eventlet.coros.queue@ instance on which incoming RFB data is written. The handler should wait for data on this queue.
1757 1 Adrian Georgescu
1758 147 Adrian Georgescu
*outgoing_queue*
1759
>A @eventlet.coros.queue@ instance on which outgoing RFB data is written. The handler should write data on this queue.
1760 1 Adrian Georgescu
1761
1762 147 Adrian Georgescu
h3. ConferenceHandler
1763 1 Adrian Georgescu
1764
1765 147 Adrian Georgescu
This class is internal to the @Session@ and provied the user with the ability to invite participants to a conference hosted by the remote endpoint.
1766 1 Adrian Georgescu
1767 147 Adrian Georgescu
Adding and removing participants is performed using a @REFER@ request as explained in RFC 4579, section 5.5.
1768 1 Adrian Georgescu
1769 147 Adrian Georgescu
In addition, the @ConferenceHandler@ will subscribe to the @conference@ event in order to get information about participants in the conference.
1770 1 Adrian Georgescu
1771
1772 147 Adrian Georgescu
h4. methods
1773 1 Adrian Georgescu
1774
1775 147 Adrian Georgescu
*add_participant*(_self_, *participant_uri*)
1776
>Send a @REFER@ request telling the server to invite the participant specified in @participant_uri@ to join the ongoing conference.
1777 1 Adrian Georgescu
1778 147 Adrian Georgescu
*remove_participant*(_self_, *participant_uri*)
1779
>Send a @REFER@ request telling the server to remove the participant specified in @participant_uri@ from the ongoing conference.
1780 1 Adrian Georgescu
1781
1782 147 Adrian Georgescu
h4. notifications
1783
1784
1785
 All notifications are sent with the @Session@ object as the sender.
1786
1787
*SIPSessionGotConferenceInfo*
1788
>This notification is sent when a @NOTIFY@ is received with a valid conferene payload.
1789
  
1790
timestamp:
1791
1792
>A @datetime.datetime@ object indicating when the notification was sent.
1793
  
1794
conference_info:
1795
1796
>The @Conference@ payload object.
1797
1798
*SIPConferenceDidAddParticipant*
1799
>This notification is sent when a participant was successfully added to the conference.
1800
  
1801
timestamp:
1802
1803
>A @datetime.datetime@ object indicating when the notification was sent.
1804
  
1805
participant:
1806
1807
>URI of the participant added to the conference.
1808
1809
*SIPConferenceDidNotAddParticipant*
1810
>This notification is sent when a participant could not be added to the conference.
1811
  
1812
timestamp:
1813
1814
>A @datetime.datetime@ object indicating when the notification was sent.
1815
  
1816
participant:
1817
1818
>URI of the participant added to the conference.
1819
  
1820
code:
1821
1822
>SIP response code for the failure.
1823
  
1824
reason:
1825
1826
>Reason for the failure.
1827
1828
*SIPConferenceDidRemoveParticipant*
1829
>This notification is sent when a participant was successfully removed from the conference.
1830
  
1831
timestamp:
1832
1833
>A @datetime.datetime@ object indicating when the notification was sent.
1834
  
1835
participant:
1836
1837
>URI of the participant removed from the conference.
1838
1839
*SIPConferenceDidNotRemoveParticipant*
1840
>This notification is sent when a participant could not be removed from the conference.
1841
  
1842
timestamp:
1843
1844
>A @datetime.datetime@ object indicating when the notification was sent.
1845
  
1846
participant:
1847
1848
>URI of the participant removed from the conference.
1849
  
1850
code:
1851
1852
>SIP response code for the failure.
1853
  
1854
reason:
1855
1856
>Reason for the failure.
1857
1858
*SIPConferenceGotAddParticipantProgress*
1859
>This notification is sent when a @NOTIFY@ is received indicating the status of the add participant operation.
1860
  
1861
timestamp:
1862
1863
>A @datetime.datetime@ object indicating when the notification was sent.
1864
  
1865
participant:
1866
1867
>URI of the participant whose operation is in progress.
1868
  
1869
code:
1870
1871
>SIP response code for progress.
1872
  
1873
reason:
1874
1875
>Reason associated with the response code.
1876
1877
*SIPConferenceGotRemoveParticipantProgress*
1878
>This notification is sent when a @NOTIFY@ is received indicating the status of the remove participant operation.
1879
  
1880
timestamp:
1881
1882
>A @datetime.datetime@ object indicating when the notification was sent.
1883
  
1884
participant:
1885
1886
>URI of the participant whose operation is in progress.
1887
  
1888
code:
1889
1890
>SIP response code for progress.
1891
  
1892
reason:
1893
1894
>Reason associated with the response code.
1895
1896
1897
h2. Address Resolution
1898
1899
1900
The SIP SIMPLE middleware offers the @sipsimple.lookup@ module which contains an implementation for doing DNS lookups for SIP proxies, MSRP relays, STUN servers and XCAP servers. The interface offers both an asynchronous and synchronous interface. The asynchronous interface is based on notifications, while the synchronous one on green threads. In order to call the methods in a asynchronous manner, you just need to call the method and wait for the notification which is sent on behalf of the DNSLookup instance. The notifications sent by the DNSLookup object are DNSLookupDidSucceed and DNSLookupDidFail. In order to call the methods in a synchronous manner, you need to call the wait method on the object returned by the methods of DNSLookup. This wait method needs to be called from a green thread and will either return the result of the lookup or raise an exception.
1901
1902 1 Adrian Georgescu
The DNSLookup object uses DNSManager, an object that will use the system nameservers and it will fallback to Google's nameservers (8.8.8.8 and 8.8.4.4) in case of failure. 
1903
1904
1905 147 Adrian Georgescu
h3. DNS Manager
1906 1 Adrian Georgescu
1907
1908 147 Adrian Georgescu
This object provides @DNSLookup@ with the nameserver list that will be used to perform DNS lookups. It will probe the system local nameservers and check if they are able to do proper lookups (by querying sip2sip.info domain). If the local nameservers are not able to do proper lookups Google nameservers will be used and another probing operation will be scheduled. Local nameservers are always preferred.
1909 1 Adrian Georgescu
1910 122 Adrian Georgescu
1911 147 Adrian Georgescu
h4. methods
1912 122 Adrian Georgescu
1913 121 Adrian Georgescu
1914 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_)
1915
>Instantiate the DNSManager object (it's a Singleton).
1916 121 Adrian Georgescu
1917 147 Adrian Georgescu
*start*(_self_)
1918
>Start the DNSManager. It will start the probing process to determine the suitable nameservers to use.
1919 1 Adrian Georgescu
1920 147 Adrian Georgescu
*stop*(_self_)
1921
>Stop the DNS resolution probing.
1922 1 Adrian Georgescu
1923 112 Luci Stanescu
1924 1 Adrian Georgescu
1925 147 Adrian Georgescu
h4. notifications
1926
1927
1928
*DNSResolverDidInitialize*
1929
>This notification is sent when the nameservers to use for probing (and further DNS lookups) have been set for the first time.
1930
  
1931
timestamp:
1932
1933
>A @datetime.datetime@ object indicating when the notification was sent.
1934
  
1935
nameservers:
1936
1937
>The list of nameservers that was set on the DNS Manager.
1938
1939
*DNSNameserversDidChange*
1940
>This notification is sent when the nameservers to use for probing (and further DNS lookups) have changed as a result of the probing process.
1941
  
1942
timestamp:
1943
1944
>A @datetime.datetime@ object indicating when the notification was sent.
1945
  
1946
nameservers:
1947
1948
>The list of nameservers that was set on the DNS Manager.
1949
1950
1951
1952
h3. DNS Lookup
1953
1954
1955 1 Adrian Georgescu
This object implements DNS lookup support for SIP proxies according to RFC3263 and MSRP relay and STUN server lookup using SRV records. The object initially does NS record queries in order to determine the authoritative nameservers for the domain requested; these authoritative nameservers will then be used for NAPTR, SRV and A record queries. If this fails, the locally configured nameservers are used. The reason for doing this is that some home routers have broken NAPTR and/or SRV query support.
1956
1957
1958 147 Adrian Georgescu
h4. methods
1959 1 Adrian Georgescu
1960
1961 127 Adrian Georgescu
1962 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_)
1963
>Instantiate a new DNSLookup object.
1964 129 Adrian Georgescu
1965 147 Adrian Georgescu
*lookup_service*(_self_, *uri*, *service*, *timeout*=@3.0@, *lifetime*=@15.0@)
1966
>Perform an SRV lookup followed by A lookups for MSRP relays or STUN servers depending on the @service@ parameter. If SRV queries on the @uri.host@ domain fail, an A lookup is performed on it and the default port for the service is returned. Only the @uri.host@ attribute is used. The return value is a list of (host, port) tuples.
1967
  
1968
uri:
1969 127 Adrian Georgescu
1970 147 Adrian Georgescu
>A @(Frozen)SIPURI@ from which the @host@ attribute is used for the query domain.
1971
  
1972
service:
1973 1 Adrian Georgescu
1974 147 Adrian Georgescu
>The service to lookup servers for, @"msrprelay"@ or @"stun"@.
1975
  
1976
timeout:
1977 129 Adrian Georgescu
1978 147 Adrian Georgescu
>How many seconds to wait for a response from a nameserver.
1979
  
1980
lifetime:
1981 129 Adrian Georgescu
1982 147 Adrian Georgescu
>How many seconds to wait for a response from all nameservers in total.
1983 1 Adrian Georgescu
1984 147 Adrian Georgescu
*lookup_sip_proxy*(_self_, *uri*, *supported_transports*, *timeout*=@3.0@, *lifetime*=@15.0@)
1985
>Perform a RFC3263 compliant DNS lookup for a SIP proxy using the URI which is considered to point to a host if either the @host@ attribute is an IP address, or the @port@ is present. Otherwise, it is considered a domain for which NAPTR, SRV and A lookups are performed. If NAPTR or SRV queries fail, they fallback to using SRV and A queries. If the transport parameter is present in the URI, this will be used as far as it is part of the supported transports. If the URI has a @sips@ schema, then only the TLS transport will be used as far as it doesn't conflict with the supported transports or the transport parameter. The return value is a list of @Route@ objects containing the IP address, port and transport to use for routing in the order of preference given by the supported_transports argument.
1986
  
1987
uri:
1988 129 Adrian Georgescu
1989 147 Adrian Georgescu
>A @(Frozen)SIPURI@ from which the @host@, @port@, @parameters@ and @secure@ attributes are used.
1990
  
1991
supported_transports:
1992 1 Adrian Georgescu
1993 147 Adrian Georgescu
>A sublist of @['udp', 'tcp', 'tls']@ in the application's order of preference.
1994
  
1995
timeout:
1996 129 Adrian Georgescu
1997 147 Adrian Georgescu
>How many seconds to wait for a response from a nameserver.
1998
  
1999
lifetime:
2000 1 Adrian Georgescu
2001 147 Adrian Georgescu
>How many seconds to wait for a response from all nameservers in total.
2002 129 Adrian Georgescu
2003 147 Adrian Georgescu
*lookup_xcap_server*(_self_, *uri*, *timeout*=@3.0@, *lifetime*=@15.0@)
2004
>Perform a TXT DNS query on xcap.<uri.host> and return all values of the TXT record which are URIs with a scheme of http or https. Only the @uri.host@ attribute is used. The return value is a list of strings representing HTTP URIs.
2005
  
2006
uri:
2007 1 Adrian Georgescu
2008 147 Adrian Georgescu
>A @(Frozen)SIPURI@ from which the @host@ attribute is used for the query domain.
2009
  
2010
timeout:
2011 129 Adrian Georgescu
2012 147 Adrian Georgescu
>How many seconds to wait for a response from a nameserver.
2013
  
2014
lifetime:
2015 1 Adrian Georgescu
2016 147 Adrian Georgescu
>How many seconds to wait for a response from all nameservers in total.
2017
2018
2019
2020
h4. notifications
2021
2022
2023
2024
*DNSLookupDidSucceed*
2025
>This notification is sent when one of the lookup methods succeeds in finding a result.
2026
  
2027
timestamp:
2028
2029
>A @datetime.datetime@ object indicating when the notification was sent.
2030
  
2031
result:
2032
2033
>The result of the DNS lookup in the format described in each method.
2034
2035
*DNSLookupDidFail*
2036
>This notification is sent when one of the lookup methods fails in finding a result.
2037
  
2038
timestamp:
2039
2040
>A @datetime.datetime@ object indicating when the notification was sent.
2041
  
2042
error:
2043
2044
>A @str@ object describing the error which resulted in the DNS lookup failure.
2045
2046
*DNSLookupTrace*
2047
>This notification is sent several times during a lookup process for each individual DNS query.
2048
  
2049
timestamp:
2050
2051
>A @datetime.datetime@ object indicating when the notification was sent.
2052
  
2053
query_type:
2054
2055
>The type of the query, @"NAPTR"@, @"SRV"@, @"A"@, @"NS"@ etc.
2056
  
2057
query_name:
2058
2059
>The name which was queried.
2060
  
2061
answer:
2062
2063
>The answer returned by dnspython, or @None@ if an error occurred.
2064
  
2065
error:
2066
2067
>The exception which caused the query to fail, or @None@ if no error occurred.
2068
  
2069
context:
2070
2071
>The name of the method which was called on the @DNSLookup@ object.
2072
  
2073
service:
2074
2075
>The service which was queried for, only available when context is @"lookup_service"@.
2076
  
2077
uri:
2078
2079
>The uri which was queried for.
2080
  
2081
nameservers:
2082
2083
>The list of nameservers that was used to perform the lookup.
2084
2085
2086
2087
h3. Route
2088
2089
2090
This is a convinience object which contains sufficient information to identify a route to a SIP proxy. This object is returned by @DNSLookup.lookup_sip_proxy@ and can be used with the @Session@ or a @(Frozen)RouteHeader@ can be easily constructed from it to pass to one of the objects in the SIP core handling SIP dialogs/transactions (@Invitation@, @Subscription@, @Request@, @Registration@, @Message@, @Publication@). This object has three attributes which can be set in the constructor or after it was instantiated. They will only be documented as arguments to the constructor.
2091
2092
2093
h4. methods
2094
2095
2096
2097
*<notextile>__init__</notextile>*(_self_, *address*, *port*=None, *transport*=@'udp'@)
2098
>Creates the Route object with the specified parameters as attributes.
2099
>Each of these attributes can be accessed on the object once instanced.
2100
  
2101
>+_address_+:
2102
2103
>The IPv4 address that the request in question should be sent to as a string.
2104
  
2105
>+_port_+:
2106
2107
>The port to send the requests to, represented as an int, or None if the default port is to be used.
2108
  
2109
>+_transport_+:
2110
2111
>The transport to use, this can be a string of either "udp", "tcp" or "tls" (case insensitive).
2112
2113
*get_uri*(_self_)
2114
>Returns a @SIPURI@ object which contains the adress, port and transport as parameter. This can be used to easily construct a @RouteHeader@:
2115
  <pre>
2116 87 Adrian Georgescu
    route = Route("1.2.3.4", port=1234, transport="tls")
2117
    route_header = RouteHeader(route.get_uri())
2118 147 Adrian Georgescu
</pre>
2119 87 Adrian Georgescu
2120
2121
2122 147 Adrian Georgescu
h2. SIP Accounts
2123 87 Adrian Georgescu
2124
2125 147 Adrian Georgescu
Account Management is implemented in [browser:sipsimple/account.py] (@sipsimple.account@ module) and offers support for SIP accounts registered at SIP providers and SIP bonjour accounts which are discovered using mDNS.
2126 87 Adrian Georgescu
2127
2128 147 Adrian Georgescu
h3. AccountManager
2129 87 Adrian Georgescu
2130 94 Adrian Georgescu
2131 147 Adrian Georgescu
The @sipsimple.account.AccountManager@ is the entity responsible for loading and keeping track of the existing accounts. It is a singleton and can be instantiated anywhere, obtaining the same instance. It cannot be used until its @start@ method has been called.
2132 87 Adrian Georgescu
2133
2134 147 Adrian Georgescu
h4. methods
2135 87 Adrian Georgescu
2136
2137
2138 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_)
2139
>The @__init__@ method allows the @AccountManager@ to be instantiated without passing any parameters. A reference to the @AccountManager@ can be obtained anywhere before it is started.
2140 87 Adrian Georgescu
2141 147 Adrian Georgescu
*start*(_self_)
2142
>This method will load all the existing accounts from the configuration. If the Engine is running, the accounts will also activate. This method can only be called after the [[SipConfigurationAPI#ConfigurationManager|ConfigurationManager]] has been started. A *SIPAccountManagerDidAddAccount* will be sent for each account loaded. This method is called automatically by the SIPApplication when it initializes all the components of the middleware.
2143 87 Adrian Georgescu
2144 147 Adrian Georgescu
*stop*(_self_)
2145
>Calling this method will deactivate all accounts managed by the @AccountManager@. This method is called automatically by the SIPApplication when it stops.
2146 87 Adrian Georgescu
2147 147 Adrian Georgescu
*has_account*(_self_, *id*)
2148
>This method returns @True@ if an account which has the specifed SIP ID (must be a string) exists and @False@ otherwise.
2149 87 Adrian Georgescu
2150 147 Adrian Georgescu
*get_account*(_self_, *id*)
2151
>Returns the account (either an @Account@ instance or the @BonjourAccount@ instance) with the specified SIP ID. Will raise a @KeyError@ if such an account does not exist.
2152 87 Adrian Georgescu
2153 147 Adrian Georgescu
*get_accounts*(_self_)
2154
>Returns a list containing all the managed accounts.
2155 87 Adrian Georgescu
2156 147 Adrian Georgescu
*iter_accounts*(_self_)
2157
>Returns an iterator through all the managed accounts.
2158
2159
*find_account*(_self_, *contact_uri*)
2160
>Returns an account with matches the specified @contact_uri@ which must be a @sipsimple.core.SIPURI@ instance. Only the accounts with the enabled flag set will be considered. Returns None if such an account does not exist.
2161
2162
2163
h4. notifications
2164
2165
2166
2167
*SIPAccountManagerDidAddAccount*
2168
>This notification is sent when a new account becomes available to the @AccountManager@. The notification is also sent when the accounts are loaded from the configuration.
2169
  
2170
>+_timestamp_+:
2171
2172
>A @datetime.datetime@ object indicating when the notification was sent.
2173
  
2174
>+_account_+:
2175
2176
>The account object which was added.
2177
2178
*SIPAccountManagerDidRemoveAccount*
2179
>This notification is sent when an account is deleted using the @delete@ method.
2180
  
2181
>+_timestamp_+:
2182
2183
>A @datetime.datetime@ object indicating when the notification was sent.
2184
  
2185
>+_account_+:
2186
2187
>The account object which was deleted.
2188
2189
*SIPAccountManagerDidChangeDefaultAccount*
2190
>This notification is sent when the default account changes.
2191
  
2192
>+_timestamp_+:
2193
2194
>A @datetime.datetime@ object indicating when the notification was sent.
2195
  
2196
>+_old_account_+:
2197
2198 133 Adrian Georgescu
   This is the account object which used to be the default account.
2199 147 Adrian Georgescu
  
2200
>+_account_+:
2201
2202 87 Adrian Georgescu
   This is the account object which is the new default account.
2203
2204
2205 147 Adrian Georgescu
h3. Account
2206 87 Adrian Georgescu
2207
2208 147 Adrian Georgescu
The @sipsimple.account.Account@ objects represent the SIP accounts which are registered at SIP providers. It has a dual purpose: it acts as both a container for account-related settings and as a complex object which can be used to interact with various per-account functions, such as presence, registration etc. This page documents the latter case, while the former is explained in the [[SipConfigurationAPI#Account|Configuration API]].
2209 87 Adrian Georgescu
2210 147 Adrian Georgescu
There is exactly one instance of @Account@ per SIP account used and it is uniquely identifiable by its SIP ID, in the form _user@domain_. It is a singleton, in the sense that instantiating @Account@ using an already used SIP ID will return the same object. However, this is not the recommended way of accessing accounts, as this can lead to creation of new ones; the recommended way is by using the [[SipMiddlewareApi#AccountManager|AccountManager]]. The next sections will use a lowercase, monospaced @account@ to represent an instance of @Account@.
2211
2212
2213
h4. states
2214
2215
2216
The @Account@ objects have a setting flag called @enabled@ which, if set to @False@ will deactivate it: none of the internal functions will work in this case; in addition, the application using the middleware should not do anything with a disabled account. After changing it's value, the @save()@ method needs to be called, as the flag is a setting and will not be used until this method is called:
2217
<pre>
2218 87 Adrian Georgescu
account.enabled = True
2219
account.save()
2220 147 Adrian Georgescu
</pre>
2221 87 Adrian Georgescu
2222 147 Adrian Georgescu
The @Account@ objects will activate automatically when they are loaded/created if the @enabled@ flag is set to @True@ and the @sipsimple.engine.Engine@ is running; if it is not running, the accounts will activate after the engine starts.
2223 87 Adrian Georgescu
2224 147 Adrian Georgescu
In order to create a new account, just create a new instance of @Account@ with an id which doesn't belong to any other account.
2225 87 Adrian Georgescu
2226 147 Adrian Georgescu
The other functions of @Account@ which run automatically have other enabled flags as well. They will only be activated when both the global enabled flag is set and the function-specific one. These are:
2227 87 Adrian Georgescu
2228
2229 147 Adrian Georgescu
*Account.registration.enabled*
2230
>This flag controls the automatic registration of the account. The notifications *SIPAccountRegistrationDidSucceed*, *SIPAccountRegistrationDidFail* and *SIPAccountRegistrationDidEnd* are used to inform the status of this registration.
2231 87 Adrian Georgescu
2232 147 Adrian Georgescu
*Account.presence.enabled*
2233
>This flag controls the automatic subscription to buddies for the _presence_ event and the publication of data in this event. (Not implemented yet)
2234 87 Adrian Georgescu
2235 147 Adrian Georgescu
*Account.dialog_event.enabled*
2236
>This flag controls the automatic subscription to buddies for the _dialog-info_ event and the publication of data in this event. (Not implemented yet)
2237 87 Adrian Georgescu
2238 147 Adrian Georgescu
*Account.message_summary.enabled*
2239
>This flag controls the automatic subscription to the _message-summary_ event in order to find out about voicemail messages. (Not implemented yet)
2240 87 Adrian Georgescu
2241 147 Adrian Georgescu
The @save()@ method needs to be called after changing these flags in order for them to take effect. The methods available on @Account@ objects are inherited from [[SipConfigurationAPI#SettingsObject|SettingsObject]].
2242 87 Adrian Georgescu
2243
2244 147 Adrian Georgescu
h4. attributes
2245
2246
2247 87 Adrian Georgescu
The following attributes can be used on an Account object and need to be considered read-only.
2248
2249 73 Luci Stanescu
2250 147 Adrian Georgescu
*id*
2251
>This attribute is of type @sipsimple.configuration.datatypes.SIPAddress@ (a subclass of @str@) and contains the SIP id of the account. It can be used as a normal string in the form _user@domain_, but it also allows access to the components via the attributes @username@ and @domain@.
2252
  <pre>
2253 73 Luci Stanescu
  account.id # 'alice@example.com'
2254
  account.id.username # 'alice'
2255
  account.id.domain # 'example.com'
2256 147 Adrian Georgescu
</pre>
2257 73 Luci Stanescu
2258 147 Adrian Georgescu
*contact*
2259
>This attribute can be used to construct the Contact URI for SIP requests sent on behalf of this account. It's type is @sipsimple.account.ContactURIFactory@. It can be indexed by a string representing a transport (@'udp'@, @'tcp'@, @'tls'@) or a @sipsimple.util.Route@ object which will return a @sipsimple.core.SIPURI@ object with the appropriate IP, port and transport. The username part is a randomly generated 8 character string consisting of lowercase letters; but it can be chosen by passing it to +init+ when building the @ContactURIFactory@ object.
2260
  <pre>
2261 73 Luci Stanescu
  account.contact # 'ContactURIFactory(username=hnfkybrt)'
2262
  account.contact.username # 'hnfkybrt'
2263 94 Adrian Georgescu
  account.contact['udp'] # <SIPURI "sip:hnfkybrt@10.0.0.1:53024">
2264 73 Luci Stanescu
  account.contact['tls'] # <SIPURI "sip:hnfkybrt@10.0.0.1:54478;transport=tls">
2265 147 Adrian Georgescu
</pre>
2266 94 Adrian Georgescu
2267 147 Adrian Georgescu
*credentials*
2268
>This attribute is of type @sipsimple.core.Credentials@ which is built from the @id.username@ attribute and the @password@ setting of the Account. Whenever this setting is changed, this attribute is updated.
2269
  <pre>
2270 73 Luci Stanescu
  account.credentials # <Credentials for 'alice'>
2271 147 Adrian Georgescu
</pre>
2272 94 Adrian Georgescu
2273 147 Adrian Georgescu
*uri*
2274
>This attribute is of type @sipsimple.core.SIPURI@ which can be used to form a @FromHeader@ associated with this account. It contains the SIP ID of the account.
2275
  <pre>
2276 73 Luci Stanescu
  account.uri # <SIPURI "sip:alice@example.com">
2277 147 Adrian Georgescu
</pre>
2278 94 Adrian Georgescu
2279 73 Luci Stanescu
2280 147 Adrian Georgescu
h4. notifications
2281 94 Adrian Georgescu
2282 73 Luci Stanescu
2283
2284 147 Adrian Georgescu
*CFGSettingsObjectDidChange*
2285
>This notification is sent when the @save()@ method is called on the account after some of the settings were changed. As the notification belongs to the @SettingsObject@ class, it is exaplained in detail in [[SipConfigurationAPI#SettingsObjectNotifications|SettingsObject Notifications]].
2286 1 Adrian Georgescu
2287 147 Adrian Georgescu
*SIPAccountWillActivate*
2288
>This notification is sent when the @Account@ is about to be activated, but before actually performing any activation task. See @SIPAccountDidActivate@ for more detail.
2289
  
2290
>+_timestamp_+:
2291 119 Luci Stanescu
2292 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2293 119 Luci Stanescu
2294 147 Adrian Georgescu
*SIPAccountDidActivate*
2295
>This notification is sent when the @Account@ activates. This can happen when the @Account@ is loaded if it's enabled flag is set and the Engine is running, and at any later time when the status of the Engine changes or the enabled flag is modified.
2296
  
2297
>+_timestamp_+:
2298 119 Luci Stanescu
2299 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2300 119 Luci Stanescu
2301 147 Adrian Georgescu
*SIPAccountWillDeactivate*
2302
>This notification is sent when the @Account@ is about to be deactivated, but before performing any deactivation task. See @SIPAccountDidDeactivate@ for more detail.
2303
  
2304
>+_timestamp_+:
2305
2306
>A @datetime.datetime@ object indicating when the notification was sent.
2307
2308
*SIPAccountDidDeactivate*
2309
>This notification is sent when the @Account@ deactivates. This can happend when the @Engine@ is stopped or when the enabled flag of the account is set to @False@.
2310
  
2311
>+_timestamp_+:
2312
2313
>A @datetime.datetime@ object indicating when the notification was sent.
2314
2315
*SIPAccountWillRegister*
2316
>This notification is sent when the account is about to register for the first time.
2317
  
2318
>+_timestamp_+:
2319
2320
>A @datetime.datetime@ object indicating when the notification was sent.
2321
2322
*SIPAccountRegistrationWillRefresh*
2323
>This notification is sent when a registration is about to be refreshed.
2324
  
2325
>+_timestamp_+:
2326
2327
>A @datetime.datetime@ object indicating when the notification was sent.
2328
2329
*SIPAccountRegistrationDidSucceed*
2330
>This notification is sent when a REGISTER request sent for the account succeeds (it is also sent for each refresh of the registration). The data contained in this notification is:
2331
  
2332
>+_timestamp_+:
2333
2334
>A @datetime.datetime@ object indicating when the notification was sent.
2335
  
2336
>+_contact_header_+:
2337
2338 119 Luci Stanescu
   The Contact header which was registered.
2339 147 Adrian Georgescu
  
2340
>+_contact_header_list_+:
2341
2342 119 Luci Stanescu
   A list containing all the contacts registered for this SIP account.
2343 147 Adrian Georgescu
  
2344
>+_expires_+:
2345
2346 119 Luci Stanescu
   The amount in seconds in which this registration will expire.
2347 147 Adrian Georgescu
  
2348
>+_registrar_+:
2349 119 Luci Stanescu
2350 147 Adrian Georgescu
>The @sipsimple.util.Route@ object which was used.
2351
2352
*SIPAccountRegistrationDidFail*
2353
>This notification is sent when a REGISTER request sent for the account fails. It can fail either because a negative response was returned or because PJSIP considered the request failed (e.g. on timeout). The data contained in this notification is:
2354
  
2355
>+_timestamp_+:
2356
2357
>A @datetime.datetime@ object indicating when the notification was sent.
2358
  
2359
>+_error_+:
2360
2361 119 Luci Stanescu
   The reason for the failure of the REGISTER request.
2362 147 Adrian Georgescu
  
2363
>+_timeout_+:
2364 119 Luci Stanescu
2365 147 Adrian Georgescu
   The amount in seconds as a @float@ after which the registration will be tried again.
2366 119 Luci Stanescu
2367 147 Adrian Georgescu
*SIPAccountRegistrationDidEnd*
2368
>This notification is sent when a registration is ended (the account is unregistered). The data contained in this notification is:
2369
  
2370
>+_timestamp_+:
2371 119 Luci Stanescu
2372 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2373
  
2374
>+_registration_+:
2375 119 Luci Stanescu
2376 147 Adrian Georgescu
   The @sipsimple.core.Registration@ object which ended.
2377 119 Luci Stanescu
2378 147 Adrian Georgescu
*SIPAccountRegistrationDidNotEnd*
2379
>This notification is sent when a registration fails to end (the account is not unregistered). The data contained in this notification is:
2380
  
2381
>+_timestamp_+:
2382 119 Luci Stanescu
2383 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2384
  
2385
>+_code_+:
2386 119 Luci Stanescu
2387 147 Adrian Georgescu
>The SIP status code received.
2388
  
2389
>+_reason_+:
2390 119 Luci Stanescu
2391 147 Adrian Georgescu
>The SIP status reason received.
2392
  
2393
>+_registration_+:
2394 119 Luci Stanescu
2395 147 Adrian Georgescu
>The @sipsimple.core.Registration@ object which ended.
2396 119 Luci Stanescu
2397 147 Adrian Georgescu
*SIPAccountRegistrationGotAnswer*
2398
>This notification is sent whenever a response is received to a sent REGISTER request for this account. The data contained in this notification is:
2399
  
2400
>+_timestamp_+:
2401
2402
>A @datetime.datetime@ object indicating when the notification was sent.
2403
  
2404
>+_code_+:
2405
2406
>The SIP status code received.
2407
  
2408
>+_reason_+:
2409
2410
>The SIP status reason received.
2411
  
2412
>+_registration_+:
2413
2414
>The @sipsimple.core.Registration@ object which was used.
2415
  
2416
>+_registrar_+:
2417
2418
>The @sipsimple.util.Route@ object which was used.
2419
2420
*SIPAccountMWIDidGetSummary*
2421
>This notification is sent when a NOTIFY is received with a message-summary payload. The data contained in this notification is:
2422
  
2423
>+_timestamp_+:
2424
2425
>A @datetime.datetime@ object indicating when the notification was sent.
2426
  
2427
>+_message_summary_+:
2428
2429
>A @sipsimple.payloads.messagesummary.MessageSummary@ object with the parsed payload from the NOTIFY request.
2430
2431
2432
h3. BonjourAccount
2433
2434
2435
The @sipsimple.account.BonjourAccount@ represents the SIP account used for P2P mode; it does not interact with any server. The class is a singleton, as there can only be one such account on a system. Similar to the @Account@, it is used both as a complex object, which implements the functions for bonjour mode, as well as a container for the related settings.
2436
2437
2438
h4. states
2439
2440
2441
The @BonjourAccount@ has an @enabled@ flag which controls whether this account will be used or not. If it is set to @False@, none of the internal functions will be activated and, in addition, the account should not be used by the application. The bonjour account can only activated if the Engine is running; once it is started, if the enabled flag is set, the account will activate. When the @BonjourAccount@ is activated, it will broadcast the contact address on the LAN and discover its neighbours sending notifications as this happens.
2442
2443
2444
h4. attributes
2445
2446
2447 119 Luci Stanescu
The following attributes can be used on a BonjourAccount object and need to be considered read-only.
2448
2449
2450 147 Adrian Georgescu
*id*
2451
>This attribute is of type @sipsimple.configuration.datatypes.SIPAddress@ (a subclass of @str@) and contains the SIP id of the account, which is @'bonjour@local'@. It can be used as a normal string, but it also allows access to the components via the attributes @username@ and @domain@.
2452
  <pre>
2453 119 Luci Stanescu
  bonjour_account.id # 'bonjour@local'
2454
  bonjour_account.id.username # 'bonjour'
2455
  bonjour_account.id.domain # 'local'
2456 147 Adrian Georgescu
</pre>
2457 119 Luci Stanescu
2458 147 Adrian Georgescu
*contact*
2459
>This attribute can be used to construct the Contact URI for SIP requests sent on behalf of this account. It's type is @sipsimple.account.ContactURIFactory@. It can be indexed by a string representing a transport (@'udp'@, @'tcp'@, @'tls'@) or a @sipsimple.util.Route@ object which will return a @sipsimple.core.SIPURI@ object with the appropriate IP, port and transport. The username part is a randomly generated 8 character string consisting of lowercase letters; but it can be chosen by passing it to +init+ when building the @ContactURIFactory@ object.
2460
  <pre>
2461 119 Luci Stanescu
  bonjour_account.contact # 'ContactURIFactory(username=lxzvgack)'
2462
  bonjour_account.contact.username # 'lxzvgack'
2463
  bonjour_account.contact['udp'] # <SIPURI "sip:lxzvgack@10.0.0.1:53024">
2464
  bonjour_account.contact['tls'] # <SIPURI "sip:lxzvgack@10.0.0.1:54478;transport=tls">
2465 147 Adrian Georgescu
</pre>
2466 119 Luci Stanescu
2467 147 Adrian Georgescu
*credentials*
2468
>This attribute is of type @sipsimple.core.Credentials@ object which is built from the @contact.username@ attribute; the password is set to the empty string.
2469
  <pre>
2470 119 Luci Stanescu
  bonjour_account.credentials # <Credentials for 'alice'>
2471 147 Adrian Georgescu
</pre>
2472 119 Luci Stanescu
2473 147 Adrian Georgescu
*uri*
2474
>This attribute is of type @sipsimple.core.SIPURI@ which can be used to form a @FromHeader@ associated with this account. It contains the contact address of the bonjour account:
2475
  <pre>
2476 119 Luci Stanescu
  bonjour_account.uri # <SIPURI "sip:lxzvgack@10.0.0.1">
2477 147 Adrian Georgescu
</pre>
2478 119 Luci Stanescu
2479
2480 147 Adrian Georgescu
h4. notifications
2481 119 Luci Stanescu
2482
2483 147 Adrian Georgescu
*BonjourAccountDidAddNeighbour*
2484
>This notification is sent when a new Bonjour neighbour is discovered.
2485
  
2486
>+_service_description_+:
2487 119 Luci Stanescu
2488 147 Adrian Georgescu
>BonjourServiceDescription object uniquely identifying this neighbour in the mDNS library.
2489
  
2490
>+_display_name_+:
2491 119 Luci Stanescu
2492 147 Adrian Georgescu
>The name of the neighbour as it is published.
2493
  
2494
>+_host_+:
2495 119 Luci Stanescu
2496 147 Adrian Georgescu
>The hostname of the machine from which the Bonjour neighbour registered its contact address.
2497
  
2498
>+_uri_+:
2499 119 Luci Stanescu
2500 147 Adrian Georgescu
>The contact URI of the Bonjour neighbour, as a @FrozenSIPURI@ object.
2501
  
2502
>+_timestamp_+:
2503 119 Luci Stanescu
2504 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2505 119 Luci Stanescu
2506 147 Adrian Georgescu
*BonjourAccountDidUpdateNeighbour*
2507
>This notification is sent when an existing Bonjour neighbour has updates its published data.
2508
  
2509
>+_service_description_+:
2510 119 Luci Stanescu
2511 147 Adrian Georgescu
>BonjourServiceDescription object uniquely identifying this neighbour in the mDNS library.
2512
  
2513
>+_display_name_+:
2514 119 Luci Stanescu
2515 147 Adrian Georgescu
>The name of the neighbour as it is published.
2516
  
2517
>+_host_+:
2518 119 Luci Stanescu
2519 147 Adrian Georgescu
>The hostname of the machine from which the Bonjour neighbour registered its contact address.
2520
  
2521
>+_uri_+:
2522 119 Luci Stanescu
2523 147 Adrian Georgescu
>The contact URI of the Bonjour neighbour, as a @FrozenSIPURI@ object.
2524
  
2525
>+_timestamp_+:
2526 119 Luci Stanescu
2527 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2528 119 Luci Stanescu
2529 147 Adrian Georgescu
*BonjourAccountDidRemoveNeighbour*
2530
>This notification is sent when a Bonjour neighbour unregisters.
2531
  
2532
>+_service_description_+:
2533 119 Luci Stanescu
2534 147 Adrian Georgescu
>The BonjourServiceDescription object, which uniquely identifies a neighbour, that got unregistered.
2535 119 Luci Stanescu
2536 147 Adrian Georgescu
*BonjourAccountDiscoveryDidFail*
2537
>This notification is sent once per transport when the Bonjour account has failed to perform the discovery process for the indicated transport.
2538
  
2539
>+_reason_+:
2540 119 Luci Stanescu
2541 147 Adrian Georgescu
>String defining the reason of the failure.
2542
  
2543
>+_transport_+:
2544 119 Luci Stanescu
2545 147 Adrian Georgescu
>String specifying the transport for which the discovery failed.
2546
  
2547
>+_timestamp_+:
2548 119 Luci Stanescu
2549 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
2550 119 Luci Stanescu
2551 147 Adrian Georgescu
*BonjourAccountDiscoveryFailure*
2552
>This notification is sent once per transport when the Bonjour account has encountered a problem while browsing the list of neighbours for the indicated transport.
2553
  
2554
>+_error_+:
2555
2556
>String defining the error of the failure.
2557
  
2558
>+_transport_+:
2559
2560
>String specifying the transport for which the neighbour resoution failed.
2561
  
2562
>+_timestamp_+:
2563
2564
>A @datetime.datetime@ object indicating when the notification was sent.
2565
2566
*BonjourAccountRegistrationDidEnd*
2567
>This notification is sent once per transport when the Bonjour account unregisters its contact address for the indicated transport using mDNS.
2568
  
2569
>+_transport_+:
2570
2571
>String specifying the transport for which the registration ended.
2572
  
2573
>+_timestamp_+:
2574
2575
>A @datetime.datetime@ object indicating when the notification was sent.
2576
2577
*BonjourAccountRegistrationDidFail*
2578
>This notification is sent once per transport when the Bonjour account fails to register its contact address for the indicated transport using mDNS.
2579
  
2580
>+_reason_+:
2581
2582
>A human readable error message.
2583
  
2584
>+_transport_+:
2585
2586
>String specifying the transport for which the registration failed.
2587
  
2588
>+_timestamp_+:
2589
2590
>A @datetime.datetime@ object indicating when the notification was sent.
2591
2592
*BonjourAccountRegistrationUpdateDidFail*
2593
>This notification is sent once per transport when the Bonjour account fails to update its data for the indicated transport using mDNS.
2594
  
2595
>+_reason_+:
2596
2597
>A human readable error message.
2598
  
2599
>+_transport_+:
2600
2601
>String specifying the transport for which the registration update failed.
2602
  
2603
>+_timestamp_+:
2604
2605
>A @datetime.datetime@ object indicating when the notification was sent.
2606
2607
*BonjourAccountRegistrationDidSucceed*
2608
>This notification is sent once per transport when the Bonjour account successfully registers its contact address for the indicated transport using mDNS.
2609
  
2610
>+_name_+:
2611
2612
>The contact address registered.
2613
  
2614
>+_transport_+:
2615
2616
>String specifying the transport for which the registration succeeded.
2617
  
2618
>+_timestamp_+:
2619
2620
>A @datetime.datetime@ object indicating when the notification was sent.
2621
2622
*BonjourAccountWillInitateDiscovery*
2623
>This notification is sent when the Bonjour account is about to start the discovery process for the indicated transport.
2624
  
2625
>+_transport_+:
2626
2627
>String specifying the transport for which the discovery will be started.
2628
  
2629
>+_timestamp_+:
2630
2631
>A @datetime.datetime@ object indicating when the notification was sent.
2632
2633
  *BonjourAccountWillRegister*
2634
>This notification is sent just before the Bonjour account starts the registering process for the indicated transport.
2635
  
2636
>+_transport_+:
2637
2638
>String specifying the transport for which the registration will be started.
2639
  
2640
>+_timestamp_+:
2641
2642
>A @datetime.datetime@ object indicating when the notification was sent.
2643
2644
*CFGSettingsObjectDidChange*
2645
>This notification is sent when the @save()@ method is called on the account after some of the settings were changed. As the notification belongs to the @SettingsObject@ class, it is exaplained in detail in [[SipConfigurationAPI#SettingsObjectNotifications|SettingsObject Notifications]].
2646
  
2647
>+_timestamp_+:
2648
2649
>A @datetime.datetime@ object indicating when the notification was sent.
2650
2651
*SIPAccountWillActivate*
2652
>This notification is sent when the @BonjourAccount@ is about to be activated, but before actually performing any activation task. See @SIPAccountDidActivate@ for more detail.
2653
  
2654
>+_timestamp_+:
2655
2656
>A @datetime.datetime@ object indicating when the notification was sent.
2657
2658
*SIPAccountDidActivate*
2659
>This notification is sent when the @BonjourAccount@ activates. This can happen when the @BonjourAccount@ is loaded if it's enabled flag is set and the Engine is running, and at any later time when the status of the Engine changes or the enabled flag is modified.
2660
  
2661
>+_timestamp_+:
2662
2663
>A @datetime.datetime@ object indicating when the notification was sent.
2664
2665
*SIPAccountWillDeactivate*
2666
>This notification is sent when the @BonjourAccount@ is about to be deactivated, but before performing any deactivation task. See @SIPAccountDidDeactivate@ for more detail.
2667
  
2668
>+_timestamp_+:
2669
2670
>A @datetime.datetime@ object indicating when the notification was sent.
2671
2672
*SIPAccountDidDeactivate*
2673
>This notification is sent when the @BonjourAccount@ deactivates. This can happend when the @Engine@ is stopped or when the enabled flag of the account is set to @False@.
2674
  
2675
>+_timestamp_+:
2676
2677
>A @datetime.datetime@ object indicating when the notification was sent.
2678
2679
2680
2681
h2. Audio
2682
2683
2684
The high-level audio API hides the complexity of using the low-level PJMEDIA interface. This is implemented in the @sipsimple.audio@ module and contains the following components:
2685
* IAudioPort: an interface describing an object capable of producing and/or consuming audio data.
2686
* AudioDevice: an object conforming to the IAudioPort interface which describes a physical audio device.
2687
* AudioBridge: a collection of objects conforming to IAudioPort which connects all of them in a full mesh.
2688
* WavePlayer: an object conforming to the IAudioPort interface which can playback the audio data from a @.wav@ file.
2689
* WaveRecorder: an object conforming to the IAudioPort interface which can record audio data to a @.wav@ file.
2690
2691
2692
h3. IAudioPort
2693
2694
2695 119 Luci Stanescu
The IAudioPort interface describes an object capable of producing and/or consuming audio data. This can be a dynamic object, which changes its role during its lifetime and notifies such changes using a notification, which is part of the interface.
2696
2697
2698 147 Adrian Georgescu
h4. attributes
2699 119 Luci Stanescu
2700
2701
2702 147 Adrian Georgescu
*mixer*
2703
>The @AudioMixer@ this audio object is connected to. Only audio objects connected to the same mixer will be able to send audio data from one to another.
2704 119 Luci Stanescu
2705 147 Adrian Georgescu
*consumer_slot*
2706
>An integer representing the slot (see [[SipCoreApiDocumentation#AudioMixer|AudioMixer]]) which this object uses to consume audio data, or @None@ if this object is not a consumer.
2707
2708
*producer_slot*
2709
>An integer representing the slot (see [[SipCoreApiDocumentation#AudioMixer|AudioMixer]]) which this object uses to produce audio data, or @None@ if this object is not a producer.
2710
2711
2712
h4. notifications
2713
2714 119 Luci Stanescu
 
2715
2716 147 Adrian Georgescu
*AudioPortDidChangeSlots*
2717
>This notification needs to be sent by implementations of this interface when the slots it has change, so as to let the @AudioBridges@ it is part of know that reconnections need to be made.
2718
  
2719
consumer_slot_changed:
2720 119 Luci Stanescu
2721 147 Adrian Georgescu
>A bool indicating whether the consumer slot was changed.
2722
  
2723
producer_slot_changed:
2724 119 Luci Stanescu
2725 147 Adrian Georgescu
>A bool indicating whether the producer slot was changed.
2726
  
2727
old_consumer_slot:
2728 119 Luci Stanescu
2729 147 Adrian Georgescu
>The old slot for consuming audio data. Only required if consumer_slot_changed is @True@.
2730
  
2731
new_consumer_slot:
2732 119 Luci Stanescu
2733 147 Adrian Georgescu
>The new slot for consuming audio data. Only required if consumer_slot_changed is @True@.
2734
  
2735
old_producer_slot:
2736 119 Luci Stanescu
2737 147 Adrian Georgescu
>The old slot for producing audio data. Only required if producer_slot_changed is @True@.
2738
  
2739
new_producer_slot:
2740 119 Luci Stanescu
2741 147 Adrian Georgescu
>The new slot for producing audio data. Only required if producer_slot_changed is @True@.
2742 119 Luci Stanescu
2743
2744 147 Adrian Georgescu
h3. AudioDevice
2745 119 Luci Stanescu
2746
2747 147 Adrian Georgescu
The AudioDevice represents the physical audio device which is part of a @AudioMixer@, implementing the @IAudioPort@ interface. As such, it can be uniquely identified by the mixer it represents.
2748 119 Luci Stanescu
2749
2750 147 Adrian Georgescu
h4. methods
2751 119 Luci Stanescu
2752
2753
2754 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *mixer*, *input_muted*=@False@, *output_muted*=@False@):
2755
>Instantiates a new AudioDevice which represents the physical device associated with the specified @AudioMixer@.
2756
  
2757
mixer:
2758 119 Luci Stanescu
2759 147 Adrian Georgescu
>The @AudioMixer@ whose physical device this object represents.
2760
  
2761
input_muted:
2762 119 Luci Stanescu
2763 147 Adrian Georgescu
>A boolean which indicates whether this object should act as a producer of audio data.
2764
  
2765
output_muted:
2766 119 Luci Stanescu
2767 147 Adrian Georgescu
>A boolean which indicates whether this object should act as a consumer of audio data.
2768 119 Luci Stanescu
2769
2770 147 Adrian Georgescu
h4. attributes
2771 119 Luci Stanescu
2772
2773
2774 147 Adrian Georgescu
*input_muted*
2775
>A writable property which controls whether this object should act as a producer of audio data. An @AudioPortDidChange@ slots notification is sent when this attribute is changed to force connections to be reconsidered within the @AudioBridges@ this object is part of.
2776 119 Luci Stanescu
2777 147 Adrian Georgescu
*output_muted*
2778
>A writable property which controls whether this object should act as a consumer of audio data. An @AudioPortDidChange@ slots notification is sent when this attribute is changed to force connections to be reconsidered within  the @AudioBridges@ this object is part of.
2779 119 Luci Stanescu
2780
2781 147 Adrian Georgescu
h3. AudioBridge
2782 119 Luci Stanescu
2783
2784 147 Adrian Georgescu
The @AudioBridge@ is the basic component which is able to connect @IAudioPort@ implementations. It acts as a container which connects as the producers to all the consumers which are part of it. An object which is both a producer and a consumer of audio data will not be connected to itself. Being an implementation of @IAudioPort@ itself, an @AudioBridge@ can be part of another @AudioBridge@. The @AudioBridge@ does not keep strong references to the ports it contains and once the port's reference count reaches 0, it is automatically removed from the @AudioBridge@.
2785
> Note: although this is not enforced, there should never be any cycles when connecting @AudioBridges@.
2786 119 Luci Stanescu
2787
2788 147 Adrian Georgescu
h4. methods
2789 119 Luci Stanescu
2790
2791
2792 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *mixer*)
2793
>Instantiate a new @AudioBridge@ which uses the specified @AudioMixer@ for mixing.
2794 119 Luci Stanescu
2795 147 Adrian Georgescu
*add*(_self_, *port*)
2796
>Add an implementation of @IAudioPort@ to this AudioBridge. This will connect the new port to all the existing ports of the bridge. A port cannot be added more than once to an @AudioBridge@; thus, this object acts like a set.
2797 119 Luci Stanescu
2798 147 Adrian Georgescu
*remove*(_self_, *port*)
2799
>Remove a port from this @AudioBridge@. The port must have previously been added to the @AudioBridge@, otherwise a @ValueError@ is raised.
2800 119 Luci Stanescu
2801
2802 147 Adrian Georgescu
h3. WavePlayer
2803 119 Luci Stanescu
2804
2805 147 Adrian Georgescu
A @WavePlayer@ is an implementation of @IAudioPort@ which is capable of producing audio data read from a @.wav@ file. This object is completely reusable, as it can be started and stopped any number of times.
2806 1 Adrian Georgescu
2807
2808 147 Adrian Georgescu
h4. methods
2809 1 Adrian Georgescu
2810
2811
2812 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *mixer*, *filename*, *volume*=@100@, *loop_count*=@1@, *pause_time*=@0@, *initial_play*=@True@)
2813
>Instantiate a new @WavePlayer@ which is capable of playing a @.wav@ file repeatedly. All the parameters are available as attributes of the object, but should not be changed once the object has been started.
2814
  
2815
mixer:
2816 1 Adrian Georgescu
2817 147 Adrian Georgescu
>The @AudioMixer@ this object is connected to.
2818
  
2819
filename:
2820 1 Adrian Georgescu
2821 147 Adrian Georgescu
>The full path to the @.wav@ file from which audio data is to be read.
2822
  
2823
volume:
2824 1 Adrian Georgescu
2825 147 Adrian Georgescu
>The volume at which the file should be played.
2826
  
2827
loop_count:
2828 1 Adrian Georgescu
2829 147 Adrian Georgescu
>The number of times the file should be played, or @0@ for infinity.
2830
  
2831
pause_time:
2832 1 Adrian Georgescu
2833 147 Adrian Georgescu
>How many seconds to wait between successive plays of the file. 
2834
  
2835
initial_play:
2836 1 Adrian Georgescu
2837 147 Adrian Georgescu
>Whether or not the file to play once the @WavePlayer@ is started, or to wait @pause_time@ seconds before the first play.
2838 1 Adrian Georgescu
2839 147 Adrian Georgescu
*start*(_self_)
2840
>Start playing the @.wav@ file.
2841 1 Adrian Georgescu
2842 147 Adrian Georgescu
*stop*(_self_)
2843
>Stop playing the @.wav@ file immediately.
2844 1 Adrian Georgescu
2845 147 Adrian Georgescu
*play*(_self_)
2846
>Play the @.wav@ file. This method is an alternative to the start/stop methods, it runs on a waitable green thread. One may call @play().wait()@ in order to green-block waiting for the file playback to end.
2847 1 Adrian Georgescu
2848
2849 147 Adrian Georgescu
h4. attributes
2850 1 Adrian Georgescu
2851
2852
2853 147 Adrian Georgescu
*is_active*
2854
>A boolean indicating whether or not this @WavePlayer@ is currently playing.
2855 1 Adrian Georgescu
2856
2857 147 Adrian Georgescu
h4. notifications
2858 1 Adrian Georgescu
2859
2860 147 Adrian Georgescu
2861
*WavePlayerDidStart*
2862
>This notification is sent when the @WavePlayer@ starts playing the file the first time after the @start()@ method has been called.
2863
  
2864
timestamp:
2865
2866
>A @datetime.datetime@ object indicating when the notification was sent.
2867
2868
*WavePlayerDidEnd*
2869
>This notification is sent when the @WavePlayer@ is done playing either as a result of playing the number of times it was told to, or because the @stop()@ method has been called.
2870
  
2871
timestamp:
2872
2873
>A @datetime.datetime@ object indicating when the notification was sent.
2874
2875
*WavePlayerDidFail*
2876
>This notification is sent when the @WavePlayer@ is not capable of playing the @.wav@ file.
2877
  
2878
timestamp:
2879
2880
>A @datetime.datetime@ object indicating when the notification was sent.
2881
  
2882
error:
2883
2884
>The exception raised by the @WaveFile@ which identifies the cause for not being able to play the @.wav@ file.
2885
2886
2887
h3. WaveRecorder
2888
2889
2890
A @WaveRecorder@ is an implementation of @IAudioPort@ is is capable of consuming audio data and writing it to a @.wav@ file. Just like @WavePlayer@, this object is reusable: once stopped it can be started again, but if the filename attribute is not changed, the previously written file will be overwritten.
2891
2892
2893
h4. methods
2894
2895
2896
2897
*<notextile>__init__</notextile>*(_self_, *mixer*, *filename*)
2898
>Instantiate a new @WaveRecorder@.
2899
  
2900
mixer:
2901
2902
>The @AudioMixer@ this @WaveRecorder@ is connected to.
2903
  
2904
filename:
2905
2906
>The full path to the @.wav@ file where this object should write the audio data. The file must be writable. The directories up to the file will be created if possible when the @start()@ method is called.
2907
2908
*start*(_self_)
2909
>Start consuming audio data and writing it to the @.wav@ file. If this object is not part of an @AudioBridge@, not audio data will be written.
2910
2911
*stop*(_self_)
2912
>Stop consuming audio data and close the @.wav@ file.
2913
2914
2915
h4. attributes
2916
2917
2918
2919
*is_active*
2920
>A boolean indicating whether or not this @WaveRecorder@ is currently recording audio data.
2921
2922
2923
2924
h2. Conference
2925
2926
2927
Conference support is implemented in the @sipsimple.conference@ module. Currently, only audio conferencing is supported.
2928
2929
2930
h3. AudioConference
2931
2932
2933
This class contains the basic implementation for audio conferencing. It acts as a container for @AudioStream@ objects which it will connect in a full mesh, such that all participants can hear all other participants.
2934
2935
2936
h4. methods
2937
2938
2939
2940
*<notextile>__init__</notextile>*(_self_)
2941
>Instantiates a new @AudioConference@ which is ready to contain @AudioStream@ objects.
2942
2943
*add*(_self_, *stream*)
2944
>Add the specified @AudioStream@ object to the conference.
2945
2946
*remove*(_self_, *stream*)
2947
>Removes the specified @AudioStream@ object from the conference. Raises a @ValueError@ if the stream is not part of the conference.
2948
2949
*hold*(_self_)
2950
>Puts the conference "on hold". This means that the audio device will be disconnected from the conference: all the participants will be able to continue the conference, but the local party will no longer contribute any audio data and will not receive any audio data using the input and output devices respectively. This does not affect the hold state of the streams in any way.
2951
2952
*unhold*(_self_)
2953
>Removes the conference "from hold". This means that the audio device will be reconnected to the conference: all the participants will start to hear the local party and the local party will start to hear all the participants. This does not affect the hold state of the streams in any way.
2954
2955
2956
h4. attributes
2957
2958
2959
2960
*bridge*
2961
>An @AudioBridge@ which this conference uses to connect all audio streams. It can be used by the application to play a wav file using a @WavePlayer@ to all the participants or record the whole conference using a @WaveRecorder@.
2962
2963
*on_hold*
2964
>A boolean indicating whether or not the conference is "on hold".
2965
2966
*streams*
2967
>The list of streams which are part of this conference. The application must not manipulate this list in any way.
2968
2969
2970
2971
h2. XCAP support
2972
2973
2974
The @sipsimple.xcap@ module offers a high level API for managing XCAP resources to other parts of the middleware or to the applications built on top of the middleware. The XCAP resources
2975 1 Adrian Georgescu
which can be managed by means of this module are:
2976 147 Adrian Georgescu
* *contact list*, by means of the @resource-lists@ and @rls-services@ XCAP applications
2977
* *presence policies*, by means of the @org.openmobilealliance.pres-rules@ or @pres-rules@ XCAP applications
2978
* *dialoginfo policies*, by means of the @org.openxcap.dialog-rules@ XCAP application
2979
* *status icon*, by means of the @org.openmobilealliance.pres-content@ XCAP application
2980
* *offline status*, by means of the @pidf-manipulation@ XCAP application
2981 1 Adrian Georgescu
2982
The module can work with both OMA or IETF-compliant XCAP servers, preferring the OMA variants of the specification if the server supports them. Not all applications need to be available on the
2983
XCAP server, although it is obvious that only those that are will be managed. The central entity for XCAP resource management is the XCAPManager, whose API relies on a series of objects describing
2984
the resources stored on the XCAP server.
2985
2986
2987 147 Adrian Georgescu
h3. Contact
2988 1 Adrian Georgescu
2989
2990 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
2991 1 Adrian Georgescu
2992 147 Adrian Georgescu
A @Contact@ is a URI with additional information stored about it, central to the XCAP contact list management. Information about a contact is stored in the @resource-lists@, @rls-services@,
2993
@org.openmobilealliance.pres-rules@ or @pres-rules@, and @org.openxcap.dialog-rules@ applications. The URI associated with the contact is considered a unique identifier. Information
2994
found in various places about the same URI is aggregated into a single @Contact@ instance. More information about the contact is described within the attributes section.
2995 1 Adrian Georgescu
2996
2997 147 Adrian Georgescu
h4. attributes
2998 1 Adrian Georgescu
2999
3000 147 Adrian Georgescu
*name*
3001
>A human-readable name which can be associated with the contact. This is stored using the @display-name@ standard @resource-lists@ element.
3002 1 Adrian Georgescu
3003 147 Adrian Georgescu
*uri*
3004
>The uniquely identifying URI.
3005
3006
*group*
3007
>A human-readable group name which can be used to group contacts together. If this is not @None@, the contact will be reachable from the @oma_buddylist@ list within the @resource-lists@
3008
>document, as defined by OMA. The group of a contact is the first @display-name@ of an ancestor list which contains the contact information.
3009
3010
*subscribe_to_presence*
3011
>A boolean flag which indicates whether a subscription to the @presence@ event is desired. If this is @True@, the contact's URI is referenced from a @rls-services@ service which defines
3012
  @presence@ as one of the packages. Thus, a contact with this flag set is guaranteed to be referenced by an RLS service.
3013
3014
*subscribe_to_dialoginfo*
3015
>A boolean flag which indicates whether a subscription to the @dialog@ event is desired. If this is @True@, the contact's URI is referenced from a @rls-services@ service which defines
3016
  @dialog@ as one of the packages. Thus, a contact with this flag set is guaranteed to be refereneced by an RLS service.
3017
3018
*presence_policies*
3019
>Either @None@ or a list of @PresencePolicy@ objects which represent @org.openmobilealliance.pres-rules@ or @pres-rules@ rules which reference this contact's URI either directly
3020 1 Adrian Georgescu
  (through an identity condition) or indirectly through resource lists (using the OMA external-list common policy extension).
3021
3022 147 Adrian Georgescu
*dialoginfo_policies*
3023
>Either @None@ or a list of @DialoginfoPolicy@ objects which represent @org.openxcap.dialog-rules@ rules which reference this contact's URI through an identity condition.
3024 1 Adrian Georgescu
3025 147 Adrian Georgescu
*attributes*
3026
>A dictionary containing additional name, value pairs which the middleware or the application can use to store any information regarding this contact. This is stored through a proprietary AG-Projects
3027
>extension to resource-lists.
3028 1 Adrian Georgescu
3029
3030 147 Adrian Georgescu
h4. methods
3031 1 Adrian Georgescu
3032
3033 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *name*, *uri*, *group*, ***attributes*)
3034
>Initializes a new @Contact@ instance. The policies are by default set to @None@ and the @subscribe_to_presence@ and @subscribe_to_dialoginfo@ flags to @True@.
3035 1 Adrian Georgescu
3036
3037
3038 147 Adrian Georgescu
h3. Service
3039 1 Adrian Georgescu
3040
3041 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
3042 1 Adrian Georgescu
3043 147 Adrian Georgescu
A @Service@ represents a URI managed by a Resource List Server (RLS). Subscriptions to this URI will be handled by the RLS.
3044 1 Adrian Georgescu
3045
3046 147 Adrian Georgescu
h4. attributes
3047 1 Adrian Georgescu
3048
3049 147 Adrian Georgescu
*uri*
3050
>The URI which can be used to access a service provided by the RLS.
3051 1 Adrian Georgescu
3052 147 Adrian Georgescu
*packages*
3053
>A list of strings containing the SIP events which can be subscribed for to the URI.
3054 1 Adrian Georgescu
3055 147 Adrian Georgescu
*entries*
3056
>A list of URIs which represent the expanded list of URIs referenced by the service. A subscription to the service's URI for one of packages will result in the RLS subscribing to these URIs.
3057 1 Adrian Georgescu
3058
3059 147 Adrian Georgescu
h4. methods
3060 1 Adrian Georgescu
3061
3062 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *uri*, *packages*, *entries*=@None@)
3063
>Initializes a new @Service@ instance.
3064
3065
3066
3067
h3. Policy
3068
3069
3070
Implemented in [browser:sipsimple/xcap/+init+.py]
3071
3072
@Policy@ is the base class for @PresencePolicy@ and @DialoginfoPolicy@. It describes the attributes common to both.
3073
3074
3075
h4. attributes
3076
3077
3078
*id*
3079
>A string containing the unique identifier of this specific policy. While it should not be considered human readable, OMA does assign specific meanings to some IDs.
3080
3081
*action*
3082
>A string having one of the values @"allow"@, @"confirm"@, @"polite-block"@ or @"block"@.
3083
3084
*validity*
3085
>Either @None@, or a list of @datetime@ instance 2-tuples representing the intervals when this policy applies. Example valid validity list which represents two intervals, each of two hours:
3086
  <pre>
3087 1 Adrian Georgescu
  from datetime import datetime, timedelta
3088
  now = datetime.now()
3089
  one_hour = timedelta(seconds=3600)
3090
  one_day = timedelta(days=1)
3091
  validity = [(now-one_hour, now+one_hour), (now+one_day-one_hour, now+one_day+one_hour)]
3092 147 Adrian Georgescu
</pre>
3093 1 Adrian Georgescu
3094 147 Adrian Georgescu
*sphere*
3095
>Either @None@ or a string representing the sphere of presentity when this policy applies.
3096 1 Adrian Georgescu
3097 147 Adrian Georgescu
*multi_identity_conditions*
3098
>Either @None@ or a list of @CatchAllCondition@ or @DomainCondition@ objects as defined below. This is used to apply this policy to multiple users.
3099 1 Adrian Georgescu
3100
3101 147 Adrian Georgescu
h4. methods
3102 1 Adrian Georgescu
3103
3104 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *id*, *action*, *name*=@None@, *validity*=@None@, *sphere*=@None@, *multi_identity_conditions*=@None@)
3105
>Initializes a new @Policy@ instance.
3106 1 Adrian Georgescu
3107 147 Adrian Georgescu
*check_validity*(_self_, *timestamp*, *sphere*=@Any@)
3108
>Returns a boolean indicating whether this policy applies at the specific moment given by timestamp (which must be a @datetime@ instance) in the context of the specific sphere.
3109 1 Adrian Georgescu
3110
3111
3112 147 Adrian Georgescu
h3. CatchAllCondition
3113 1 Adrian Georgescu
3114
3115 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
3116 1 Adrian Georgescu
3117 147 Adrian Georgescu
@CatchAllCondition@ represents a condition which matches any user, but which can have some exceptions.
3118 1 Adrian Georgescu
3119
3120 147 Adrian Georgescu
h4. attributes
3121 1 Adrian Georgescu
3122
3123 147 Adrian Georgescu
*exceptions*
3124
>A list containing @DomainException@ or @UserException@ objects to define when this condition does not apply.
3125 1 Adrian Georgescu
3126
3127 147 Adrian Georgescu
h4. methods
3128 1 Adrian Georgescu
3129
3130 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *exceptions*=@None@)
3131
>Initializes a new @CatchAllCondition@ instance.
3132 1 Adrian Georgescu
3133
3134
3135 147 Adrian Georgescu
h3. DomainCondition
3136 1 Adrian Georgescu
3137
3138 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
3139 1 Adrian Georgescu
3140 147 Adrian Georgescu
@DomainCondition@ represents a condition which matches any user within a specified domain, but which can have some exceptions.
3141 1 Adrian Georgescu
3142
3143 147 Adrian Georgescu
h4. attributes
3144 1 Adrian Georgescu
3145
3146 147 Adrian Georgescu
*domain*
3147
>A string containing the domain for which this condition applies.
3148 1 Adrian Georgescu
3149 147 Adrian Georgescu
*exceptions*
3150
>A list containing @UserEception@ objects to define when this condition does not apply.
3151 1 Adrian Georgescu
3152
3153
3154 147 Adrian Georgescu
h4. methods
3155 1 Adrian Georgescu
3156
3157 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *domain*, *exceptions*=@None@)
3158
>Initializes a new @DomainCondition@ instance.
3159 1 Adrian Georgescu
3160
3161
3162 147 Adrian Georgescu
h3. DomainException
3163 1 Adrian Georgescu
3164
3165 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
3166 1 Adrian Georgescu
3167 147 Adrian Georgescu
@DomainException@ is used as an exception for a @CatchAllCondition@ which excludes all users within a specified domain.
3168 1 Adrian Georgescu
3169
3170 147 Adrian Georgescu
h4. attributes
3171
3172
3173
*domain*
3174
>A string containing the domain which is to be excluded from the @CatchAllCondition@ containing this object as an exception.
3175
3176
3177
3178
h4. methods
3179
3180
3181
*<notextile>__init__</notextile>*(_self_, *domain*)
3182
>Initializes a new @DomainException@ instance.
3183
3184
3185
3186
h3. UserException
3187
3188
3189
Implemented in [browser:sipsimple/xcap/+init+.py]
3190
3191
@UserException@ is used as an exception for either a @CatchAllCondition@ or a @DomainCondition@ and excludes a user identified by an URI.
3192
3193
3194
h4. attributes
3195
3196
3197
*uri*
3198
>A string containing the URI which is to be excluded from the @CatchAllCondition@ or @DomainCondition@ containing this object as an exception.
3199
3200
3201
3202
h4. methods
3203
3204
3205
*<notextile>__init__</notextile>*(_self_, *uri*)
3206
>Initializes a new @UserException@ instance.
3207
3208
3209
3210
h3. PresencePolicy
3211
3212
3213
Implemented in [browser:sipsimple/xcap/+init+.py]
3214
3215
A @PresencePolicy@ represents either a @org.openmobilealliance.pres-rules@ or @pres-rules@ rule. It subclasses @Policy@ and inherits its attributes, but defines additional
3216 1 Adrian Georgescu
attributes corresponding to the transformations which can be specified in a rule.
3217
3218
3219 147 Adrian Georgescu
h4. attributes
3220 1 Adrian Georgescu
3221
3222 147 Adrian Georgescu
 All of the following attributes only make sense for a policy having a @"allow"@ action.
3223 1 Adrian Georgescu
3224 147 Adrian Georgescu
*provide_devices*
3225
>Either @sipsimple.util.All@, or a list of @Class@, @OccurenceID@ or @DeviceID@ objects as defined below.
3226 1 Adrian Georgescu
3227 147 Adrian Georgescu
*provide_persons*
3228
>Either @sipsimple.util.All@, or a list of @Class@ or @OccurenceID@ objects as defined below.
3229 1 Adrian Georgescu
3230 147 Adrian Georgescu
*provide_services*
3231
>Either @sipsimple.util.All@, or a list of @Class@, @OccurenceID@, @ServiceURI@ or @ServiceURIScheme@ objects as defined below.
3232 1 Adrian Georgescu
3233 147 Adrian Georgescu
*provide_activities*
3234
>Either @None@ (if the transformation is not be specified) or a boolean.
3235 1 Adrian Georgescu
3236 147 Adrian Georgescu
*provide_class*
3237
>Either @None@ (if the transformation is not be specified) or a boolean.
3238 1 Adrian Georgescu
3239 147 Adrian Georgescu
*provide_device_id*
3240
>Either @None@ (if the transformation is not be specified) or a boolean.
3241 1 Adrian Georgescu
3242 147 Adrian Georgescu
*provide_mood*
3243
>Either @None@ (if the transformation is not be specified) or a boolean.
3244 1 Adrian Georgescu
3245 147 Adrian Georgescu
*provide_place_is*
3246
>Either @None@ (if the transformation is not be specified) or a boolean.
3247 1 Adrian Georgescu
3248 147 Adrian Georgescu
*provide_place_type*
3249
>Either @None@ (if the transformation is not be specified) or a boolean.
3250 1 Adrian Georgescu
3251 147 Adrian Georgescu
*provide_privacy*
3252
>Either @None@ (if the transformation is not be specified) or a boolean.
3253 1 Adrian Georgescu
3254 147 Adrian Georgescu
*provide_relationship*
3255
>Either @None@ (if the transformation is not be specified) or a boolean.
3256 1 Adrian Georgescu
3257 147 Adrian Georgescu
*provide_status_icon*
3258
>Either @None@ (if the transformation is not be specified) or a boolean.
3259 1 Adrian Georgescu
3260 147 Adrian Georgescu
*provide_sphere*
3261
>Either @None@ (if the transformation is not be specified) or a boolean.
3262 1 Adrian Georgescu
3263 147 Adrian Georgescu
*provide_time_offset*
3264
>Either @None@ (if the transformation is not be specified) or a boolean.
3265 1 Adrian Georgescu
3266 147 Adrian Georgescu
*provide_user_input*
3267
>Either @None@ (if the transformation is not be specified) or one of the strings @"false"@, @"bare"@, @"thresholds"@, @"full"@.
3268 1 Adrian Georgescu
3269 147 Adrian Georgescu
*provide_unknown_attributes*
3270
>Either @None@ (if the transformation is not be specified) or a boolean. The name of the attribute is not a typo, although it maps to the transformation named @provide-unknown-attribute@ (singular form).
3271 1 Adrian Georgescu
3272 147 Adrian Georgescu
*provide_all_attributes*
3273
>Either @None@ (if the transformation is not be specified) or a boolean.
3274 1 Adrian Georgescu
3275
3276 147 Adrian Georgescu
h4. methods
3277 1 Adrian Georgescu
3278
3279 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *id*, *action*, *name*=@None@, *validity*=@None@, *sphere*=@None@, *multi_identity_conditions*=@None@)
3280
>Initializes a new @PresencePolicy@ instance. The @provide_devices@, @provide_persons@ and @provide_services@ are initialized to @sipsimple.util.All@, @provide_all_attributes@ to @True@ and the rest to @None@.
3281
3282
3283
3284
h3. DialoginfoPolicy
3285
3286
3287
Implemented in [browser:sipsimple/xcap/+init+.py]
3288
3289
A @DialoginfoPolicy@ represents a @org.openxcap.dialog-rules@ rule. It subclasses @Policy@ and inherits all of its attributes. It does not add any other attributes or methods and thus
3290 1 Adrian Georgescu
has an identical API.
3291
3292
3293
3294 147 Adrian Georgescu
h3. Icon
3295 1 Adrian Georgescu
3296
3297 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
3298 1 Adrian Georgescu
3299 147 Adrian Georgescu
An @Icon@ instance represents a status icon stored using the @org.openmobilealliance.pres-content@ application.
3300 1 Adrian Georgescu
3301
3302 147 Adrian Georgescu
h4. attributes
3303 1 Adrian Georgescu
3304
3305 147 Adrian Georgescu
*data*
3306
>The binary data of the image, as  a string.
3307 1 Adrian Georgescu
3308 147 Adrian Georgescu
*mime_type*
3309
>The MIME type of the image, one of @image/jpeg@, @image/gif@ or @image/png@.
3310 1 Adrian Georgescu
3311 147 Adrian Georgescu
*description*
3312
>An optional description of the icon.
3313 1 Adrian Georgescu
3314 147 Adrian Georgescu
*location*
3315
>An HTTP(S) URI which can be used by other users to download the status icon of the local user. If the XCAP server returns the proprietary X-AGP-Alternative-Location header in its GET and PUT
3316
>responses, that is used otherwise the XCAP URI of the icon is used.
3317 1 Adrian Georgescu
3318
3319 147 Adrian Georgescu
h4. methods
3320 1 Adrian Georgescu
3321
3322 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *data*, *mime_type*, *description*=@None@, *location*=@None@)
3323
>Initializes a new @Icon@ instance.
3324 1 Adrian Georgescu
3325
3326
3327 147 Adrian Georgescu
h3. OfflineStatus
3328 1 Adrian Georgescu
3329
3330 147 Adrian Georgescu
Implemented in [browser:sipsimple/xcap/+init+.py]
3331 1 Adrian Georgescu
3332 147 Adrian Georgescu
An @OfflineStatus@ instance represents data stored using the @pidf-manipulation@ application.
3333 1 Adrian Georgescu
3334
3335 147 Adrian Georgescu
h4. attributes
3336 1 Adrian Georgescu
3337 147 Adrian Georgescu
3338
*activity*
3339
>A string representing an activity within a @person@ element.
3340
3341
*note*
3342
>A string stored as a note within a @person@ element.
3343
3344
3345
h4. methods
3346
3347
3348
*<notextile>__init__</notextile>*(_self_, *activity*=@None@, *note*=@Note@)
3349
>Initializes a new @OfflineStatus@ instance.
3350
3351
3352
3353
h3. XCAPManager
3354
3355
3356
Implemented in [browser:sipsimple/xcap/+init+.py]
3357
3358
The XCAPManager is the central entity used to manage resource via the XCAP protocol. It uses a storage factory provided by @SIPApplication@ through the @Storage API@. It has state machine as described in the following diagram:
3359
3360
!{ align=center}xcap-manager-state.png!
3361
3362
The @load@ method needs to be called just once in order to load the data from the cache. Once this is done, the @start@ and @stop@ methods can be called as needed. Initially in the @stopped@ state,
3363
the start method will result in a transition to the @initializing@ state. While in the @initializing@ state, the XCAP manager will try to connect to the XCAP server and retrieve the
3364
capabilities (@xcap-caps@ application). It will then initiate a SUBSCRIBE for the @xcap-diff@ event (if configured) and transition to the @fetching@ state. In the @fetching@ state, it
3365 1 Adrian Georgescu
will try retrieve all the documents from the XCAP server, also specifying the ETag of the last known version. If none of the documents changed and this is not the first fetch, it transitions to the
3366 147 Adrian Georgescu
@insync@ state. Otherwise, it inserts a @normalize@ operation at the beginning of the journal (described below) and transitions to the @updating@ state. In the @updating@ state, it
3367 1 Adrian Georgescu
applies the operations from the journal which were not applied yet on the currently known documents and tries to push the documents, specifying the Etag of the last known version. If an operation
3368 147 Adrian Georgescu
fails due to a document having been modified, it marks all the operations in the journal as not being applied and transitions to the @fetching@ state; if any other error occurs, the update is
3369
retried periodically. If the update succeeds, data is extracted from the documents and the @XCAPManagerDidReloadData@ notification is sent. The XCAPManager then transitions to the @insync@
3370
state. A call to the @stop@ method will result in a transition to the @stopping@ state, termination of any existing SUBSCRIBE dialog and a transition to the @stopped@ state.
3371 1 Adrian Georgescu
3372 147 Adrian Georgescu
Modifications to the settings which control the XCAPManager can result in either a transition to the @initializing@ state or the termination of any previous SUBSCRIBE dialog and creation of a new
3373 1 Adrian Georgescu
one.
3374
3375 147 Adrian Georgescu
The subscription to the @xcap-diff@ event allows the XCAPManager to be notified when the documents it manages are modified remotely. If the subscription fails, a fetch of all the documents is
3376
tried and the subscription is retried in some time. This allows the XCAPManager to reload the documents when they are modified remotely even if @xcap-diff@ event is not supported by the provider. If subscription for @xcap-diff@ event fails, a fetch of all the documents will be tried every 2 minutes.
3377 1 Adrian Georgescu
3378 147 Adrian Georgescu
The XCAPManager keeps the documents as they are stored on the XCAP server along with their ETags in an on-disk cache. All operations are made using the conditional @If-Match@ and
3379
@If-None-Match@ headers such that remote modifications the XCAPManager does not know about are not overwritten and bandwidth and processing power are not wasted by GET operations when a document
3380 1 Adrian Georgescu
is not modified.
3381
3382
Operations which the XCAPManager can be asked to apply to modify the documents are kept in a journal. This journal is saved to disk, such that operations which cannot be applied when requested due
3383
to server problems or lack of connectivity are retried even after application restarts. In addition, the high-level defined operations and the journal allow the modifications to be applied even if the
3384
document stored on the XCAP server are modified. Put differently, operations do depend on a specific version of the documents and the XCAPManager will try to apply them irrespective of the format
3385
of the document.
3386
3387
3388 147 Adrian Georgescu
h4. configuration
3389 1 Adrian Georgescu
3390
3391 147 Adrian Georgescu
*Account.id*, *Account.auth.username*, *Account.auth.password*
3392
>These are used both for the @xcap-diff@ subscription and the XCAP server connection. 
3393
3394
*Account.sip.subscribe_interval*
3395
>This controls the Expires header used for the subscription, although a 423 response from the server can result in a larger Expires value being used.
3396
3397
*Account.xcap.xcap_root*
3398
>This specifies the XCAP root used for contacting the XCAP server and managing the resources. If this setting is @None@, a TXT DNS query is made for the @xcap@ subdomain of the SIP account's
3399
>domain. The result is interpreted as being an XCAP root. Example record for account alice@example.org:
3400
  <pre>
3401 1 Adrian Georgescu
  xcap.example.org.    IN  TXT     "https://xcap.example.org/xcap-root"
3402 147 Adrian Georgescu
</pre>
3403 1 Adrian Georgescu
3404 147 Adrian Georgescu
*SIPSimpleSettings.sip.transport_list*
3405
>This controls the transports which can be used for the subscription.
3406 1 Adrian Georgescu
3407
3408 147 Adrian Georgescu
h4. methods
3409 1 Adrian Georgescu
3410
3411 147 Adrian Georgescu
*<notextile>__init__</notextile>*(_self_, *account*)
3412
>Initializes an XCAPManager for the specified account.
3413 1 Adrian Georgescu
3414 147 Adrian Georgescu
*load*(_self_)
3415
>Allows the XCAPManager to the load its internal data from cache.
3416 1 Adrian Georgescu
3417 147 Adrian Georgescu
*start*(_self_)
3418
>Starts the XCAPManager. This will result in the subscription being started, the XCAP server being contacted and any operations in the journal being applied. This method must be called in a green
3419
>thread.
3420 1 Adrian Georgescu
3421 147 Adrian Georgescu
*stop*(_self_)
3422
>Stops the XCAPManager from performing any tasks. Waits until the @xcap-diff@ subscription, if any, is terminated. This method must be called in a green thread.
3423 1 Adrian Georgescu
3424 147 Adrian Georgescu
*start_transaction*(_self_)
3425
>This allows multiple operations to be queued and not applied immediately. All operations queued after a call to this method will not be applied until the @commit_transaction@ method is called.
3426
>This does not have the same meaning as a relational database transaction, since there is no @rollback@ operation.
3427
3428
*commit_transaction*(_self_)
3429
>Applies the modifications queued after a call to @start_transaction@. This method needs to be called the exact same number of times the @start_transaction@ method was called. Does not have
3430
>any effect if @start_transaction@ was not previously called.
3431
3432 1 Adrian Georgescu
 The following methods results in XCAP operations being queued on the journal:
3433
3434 147 Adrian Georgescu
*add_group*(_self_, *group*)
3435
>Add a contact group with the specified name.
3436 1 Adrian Georgescu
3437 147 Adrian Georgescu
*rename_group*(_self_, *old_name*, *new_name*)
3438
>Change the name of the contact group @old_name@ to @new_name@. If such a contact group does not exist, the operation does not do anything.
3439 1 Adrian Georgescu
3440 147 Adrian Georgescu
*remove_group*(_self_, *group*)
3441
>Remove the contact group (and any contacts contained in it) with the specified name. If such a contact group does not exist, the operation does not do anything.
3442 1 Adrian Georgescu
3443 147 Adrian Georgescu
*add_contact*(_self_, *contact*)
3444
>Adds a new contact, described by a @Contact@ object. If the contact with the same URI and a not-@None@ group already exists, the operation does not do anything. Otherwise, the contact
3445
>is added and any reference to the contact's URI is overwritten. Requests to add a contact to some OMA reserved presence policies (@wp_prs_unlisted@, @wp_prs_allow_unlisted@,
3446
  @wp_prs_block_anonymous@, @wp_prs_allow_own@) is ignored.
3447 1 Adrian Georgescu
3448 147 Adrian Georgescu
*update_contact*(_self_, *contact*, ***attributes*)
3449
>Modifies a contact's properties. The keywords can be any of the @Contact@ attributes, with the same meaning. The URI of the contact to be modified is taken from the first argument. If such
3450
>a URI does not exist, it is added. Requests to add a contact to some OMA reserved presence policies (@wp_prs_unlisted@, @wp_prs_allow_unlisted@, @wp_prs_block_anonymous@,
3451
  @wp_prs_allow_own@) is ignored. The URI of a contact can be changed by specified the keyword argument @uri@ with the new value.
3452 1 Adrian Georgescu
3453 147 Adrian Georgescu
*remove_contact*(_self_, *contact*)
3454
>Removes any reference to the contact's URI from all documents. This also means that the operation will make sure there are no policies which match the contact's URI.
3455 1 Adrian Georgescu
3456 147 Adrian Georgescu
*add_presence_policy*(_self_, *policy*)
3457
>Adds a new presence policy, described by a @PresencePolicy@ object. If the id is specified and a policy with the same id exists, the operation does not do anything. Otherwise, if the id is not
3458
>specified, one will be automatically generated (recommended). If the id is specified, but it is incompatible with the description of the policy (for example if an OMA defined id is used and there
3459
>are some multi_identity_conditions), a new one will be automatically generated.
3460 1 Adrian Georgescu
3461 147 Adrian Georgescu
*update_presence_policy*(_self_, *policy*, ***attributes*)
3462
>Modifies a presence policy's properties. The keywords can be any of the @PresencePolicy@ attributes, with the same meaning. The id of the policy to be modified is taken from the first argument.
3463
>If such a policy does not exist and there is sufficient information about the policy, it is added. If the policy to be modified uses the OMA extension to reference resource-lists and
3464
>multi_identity_conditions are specified in the keywords, a new policy whose properties are the combination of the existing policy and the keywords is created.
3465 1 Adrian Georgescu
3466 147 Adrian Georgescu
*remove_presence_policy*(_self_, *policy*)
3467
>Removes the presence policy identified by the id attribute of the @PresencePolicy@ object specified. If the id is @None@ or does not exist in the document, the operation does not do
3468
>anything. Some standard OMA policies (@wp_prs_unlisted@, @wp_prs_allow_unlisted@, @wp_prs_block_anonymous@, @wp_prs_allow_own@, @wp_prs_grantedcontacts@,
3469
  @wp_prs_blockedcontacts@) cannot be removed.
3470 1 Adrian Georgescu
3471 147 Adrian Georgescu
*add_dialoginfo_policy*(_self_, *policy*)
3472
>Adds a new dialoginfo policy, described by a @DialoginfoPolicy@ object. If the id is specified and a policy with the same id exists, the operation does not do anything. Otherwise, if the id is
3473
>not specified, one will be automatically generated (recommended).
3474 1 Adrian Georgescu
3475 147 Adrian Georgescu
*update_dialoginfo_policy*(_self_, *policy*, ***attributes*)
3476
>Modifies a dialoginfo policy's properties. The keywords can be any of the @DialoginfoPolicy@ attributes, with the same meanining. The id of the policy to be modified is taken from the first
3477
>argument. If such a policy does not exist and there is sufficient information about the policy, it is added.
3478 1 Adrian Georgescu
3479 147 Adrian Georgescu
*remove_dialoginfo_policy*(_self_, *policy*)
3480
>Removes the dialoginfo policy identified by the id attribute of the @DialoginfoPolicy@ object specified. If the id is @None@ or does not exist in the document, the operation does not do
3481
>anything.
3482 1 Adrian Georgescu
3483 147 Adrian Georgescu
*set_status_icon*(_self_, *icon*)
3484
>Sets the status icon using the information from the @Icon@ object specified. The @location@ attribute is ignored. The MIME type must be one of @image/gif@, @image/png@ or
3485
  @image/jpeg@. If the argument is @None@, the status icon is deleted.
3486 1 Adrian Georgescu
3487 147 Adrian Georgescu
*set_offline_status*(_self_, *status*)
3488
>Sets the offline status using the information from the @OfflineStatus@ object specified. If the argument is @None@, the offline status document is deleted.
3489 1 Adrian Georgescu
3490
3491 147 Adrian Georgescu
h4. notifications
3492 1 Adrian Georgescu
3493
3494 147 Adrian Georgescu
*XCAPManagerWillStart*
3495
>This notification is sent just after calling the @start@ method.
3496
  
3497
timestamp:
3498 1 Adrian Georgescu
3499 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
3500 1 Adrian Georgescu
3501 147 Adrian Georgescu
*XCAPManagerDidStart*
3502
>This notification is sent after the XCAPManager has started doing its tasks (contacting the XCAP server, subscribing to @xcap-diff@ event). This notification does not mean that
3503
>any of these operations were successful, as the XCAPManager will retry them continuously should they fail.
3504
  
3505
timestamp:
3506 1 Adrian Georgescu
3507 147 Adrian Georgescu
>A @datetime.datetime@ object indicating when the notification was sent.
3508 1 Adrian Georgescu
3509 147 Adrian Georgescu
*XCAPManagerWillEnd*
3510
>This notification is sent just after calling the @stop@ method.
3511
  
3512
timestamp:
3513
3514
>A @datetime.datetime@ object indicating when the notification was sent.
3515
3516
*XCAPManagerDidEnd*
3517
>This notification is sent when the XCAPManager has stopped performing any tasks. This also means that any active @xcap-diff@ subscription has been terminated.
3518
  
3519
timestamp:
3520
3521
>A @datetime.datetime@ object indicating when the notification was sent.
3522
3523
*XCAPManagerDidDiscoverServerCapabilities*
3524
>This notification is sent when the XCAPManager contacts an XCAP server for the first time or after the connection is reset due to configuration changes. The data of the notification contains
3525
>information about the server's capabilities (obtained using the @xcap-caps@ application).
3526
  
3527
contactlist_supported:
3528
3529
>A boolean indicating the support of documents needed for contact management (@resource-lists@ and @rls-services@).
3530
  
3531
presence_policies_supported:
3532
3533
>A boolean indicating the support of documents needed for presence policy management (@org.openmobilealliance.pres-rules@ or @pres-rules@).
3534
  
3535
dialoginfo_policies_supported:
3536
3537
>A boolean indicating the support of documents needed for dialoginfo policy management (@org.openxcap.dialog-rules@).
3538
  
3539
status_icon_supported:
3540
3541
>A boolean indicating the support of documents needed for status icon management (@org.openmobilealliance.pres-content@).
3542
  
3543
offline_status_supported:
3544
3545
>A boolean indicating the support of documents needed for offline status management (@pidf-manipulation@).
3546
  
3547
timestamp:
3548
3549
>A @datetime.datetime@ object indicating when the notification was sent.
3550
3551
*XCAPManagerDidReloadData*
3552
>This notification is sent when the XCAPManager synchronizes with the XCAP server. The data of the notification contains objects representing the data as it is stored on the XCAP server.
3553
  
3554
contacts:
3555
3556
>A list of @Contact@ objects.
3557
  
3558
groups:
3559
3560
>A list of strings.
3561
  
3562
services:
3563
3564
>A list of @Service@ objects.
3565
  
3566
presence_policies:
3567
3568
>A list of @PresencePolicy@ objects.
3569
  
3570
dialoginfo_policies:
3571
3572
>A list of @DialoginfoPolicy@ objects.
3573
  
3574
status_icon:
3575
3576
>A @StatusIcon@ object if one is stored, @None@ otherwise.
3577
  
3578
offline_status:
3579
3580
>A @OfflineStatus@ object if offline status information is stored, @None@ otherwise.
3581
  
3582
timestamp:
3583
3584
>A @datetime.datetime@ object indicating when the notification was sent.
3585
3586
*XCAPManagerDidChangeState*
3587
>This notification is sent when the XCAPManager transitions from one state to another.
3588
  
3589
prev_state:
3590
3591
>The old state of the XCAPManager, a string.
3592
  
3593
state:
3594
3595
>The new state of the XCAPManager, a string.
3596
  
3597
timestamp:
3598
3599
>A @datetime.datetime@ object indicating when the notification was sent.