SipMiddlewareApi

Version 63 (Luci Stanescu, 03/26/2010 01:12 am)

1 1 Adrian Georgescu
= Middleware API =
2 1 Adrian Georgescu
3 1 Adrian Georgescu
[[TOC(WikiStart, Sip*, depth=3)]]
4 1 Adrian Georgescu
5 60 Adrian Georgescu
This chapter describes the event driven ''Middleware API'' that can be used by a developer to build a user interface for SIP SIMPLE client SDK.  
6 14 Adrian Georgescu
7 54 Adrian Georgescu
 * For sub-systems communications the Middleware uses the [http://pypi.python.org/pypi/python-application/ Notification Bus] provided by [http://pypi.python.org/pypi/python-application/ python-application]
8 49 Adrian Georgescu
 * For configuration the Middleware uses the [wiki:SipConfigurationAPI Configuration API] to access General and SIP account  settings
9 1 Adrian Georgescu
10 59 Adrian Georgescu
To see a working example for how to use Middleware, see the [http://sipsimpleclient.com/wiki/SipTesting#TestingGuide Command Line Tools] provided with the library.
11 59 Adrian Georgescu
12 53 Adrian Georgescu
[[Image(sipsimple-middleware.png, align=center, width=800)]]
13 1 Adrian Georgescu
14 62 Luci Stanescu
== High-level audio API ==
15 62 Luci Stanescu
16 62 Luci Stanescu
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:
17 62 Luci Stanescu
 * IAudioPort: an interface describing an object capable of producing and/or consuming audio data.
18 62 Luci Stanescu
 * AudioDevice: an object conforming to the IAudioPort interface which describes a physical audio device.
19 62 Luci Stanescu
 * AudioBridge: a collection of objects conforming to IAudioPort which connects all of them in a full mesh.
20 62 Luci Stanescu
 * WavePlayer: an object conforming to the IAudioPort interface which can playback the audio data from a {{{.wav}}} file.
21 62 Luci Stanescu
 * WaveRecorder: an object conforming to the IAudioPort interface which can record audio data to a {{{.wav}}} file.
22 62 Luci Stanescu
23 62 Luci Stanescu
=== IAudioPort ===
24 62 Luci Stanescu
25 62 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.
26 62 Luci Stanescu
27 62 Luci Stanescu
==== attributes ====
28 62 Luci Stanescu
29 62 Luci Stanescu
 '''mixer'''::
30 62 Luci Stanescu
  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.
31 62 Luci Stanescu
 '''consumer_slot'''::
32 62 Luci Stanescu
  An integer representing the slot (see [wiki:SipCoreApiDocumentation#AudioMixer AudioMixer]) which this object uses to consume audio data, or {{{None}}} if this object is not a consumer.
33 62 Luci Stanescu
 '''producer_slot'''::
34 62 Luci Stanescu
  An integer representing the slot (see [wiki:SipCoreApiDocumentation#AudioMixer AudioMixer]) which this object uses to produce audio data, or {{{None}}} if this object is not a producer.
35 62 Luci Stanescu
36 62 Luci Stanescu
==== notifications ====
37 62 Luci Stanescu
 
38 62 Luci Stanescu
 '''AudioPortDidChangeSlots'''::
39 62 Luci Stanescu
  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.
40 62 Luci Stanescu
  [[BR]]consumer_slot_changed:[[BR]]
41 62 Luci Stanescu
  A bool indicating whether the consumer slot was changed.
42 62 Luci Stanescu
  [[BR]]producer_slot_changed:[[BR]]
43 62 Luci Stanescu
  A bool indicating whether the producer slot was changed.
44 62 Luci Stanescu
  [[BR]]old_consumer_slot:[[BR]]
45 62 Luci Stanescu
  The old slot for consuming audio data. Only required if consumer_slot_changed is {{{True}}}.
46 62 Luci Stanescu
  [[BR]]new_consumer_slot:[[BR]]
47 62 Luci Stanescu
  The new slot for consuming audio data. Only required if consumer_slot_changed is {{{True}}}.
48 62 Luci Stanescu
  [[BR]]old_producer_slot:[[BR]]
49 62 Luci Stanescu
  The old slot for producing audio data. Only required if producer_slot_changed is {{{True}}}.
50 62 Luci Stanescu
  [[BR]]new_producer_slot:[[BR]]
51 62 Luci Stanescu
  The new slot for producing audio data. Only required if producer_slot_changed is {{{True}}}.
52 62 Luci Stanescu
53 62 Luci Stanescu
=== AudioDevice ===
54 62 Luci Stanescu
55 62 Luci Stanescu
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.
56 62 Luci Stanescu
57 62 Luci Stanescu
==== methods ====
58 62 Luci Stanescu
59 62 Luci Stanescu
 '''!__init!__'''(''self'', '''mixer''', '''input_muted'''={{{False}}}, '''output_muted'''={{{False}}}):
60 62 Luci Stanescu
  Instantiates a new AudioDevice which represents the physical device associated with the specified {{{AudioMixer}}}.
61 62 Luci Stanescu
  [[BR]]mixer:[[BR]]
62 62 Luci Stanescu
  The {{{AudioMixer}}} whose physical device this object represents.
63 62 Luci Stanescu
  [[BR]]input_muted:[[BR]]
64 62 Luci Stanescu
  A boolean which indicates whether this object should act as a producer of audio data.
65 62 Luci Stanescu
  [[BR]]output_muted:[[BR]]
66 62 Luci Stanescu
  A boolean which indicates whether this object should act as a consumer of audio data.
67 62 Luci Stanescu
68 62 Luci Stanescu
==== attributes ====
69 62 Luci Stanescu
70 62 Luci Stanescu
 '''input_muted'''::
71 62 Luci Stanescu
  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.
72 62 Luci Stanescu
 '''output_muted'''::
73 62 Luci Stanescu
  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.
74 62 Luci Stanescu
75 62 Luci Stanescu
=== AudioBridge ===
76 62 Luci Stanescu
77 62 Luci Stanescu
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}}}.
78 62 Luci Stanescu
> Note: although this is not enforced, there should never be any cycles when connecting {{{AudioBridges}}}.
79 62 Luci Stanescu
80 62 Luci Stanescu
==== methods ====
81 62 Luci Stanescu
82 62 Luci Stanescu
 '''!__init!__'''(''self'', '''mixer''')::
83 62 Luci Stanescu
  Instantiate a new {{{AudioBridge}}} which uses the specified {{{AudioMixer}}} for mixing.
84 62 Luci Stanescu
 '''add'''(''self'', '''port''')::
85 62 Luci Stanescu
  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.
86 62 Luci Stanescu
 '''remove'''(''self'', '''port''')::
87 62 Luci Stanescu
  Remove a port from this {{{AudioBridge}}}. The port must have previously been added to the {{{AudioBridge}}}, otherwise a {{{ValueError}}} is raised.
88 62 Luci Stanescu
89 62 Luci Stanescu
=== WavePlayer ===
90 62 Luci Stanescu
91 62 Luci Stanescu
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.
92 62 Luci Stanescu
93 62 Luci Stanescu
==== methods ====
94 62 Luci Stanescu
95 62 Luci Stanescu
 '''!__init!__'''(''self'', '''mixer''', '''filename''', '''volume'''={{{100}}}, '''loop_count'''={{{1}}}, '''pause_time'''={{{0}}}, '''initial_play'''={{{True}}})::
96 62 Luci Stanescu
  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.
97 62 Luci Stanescu
  [[BR]]mixer:[[BR]]
98 62 Luci Stanescu
  The {{{AudioMixer}}} this object is connected to.
99 62 Luci Stanescu
  [[BR]]filename:[[BR]]
100 62 Luci Stanescu
  The full path to the {{{.wav}}} file from which audio data is to be read.
101 62 Luci Stanescu
  [[BR]]volume:[[BR]]
102 62 Luci Stanescu
  The volume at which the file should be played.
103 62 Luci Stanescu
  [[BR]]loop_count:[[BR]]
104 62 Luci Stanescu
  The number of times the file should be played, or {{{0}}} for infinity.
105 62 Luci Stanescu
  [[BR]]pause_time:[[BR]]
106 62 Luci Stanescu
  How many seconds to wait between successive plays of the file. 
107 62 Luci Stanescu
  [[BR]]initial_play:[[BR]]
108 62 Luci Stanescu
  Whether or not the file to play once the {{{WavePlayer}}} is started, or to wait {{{pause_time}}} seconds before the first play.
109 62 Luci Stanescu
 '''start'''(''self'')::
110 62 Luci Stanescu
  Start playing the {{{.wav}}} file.
111 62 Luci Stanescu
 '''stop'''(''self'')::
112 62 Luci Stanescu
  Stop playuing the {{{.wav}}} file immediately.
113 62 Luci Stanescu
114 62 Luci Stanescu
==== attributes ====
115 62 Luci Stanescu
116 62 Luci Stanescu
 '''is_active'''::
117 62 Luci Stanescu
  A boolean indicating whether or not this {{{WavePlayer}}} is currently playing.
118 62 Luci Stanescu
119 62 Luci Stanescu
==== notifications ====
120 62 Luci Stanescu
121 62 Luci Stanescu
 '''WavePlayerDidStart'''::
122 62 Luci Stanescu
  This notification is sent when the {{{WavePlayer}}} starts playing the file the first time after the {{{start()}}} method has been called.
123 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
124 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
125 62 Luci Stanescu
 '''WavePlayerDidEnd'''::
126 62 Luci Stanescu
  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.
127 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
128 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
129 62 Luci Stanescu
 '''WavePlayerDidFail'''::
130 62 Luci Stanescu
  This notification is sent when the {{{WavePlayer}}} is not capable of playing the {{{.wav}}} file.
131 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
132 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
133 62 Luci Stanescu
  [[BR]]error:[[BR]]
134 62 Luci Stanescu
  The exception raised by the {{{WaveFile}}} which identifies the cause for not being able to play the {{{.wav}}} file.
135 62 Luci Stanescu
136 62 Luci Stanescu
=== WaveRecorder ===
137 62 Luci Stanescu
138 62 Luci Stanescu
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.
139 62 Luci Stanescu
140 62 Luci Stanescu
==== methods ====
141 62 Luci Stanescu
142 62 Luci Stanescu
 '''!__init!__'''(''self'', '''mixer''', '''filename''')::
143 62 Luci Stanescu
  Instantiate a new {{{WaveRecorder}}}.
144 62 Luci Stanescu
  [[BR]]mixer:[[BR]]
145 62 Luci Stanescu
  The {{{AudioMixer}}} this {{{WaveRecorder}}} is connected to.
146 62 Luci Stanescu
  [[BR]]filename:[[BR]]
147 62 Luci Stanescu
  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.
148 62 Luci Stanescu
 '''start'''(''self'')::
149 62 Luci Stanescu
  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.
150 62 Luci Stanescu
 '''stop'''(''self'')::
151 62 Luci Stanescu
  Stop consuming audio data and close the {{{.wav}}} file.
152 62 Luci Stanescu
153 62 Luci Stanescu
==== attributes ====
154 62 Luci Stanescu
155 62 Luci Stanescu
 '''is_active'''::
156 62 Luci Stanescu
  A boolean indicating whether or not this {{{WaveRecorder}}} is currently recording audio data.
157 62 Luci Stanescu
158 1 Adrian Georgescu
== SIPApplication ==
159 1 Adrian Georgescu
160 62 Luci Stanescu
Implemented in [browser:sipsimple/application.py]
161 1 Adrian Georgescu
162 62 Luci Stanescu
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:
163 62 Luci Stanescu
 * the twisted thread
164 62 Luci Stanescu
 * the configuration system, via the [wiki:SipConfigurationAPI#ConfigurationManager ConfigurationManager].
165 62 Luci Stanescu
 * the core [wiki:SipCoreApiDocumentation#Engine Engine] using the settings in the configuration
166 62 Luci Stanescu
 * the [wiki:SipMiddlewareApi#AccountManager AccountManager], using the accounts in the configuration
167 63 Luci Stanescu
 * the [wiki:SipMiddlewareApi#SessionManager SessionManager], in order to handle incoming sessions
168 62 Luci Stanescu
 * two [wiki:SipMiddlewareApi#AudioBridge AudioBridges], using the settings in the configuration
169 1 Adrian Georgescu
170 62 Luci Stanescu
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.
171 1 Adrian Georgescu
172 62 Luci Stanescu
=== Methods  ===
173 62 Luci Stanescu
174 62 Luci Stanescu
 '''!__init!__'''(''self'')::
175 62 Luci Stanescu
  Instantiates a new SIPApplication.
176 62 Luci Stanescu
 '''start'''(''self'', '''config_backend''')::
177 62 Luci Stanescu
  Starts the {{{SIPApplication}}} which initializes all the components in the correct order. The {{{config_backend}}} is used to start the {{{ConfigurationManager}}}. 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.
178 62 Luci Stanescu
 '''stop'''(''self'')::
179 62 Luci Stanescu
  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.
180 62 Luci Stanescu
181 1 Adrian Georgescu
=== Attributes ===
182 1 Adrian Georgescu
183 62 Luci Stanescu
 '''running'''::
184 62 Luci Stanescu
  {{{True}}} if the SIPApplication is running (it has been started and it has not been told to stop), {{{False}}} otherwise.
185 62 Luci Stanescu
 '''alert_audio_mixer'''::
186 62 Luci Stanescu
  The {{{AudioMixer}}} object created on the alert audio device as defined by the configuration (by SIPSimpleSettings.audio.alert_device).
187 62 Luci Stanescu
 '''alert_audio_bridge'''::
188 62 Luci Stanescu
  An {{{AudioBridge}}} where {{{IAudioPort}}} objects can be added to playback sound to the alert device.
189 62 Luci Stanescu
 '''alert_audio_device'''::
190 62 Luci Stanescu
  An {{{AudioDevice}}} which corresponds to the alert device as defined by the configuration. This will always be part of the alert_audio_bridge.
191 62 Luci Stanescu
 '''voice_audio_mixer'''::
192 62 Luci Stanescu
  The {{{AudioMixer}}} object created on the voice audio device as defined by the configuration (by SIPSimpleSettings.audio.input_device and SIPSimpleSettings.audio.output_device).
193 62 Luci Stanescu
 '''voice_audio_bridge'''::
194 62 Luci Stanescu
  An {{{AudioBridge}}} where {{{IAudioPort}}} objects can be added to playback sound to the output device or record sound from the input device.
195 62 Luci Stanescu
 '''voice_audio_device'''::
196 62 Luci Stanescu
  An {{{AudioDevice}}} which corresponds to the voice device as defined by the configuration. This will always be part of the voice_audio_bridge.
197 1 Adrian Georgescu
198 1 Adrian Georgescu
=== Notifications  ===
199 62 Luci Stanescu
200 62 Luci Stanescu
 '''SIPApplicationWillStart'''::
201 62 Luci Stanescu
  This notification is sent just after the configuration has been loaded and the twisted thread started, but before any other components have been initialized.
202 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
203 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
204 62 Luci Stanescu
 '''SIPApplicationDidStart'''::
205 62 Luci Stanescu
  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.
206 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
207 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
208 62 Luci Stanescu
 '''SIPApplicationWillEnd'''::
209 62 Luci Stanescu
  This notification is sent as soon as the {{{stop()}}} method has been called.
210 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
211 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
212 62 Luci Stanescu
 '''SIPApplicationDidEnd'''::
213 62 Luci Stanescu
  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).
214 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
215 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
216 62 Luci Stanescu
 '''SIPApplicationFailedToStartTLS'''::
217 62 Luci Stanescu
  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.
218 62 Luci Stanescu
  [[BR]]timestamp:[[BR]]
219 62 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
220 62 Luci Stanescu
  [[BR]]error:[[BR]]
221 62 Luci Stanescu
  The exception raised by the Engine which identifies the cause for not being able to start the TLS transport.
222 50 Adrian Georgescu
223 1 Adrian Georgescu
224 63 Luci Stanescu
== SIP Sessions ==
225 1 Adrian Georgescu
226 63 Luci Stanescu
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.
227 63 Luci Stanescu
228 63 Luci Stanescu
=== Session ===
229 63 Luci Stanescu
230 51 Adrian Georgescu
[[Image(sipsimple-session-state-machine.png, align=right, width=400)]]
231 44 Adrian Georgescu
232 1 Adrian Georgescu
Implemented in [browser:sipsimple/session.py]
233 1 Adrian Georgescu
234 26 Luci Stanescu
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.
235 1 Adrian Georgescu
236 1 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.
237 1 Adrian Georgescu
State changes are triggered by methods called on the object by the application or by received network events.
238 2 Adrian Georgescu
These states and their transitions are represented in the following diagram:
239 1 Adrian Georgescu
240 63 Luci Stanescu
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.
241 1 Adrian Georgescu
242 63 Luci Stanescu
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.
243 63 Luci Stanescu
244 63 Luci Stanescu
==== methods ====
245 63 Luci Stanescu
246 63 Luci Stanescu
 '''!__init!__'''(''self'', '''account''')::
247 63 Luci Stanescu
  Creates a new {{{Session}}} object in the {{{None}}} state.
248 63 Luci Stanescu
  [[BR]]''account'':[[BR]]
249 63 Luci Stanescu
  The local account to be associated with this {{{Session}}}.
250 63 Luci Stanescu
 '''connect'''(''self'', '''to_header''', '''routes''', '''streams''')::
251 63 Luci Stanescu
  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.
252 63 Luci Stanescu
  Before contacting the remote party, a {{{SIPSessionNewOutgoing}}} notification will be emitted.
253 63 Luci Stanescu
  If there is a failure or the remote party rejected the offer, a {{{SIPSessionDidFail}}} notification will be sent.
254 63 Luci Stanescu
  Any time a ringing indication is received from the remote party, a {{{SIPSessionGotRingIndication}}} notification is sent.
255 63 Luci Stanescu
  If the remote party accepted the session, a {{{SIPSessionWillStart}}} notification will be sent, followed by a {{{SIPSessionDidStart}}} notification when the session is actually established.
256 63 Luci Stanescu
  This method may only be called while in the {{{None}}} state.
257 63 Luci Stanescu
  [[BR]]''to_header'':[[BR]]
258 63 Luci Stanescu
  A {{{sipsimple.core.ToHeader}}} object representing the remote identity to initiate the session to.
259 63 Luci Stanescu
  [[BR]]''routes'':[[BR]]
260 63 Luci Stanescu
  An iterable of {{{sipsimple.util.Route}}} objects, specifying the IP, port and transport to the outbound proxy.
261 63 Luci Stanescu
  These routes will be tried in order, until one of them succeeds.
262 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
263 63 Luci Stanescu
  A list of stream objects which will be offered to the remote endpoint.
264 63 Luci Stanescu
 '''send_ring_indication'''(''self'')::
265 63 Luci Stanescu
  Sends a 180 provisional response in the case of an incoming session.
266 63 Luci Stanescu
 '''accept'''(''self'', '''streams''')::
267 63 Luci Stanescu
  Calling this methods will accept an incoming session and move the state machine to the {{{accepting}}} state.
268 63 Luci Stanescu
  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.
269 63 Luci Stanescu
  After this method is called, {{{SIPSessionWillStart}}} followed by {{{SIPSessionDidStart}}} will be emitted, or {{{SIPSessionDidFail}}} on an error.
270 63 Luci Stanescu
  This method may only be called while in the {{{incoming}}} state.
271 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
272 63 Luci Stanescu
  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.
273 63 Luci Stanescu
 '''reject'''(''self'', '''code'''={{{603}}}, '''reason'''={{{None}}})::
274 63 Luci Stanescu
  Reject an incoming session and move it to the {{{terminaing}}} state, which eventually leads to the {{{terminated}}} state.
275 63 Luci Stanescu
  Calling this method will cause the {{{Session}}} object to emit a {{{SIPSessionDidFail}}} notification once the session has been rejected.
276 63 Luci Stanescu
  This method may only be called while in the {{{incoming}}} state.
277 63 Luci Stanescu
  [[BR]]''code'':[[BR]]
278 63 Luci Stanescu
  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).
279 63 Luci Stanescu
  [[BR]]''reason'':[[BR]]
280 63 Luci Stanescu
  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.
281 63 Luci Stanescu
 '''accept_proposal'''(''self'', '''streams''')::
282 63 Luci Stanescu
  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.
283 63 Luci Stanescu
  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.
284 63 Luci Stanescu
  This method may only be called while in the {{{received_proposal}}} state.
285 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
286 63 Luci Stanescu
  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.
287 63 Luci Stanescu
 '''reject_proposal'''(''self'', '''code'''={{{488}}}, '''reason'''={{{None}}})::
288 63 Luci Stanescu
  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.
289 63 Luci Stanescu
  This method may only be called while in the {{{received_proposal}}} state.
290 63 Luci Stanescu
  [[BR]]''code'':[[BR]]
291 63 Luci Stanescu
  An integer which represents the SIP status code in the response which is to be sent. Usually, this is 488 (Not Acceptable Here).
292 63 Luci Stanescu
  [[BR]]''reason'':[[BR]]
293 63 Luci Stanescu
  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.
294 63 Luci Stanescu
 '''add_stream'''(''self'', '''stream''')::
295 63 Luci Stanescu
  Proposes a new stream to the remote party.
296 63 Luci Stanescu
  Calling this method will cause a {{{SIPSessionGotProposal}}} notification to be emitted.
297 63 Luci Stanescu
  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.
298 63 Luci Stanescu
  This method may only be called while in the {{{connected}}} state.
299 63 Luci Stanescu
 '''remove_stream'''(''self'', '''stream''')::
300 63 Luci Stanescu
  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).
301 63 Luci Stanescu
  This method may only be called while in the {{{connected}}} state.
302 63 Luci Stanescu
 '''cancel_proposal'''(''self'')::
303 63 Luci Stanescu
  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.
304 63 Luci Stanescu
 '''hold'''(''self'')::
305 63 Luci Stanescu
  Put the streams of the session which support the notion of hold on hold.
306 63 Luci Stanescu
  This will cause a {{{SIPSessionDidChangeHoldState}}} notification to be sent.
307 63 Luci Stanescu
  This method may be called in any state and will send the re-INVITE as soon as it is possible.
308 63 Luci Stanescu
 '''unhold'''(''self'')::
309 63 Luci Stanescu
  Take the streams of the session which support the notion of hold out of hold.
310 63 Luci Stanescu
  This will cause a {{{SIPSessionDidChangeHoldState}}} notification to be sent.
311 63 Luci Stanescu
  This method may be called in any state and will send teh re-INVITE as soon as it is possible.
312 63 Luci Stanescu
 '''end'''(''self'')::
313 63 Luci Stanescu
  This method may be called any time after the {{{Session}}} has started in order to terminate the session by sending a BYE request.
314 63 Luci Stanescu
  Right before termination a {{{SIPSessionWillEnd}}} notification is sent, after termination {{{SIPSessionDidEnd}}} is sent.
315 63 Luci Stanescu
316 1 Adrian Georgescu
=== Attributes ===
317 1 Adrian Georgescu
318 1 Adrian Georgescu
 '''state'''::
319 1 Adrian Georgescu
  The state the object is currently in, being one of the states from the diagram above.
320 1 Adrian Georgescu
 '''account'''::
321 1 Adrian Georgescu
  The {{{sipsimple.account.Account}}} or {{{sipsimple.account.BonjourAccount}}} object that the {{{Session}}} is associated with.
322 19 Ruud Klaver
  On an outbound session, this is the account the application specified on object instantiation.
323 1 Adrian Georgescu
 '''direction'''::
324 1 Adrian Georgescu
  A string indicating the direction of the initial negotiation of the session.
325 32 Adrian Georgescu
  This can be either {{{None}}}, "incoming" or "outgoing".
326 63 Luci Stanescu
 '''transport'''::
327 63 Luci Stanescu
  A string representing the transport this {{{Session}}} is using: {{{"udp"}}}, {{{"tcp"}}} or {{{"tls"}}}.
328 1 Adrian Georgescu
 '''start_time'''::
329 1 Adrian Georgescu
  The time the session started as a {{{datetime.datetime}}} object, or {{{None}}} if the session was not yet started.
330 1 Adrian Georgescu
 '''stop_time'''::
331 1 Adrian Georgescu
  The time the session stopped as a {{{datetime.datetime}}} object, or {{{None}}} if the session has not yet terminated.
332 1 Adrian Georgescu
 '''on_hold'''::
333 1 Adrian Georgescu
  Boolean indicating whether the session was put on hold, either by the local or the remote party.
334 1 Adrian Georgescu
 '''remote_user_agent'''::
335 1 Adrian Georgescu
  A string indicating the remote user agent, if it provided one.
336 1 Adrian Georgescu
  Initially this will be {{{None}}}, it will be set as soon as this information is received from the remote party (which may be never).
337 63 Luci Stanescu
 '''local_identity'''::
338 63 Luci Stanescu
  The {{{sipsimple.core.FrozenFromHeader}}} or {{{sipsimple.core.FrozenToHeader}}} identifying the local party, if the session is active, {{{None}}} otherwise.
339 63 Luci Stanescu
 '''remote_identity'''::
340 63 Luci Stanescu
  The {{{sipsimple.core.FrozenFromHeader}}} or {{{sipsimple.core.FrozenToHeader}}} identifying the remote party, if the session is active, {{{None}}} otherwise.
341 63 Luci Stanescu
 '''streams'''::
342 63 Luci Stanescu
  A list of the currently active streams in the {{{Session}}}.
343 63 Luci Stanescu
 '''proposed_streams'''::
344 63 Luci Stanescu
  A list of the currently proposed streams in the {{{Session}}}, or {{{None}}} if there is no proposal in progress.
345 1 Adrian Georgescu
346 1 Adrian Georgescu
=== Notifications ===
347 1 Adrian Georgescu
348 1 Adrian Georgescu
 '''SIPSessionNewIncoming'''::
349 26 Luci Stanescu
  Will be sent when a new incoming {{{Session}}} is received.
350 63 Luci Stanescu
  The application should listen for this notification to get informed of incoming sessions.
351 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
352 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
353 1 Adrian Georgescu
  [[BR]]''streams'':[[BR]]
354 63 Luci Stanescu
  A list of streams that were proposed by the remote party.
355 1 Adrian Georgescu
 '''SIPSessionNewOutgoing'''::
356 1 Adrian Georgescu
  Will be sent when the applcation requests a new outgoing {{{Session}}}.
357 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
358 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
359 1 Adrian Georgescu
  [[BR]]''streams'':[[BR]]
360 63 Luci Stanescu
  A list of streams that were proposed to the remote party.
361 1 Adrian Georgescu
 '''SIPSessionGotRingIndication'''::
362 1 Adrian Georgescu
  Will be sent when an outgoing {{{Session}}} receives an indication that a remote device is ringing.
363 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
364 26 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
365 63 Luci Stanescu
 '''SIPSessionGotProvisionalResponse'''::
366 63 Luci Stanescu
  Will be sent whenever the {{{Session}}} receives a provisional response as a result of sending a (re-)INVITE.
367 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
368 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
369 63 Luci Stanescu
  [[BR]]''code'':[[BR]]
370 63 Luci Stanescu
  The SIP status code received.
371 63 Luci Stanescu
  [[BR]]''reason'':[[BR]]
372 63 Luci Stanescu
  The SIP status reason received.
373 1 Adrian Georgescu
 '''SIPSessionWillStart'''::
374 1 Adrian Georgescu
  Will be sent just before a {{{Session}}} completes negotiation.
375 1 Adrian Georgescu
  In terms of SIP, this is sent after the final response to the {{{INVITE}}}, but before the {{{ACK}}}.
376 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
377 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
378 1 Adrian Georgescu
 '''SIPSessionDidStart'''::
379 63 Luci Stanescu
  Will be sent when a {{{Session}}} completes negotiation and all the streams have started.
380 26 Luci Stanescu
  In terms of SIP this is sent after the {{{ACK}}} was sent or received.
381 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
382 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
383 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
384 63 Luci Stanescu
  The list of streams which now form the active streams of the {{{Session}}}.
385 1 Adrian Georgescu
 '''SIPSessionDidFail'''::
386 63 Luci Stanescu
  This notification is sent whenever the session fails before it starts.
387 5 Redmine Admin
  The failure reason is included in the data attributes.
388 63 Luci Stanescu
  This notification is never followed by {{{SIPSessionDidEnd}}}.
389 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
390 26 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
391 1 Adrian Georgescu
  [[BR]]''originator'':[[BR]]
392 63 Luci Stanescu
  A string indicating the originator of the {{{Session}}}. This will either be "local" or "remote".
393 1 Adrian Georgescu
  [[BR]]''code'':[[BR]]
394 1 Adrian Georgescu
  The SIP error code of the failure.
395 1 Adrian Georgescu
  [[BR]]''reason'':[[BR]]
396 63 Luci Stanescu
  A SIP status reason.
397 63 Luci Stanescu
  [[BR]]''failure_reason'':[[BR]]
398 63 Luci Stanescu
  A string which represents the reason for the failure, such as {{{"user_request"}}}, {{{"missing ACK"}}}, {{{"SIP core error..."}}}.
399 1 Adrian Georgescu
 '''SIPSessionWillEnd'''::
400 63 Luci Stanescu
  Will be sent just before terminating a {{{Session}}}.
401 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
402 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
403 1 Adrian Georgescu
 '''SIPSessionDidEnd'''::
404 63 Luci Stanescu
  Will be sent always when a {{{Session}}} ends as a result of remote or local session termination.
405 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
406 19 Ruud Klaver
  A {{{datetime.datetime}}} object indicating when the notification was sent.
407 19 Ruud Klaver
  [[BR]]''originator'':[[BR]]
408 63 Luci Stanescu
  A string indicating who originated the termination. This will either be "local" or "remote".
409 63 Luci Stanescu
  [[BR]]''end_reason'':[[BR]]
410 63 Luci Stanescu
  A string representing the termination reason, such as {{{"user_request"}}}, {{{"SIP core error..."}}}.
411 63 Luci Stanescu
 '''SIPSessionDidChangeHoldState'''::
412 63 Luci Stanescu
  Will be sent when the session got put on hold or removed from hold, either by the local or the remote party.
413 1 Adrian Georgescu
  [[BR]]''timestamp'':[[BR]]
414 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
415 1 Adrian Georgescu
  [[BR]]''originator'':[[BR]]
416 1 Adrian Georgescu
  A string indicating who originated the hold request, and consequently in which direction the session got put on hold.
417 63 Luci Stanescu
  [[BR]]''on_hold'':[[BR]]
418 63 Luci Stanescu
  {{{True}}} if there is at least one stream which is on hold and {{{False}}} otherwise.
419 63 Luci Stanescu
  [[BR]]''partial'':[[BR]]
420 63 Luci Stanescu
  {{{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.
421 63 Luci Stanescu
 '''SIPSessionGotProposal'''::
422 63 Luci Stanescu
  Will be sent when either the local or the remote party proposes to add streams to the session.
423 26 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
424 23 Ruud Klaver
  A {{{datetime.datetime}}} object indicating when the notification was sent.
425 23 Ruud Klaver
  [[BR]]''originator'':[[BR]]
426 63 Luci Stanescu
  The party that initiated the stream proposal, can be either "local" or "remote".
427 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
428 63 Luci Stanescu
  A list of streams that were proposed.
429 63 Luci Stanescu
 '''SIPSessionGotRejectProposal'''::
430 63 Luci Stanescu
  Will be sent when either the local or the remote party rejects a proposal to have streams added to the session.
431 6 Ruud Klaver
  [[BR]]''timestamp'':[[BR]]
432 6 Ruud Klaver
  A {{{datetime.datetime}}} object indicating when the notification was sent.
433 63 Luci Stanescu
  [[BR]]''originator'':[[BR]]
434 63 Luci Stanescu
  The party that initiated the stream proposal, can be either "local" or "remote".
435 6 Ruud Klaver
  [[BR]]''code'':[[BR]]
436 63 Luci Stanescu
  The code with which the proposal was rejected.
437 1 Adrian Georgescu
  [[BR]]''reason'':[[BR]]
438 63 Luci Stanescu
  The reason for rejecting the stream proposal.
439 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
440 63 Luci Stanescu
  The list of streams which were rejected.
441 63 Luci Stanescu
 '''SIPSessionGotAcceptProposal'''::
442 63 Luci Stanescu
  Will be sent when either the local or the remote party accepts a proposal to have stream( added to the session.
443 24 Ruud Klaver
  [[BR]]''timestamp'':[[BR]]
444 1 Adrian Georgescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
445 63 Luci Stanescu
  [[BR]]''originator'':[[BR]]
446 63 Luci Stanescu
  The party that initiated the stream proposal, can be either "local" or "remote".
447 1 Adrian Georgescu
  [[BR]]''streams'':[[BR]]
448 63 Luci Stanescu
  The list of streams which were accepted.
449 63 Luci Stanescu
 '''SIPSessionHadProposalFailure'''::
450 63 Luci Stanescu
  Will be sent when a re-INVITE fails because of an internal reason (such as a stream not being able to start).
451 24 Ruud Klaver
  [[BR]]''timestamp'':[[BR]]
452 24 Ruud Klaver
  A {{{datetime.datetime}}} object indicating when the notification was sent.
453 63 Luci Stanescu
  [[BR]]''failure_reason'':[[BR]]
454 63 Luci Stanescu
  The error which caused the proposal to fail.
455 63 Luci Stanescu
  [[BR]]''streams'':[[BR]]
456 63 Luci Stanescu
  THe streams which were part of this proposal.
457 63 Luci Stanescu
 '''SIPSessionDidRenegotiateStreams'''::
458 24 Ruud Klaver
  Will be sent when a media stream is either activated or deactivated.
459 24 Ruud Klaver
  An application should listen to this notification in order to know when a media stream can be used.
460 6 Ruud Klaver
  [[BR]]''timestamp'':[[BR]]
461 26 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
462 63 Luci Stanescu
  [[BR]]''action'':[[BR]]
463 63 Luci Stanescu
  A string which is either {{{"add"}}} or {{{"remove"}}} which specifies what happened to the streams the notificaton referes to
464 6 Ruud Klaver
  [[BR]]''streams'':[[BR]]
465 63 Luci Stanescu
  A list with the streams which were added or removed.
466 63 Luci Stanescu
 '''SIPSessionDidProcessTransaction'''::
467 63 Luci Stanescu
  Will be sent whenever a SIP transaction is complete in order to provide low-level details of the progress of the INVITE dialog.
468 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
469 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
470 63 Luci Stanescu
  [[BR]]''originator'':[[BR]]
471 63 Luci Stanescu
  The initiator of the transaction, {{{"local"}}} or {{{"remote"}}}.
472 63 Luci Stanescu
  [[BR]]''method'':[[BR]]
473 63 Luci Stanescu
  The method of the request.
474 63 Luci Stanescu
  [[BR]]''code'':[[BR]]
475 63 Luci Stanescu
  The SIP status code of the response.
476 63 Luci Stanescu
  [[BR]]''reason'':[[BR]]
477 63 Luci Stanescu
  The SIP status reason of the response.
478 63 Luci Stanescu
  [[BR]]''ack_received'':[[BR]]
479 63 Luci Stanescu
  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.
480 1 Adrian Georgescu
481 1 Adrian Georgescu
As an example for how to use the {{{Session}}} object, the following provides a basic Python program that initiates an outgoing SIP session request:
482 1 Adrian Georgescu
483 1 Adrian Georgescu
{{{
484 1 Adrian Georgescu
from threading import Event
485 1 Adrian Georgescu
486 63 Luci Stanescu
from application.notification, NotificationCenter
487 63 Luci Stanescu
488 63 Luci Stanescu
from sipsimple.core import SIPURI, ToHeader
489 63 Luci Stanescu
490 1 Adrian Georgescu
from sipsimple.account import AccountManager
491 63 Luci Stanescu
from sipsimple.application import SIPApplication
492 6 Ruud Klaver
from sipsimple.session import Session
493 63 Luci Stanescu
from sipsimple.streams import AudioStream
494 63 Luci Stanescu
from sipsimple.util import Route
495 47 Adrian Georgescu
496 50 Adrian Georgescu
497 63 Luci Stanescu
class SimpleCallApplication(SIPApplication):
498 63 Luci Stanescu
    def __init__(self, callee, route):
499 63 Luci Stanescu
        SIPApplication.__init__(self)
500 63 Luci Stanescu
        self.ended = Event()
501 63 Luci Stanescu
        self.callee = calee
502 63 Luci Stanescu
        self.route = route
503 63 Luci Stanescu
        self.session = None
504 63 Luci Stanescu
        notification_center = NotificationCenter()
505 63 Luci Stanescu
        notification_center.add_observer(self)
506 30 Adrian Georgescu
507 63 Luci Stanescu
    def _NH_SIPApplicationDidStart(self, notification):
508 63 Luci Stanescu
        account = AccountManager().default_account
509 63 Luci Stanescu
        self.session = Session(account)
510 63 Luci Stanescu
        self.session.connect(self.callee, self.route, AudioStream(account))
511 30 Adrian Georgescu
512 63 Luci Stanescu
    def _NH_SIPSessionGotRingIndication(self, notification):
513 63 Luci Stanescu
        print 'Ringing!'
514 1 Adrian Georgescu
515 63 Luci Stanescu
    def _NH_SIPSessionDidStart(self, notification):
516 63 Luci Stanescu
        print 'Session started!'
517 63 Luci Stanescu
518 63 Luci Stanescu
    def _NH_SIPSessionDidFail(self, notification):
519 63 Luci Stanescu
        print 'Failed to connect'
520 63 Luci Stanescu
        self.stop()
521 63 Luci Stanescu
522 63 Luci Stanescu
    def _NH_SIPSessionDidEnd(self, notification):
523 63 Luci Stanescu
        print 'Session ended'
524 63 Luci Stanescu
        self.stop()
525 63 Luci Stanescu
526 63 Luci Stanescu
    def _NH_SIPApplicationDidEnd(self, notification):
527 63 Luci Stanescu
        self.ended.set()
528 63 Luci Stanescu
529 35 Luci Stanescu
# place an audio call from the specified account to the specified URI, through
530 35 Luci Stanescu
# the specified SIP proxy
531 63 Luci Stanescu
application = SimpleCallApplication(ToHeader(SIPURI(user="bob", host="example.com")), Route("1.2.3.4"))
532 37 Luci Stanescu
# block waiting for user input
533 39 Luci Stanescu
print "Placing call, press enter to quit program"
534 39 Luci Stanescu
raw_input()
535 63 Luci Stanescu
application.session.end()
536 63 Luci Stanescu
# block until the SIPApplication has stopped
537 63 Luci Stanescu
application.ended.wait()
538 1 Adrian Georgescu
}}}
539 35 Luci Stanescu
540 35 Luci Stanescu
== SessionManager ==
541 35 Luci Stanescu
542 35 Luci Stanescu
Implemented in [browser:sipsimple/session.py]
543 35 Luci Stanescu
544 35 Luci Stanescu
The {{{sipsimple.session.SessionManager}}} class is a singleton, which acts as the central aggregation point for sessions within the middleware.
545 35 Luci Stanescu
Although it is mainly used internally, the application can use it to query information about all active sessions.
546 63 Luci Stanescu
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.
547 39 Luci Stanescu
548 36 Luci Stanescu
=== Attributes ===
549 50 Adrian Georgescu
550 36 Luci Stanescu
 '''sessions'''::
551 36 Luci Stanescu
  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.
552 36 Luci Stanescu
553 1 Adrian Georgescu
=== Methods ===
554 1 Adrian Georgescu
555 1 Adrian Georgescu
 '''!__init!__'''(''self'')::
556 63 Luci Stanescu
  Instantiate a new {{{SessionManager}}} object.
557 1 Adrian Georgescu
558 63 Luci Stanescu
 '''start'''(''self'')::
559 63 Luci Stanescu
  Start the {{{SessionManager}}} in order to be able to handle incoming sessions.
560 1 Adrian Georgescu
561 63 Luci Stanescu
562 1 Adrian Georgescu
== Account ==
563 1 Adrian Georgescu
564 1 Adrian Georgescu
Implemented in [browser:sipsimple/account.py]
565 1 Adrian Georgescu
566 1 Adrian Georgescu
The {{{sipsimple.account.Account}}} objects represent the SIP accounts which are used by the middleware. 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 [wiki:SipConfigurationAPI#Account Configuration API].
567 1 Adrian Georgescu
568 1 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 [wiki:SipMiddlewareApi#AccountManager AccountManager]. The next sections will use a lowercase, monospaced {{{account}}} to represent an instance of {{{Account}}}.
569 1 Adrian Georgescu
570 1 Adrian Georgescu
=== States ===
571 1 Adrian Georgescu
572 1 Adrian Georgescu
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:
573 36 Luci Stanescu
{{{
574 36 Luci Stanescu
account.enabled = True
575 36 Luci Stanescu
account.save()
576 1 Adrian Georgescu
}}}
577 1 Adrian Georgescu
578 1 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.
579 1 Adrian Georgescu
580 1 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.
581 1 Adrian Georgescu
582 1 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:
583 1 Adrian Georgescu
584 1 Adrian Georgescu
 '''Account.registration.enabled'''::
585 1 Adrian Georgescu
  This flag controls the automatic registration of the account. The notifications '''SIPAccountRegistrationDidSucceed''', '''SIPAccountRegistrationDidFail''' and '''SIPAccountRegistrationDidEnd''' are used to inform the status of this registration.
586 1 Adrian Georgescu
 '''Account.presence.enabled'''::
587 1 Adrian Georgescu
  This flag controls the automatic subscription to buddies for the ''presence'' event and the publication of data in this event. (Not implemented yet)
588 1 Adrian Georgescu
 '''Account.dialog_event.enabled'''::
589 1 Adrian Georgescu
  This flag controls the automatic subscription to buddies for the ''dialog-info'' event and the publication of data in this event. (Not implemented yet)
590 1 Adrian Georgescu
 '''Account.message_summary.enabled'''::
591 1 Adrian Georgescu
  This flag controls the automatic subscription to the ''message-summary'' event in order to find out about voicemail messages. (Not implemented yet)
592 1 Adrian Georgescu
593 36 Luci Stanescu
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 [wiki:SipConfigurationAPI#SettingsObject SettingsObject].
594 36 Luci Stanescu
595 36 Luci Stanescu
=== Attributes ===
596 36 Luci Stanescu
597 1 Adrian Georgescu
The following attributes can be used on an Account object and need to be considered read-only.
598 1 Adrian Georgescu
599 1 Adrian Georgescu
 '''id'''::
600 1 Adrian Georgescu
  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}}}.
601 1 Adrian Georgescu
  {{{
602 1 Adrian Georgescu
  account.id # 'alice@example.com'
603 36 Luci Stanescu
  account.id.username # 'alice'
604 1 Adrian Georgescu
  account.id.domain # 'example.com'
605 1 Adrian Georgescu
  }}}
606 1 Adrian Georgescu
 '''contact'''::
607 1 Adrian Georgescu
  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.ContactURI}}} which is a subclass of {{{sipsimple.configuration.datatypes.SIPAddress}}}. In addition to the attributes defined in {{{SIPAddress}}}, it can be indexed by a string representing a transport ({{{'udp'}}}, {{{'tcp'}}} or {{{'tls'}}}) which will return a {{{sipsimple.core.SIPURI}}} object with the appropriate port and transport parameter. The username part is a randomly generated 8 character string consisting of lowercase letters; the domain part is the IP address on which the {{{Engine}}} is listening (as specified by the SIPSimpleSettings.local_ip setting).
608 1 Adrian Georgescu
  {{{
609 1 Adrian Georgescu
  account.contact # 'hnfkybrt@10.0.0.1'
610 1 Adrian Georgescu
  account.contact.username # 'hnfkybrt'
611 1 Adrian Georgescu
  account.contact.domain # '10.0.0.1'
612 1 Adrian Georgescu
  account.contact['udp'] # <SIPURI "sip:hnfkybrt@10.0.0.1:53024">
613 1 Adrian Georgescu
  account.contact['tls'] # <SIPURI "sip:hnfkybrt@10.0.0.1:54478;transport=tls">
614 1 Adrian Georgescu
  }}}
615 36 Luci Stanescu
 '''credentials'''::
616 1 Adrian Georgescu
  This attribute is of type {{{sipsimple.core.Credentials}}} object which is built from the {{{id}}} attribute and {{{display_name}}} and {{{password}}} settings of the Account. Whenever one of these settings are changed, this attribute is updated.
617 1 Adrian Georgescu
  {{{
618 1 Adrian Georgescu
  account.credentials # <Credentials for '"Alice" <sip:alice@example.com>'>
619 1 Adrian Georgescu
  }}}
620 1 Adrian Georgescu
621 1 Adrian Georgescu
=== Notifications ===
622 1 Adrian Georgescu
623 1 Adrian Georgescu
 '''CFGSettingsObjectDidChange'''::
624 1 Adrian Georgescu
  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 [wiki:SipConfigurationAPI#SettingsObjectNotifications SettingsObject Notifications].
625 36 Luci Stanescu
 '''SIPAccountDidActivate'''::
626 1 Adrian Georgescu
  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. The notification does not contain any data.
627 1 Adrian Georgescu
 '''SIPAccountDidDeactivate'''::
628 1 Adrian Georgescu
  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}}}. The notification does not contain any data.
629 1 Adrian Georgescu
 '''SIPAccountRegistrationDidSucceed'''::
630 1 Adrian Georgescu
  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:
631 1 Adrian Georgescu
  [[BR]]''code'':[[BR]]
632 36 Luci Stanescu
   The status code of the response for the REGISTER request.
633 36 Luci Stanescu
  [[BR]]''reason'':[[BR]]
634 36 Luci Stanescu
   The reason of the response for the REGISTER request.
635 36 Luci Stanescu
  [[BR]]''contact_uri'':[[BR]]
636 36 Luci Stanescu
   The Contact URI which was registered.
637 36 Luci Stanescu
  [[BR]]''contact_uri_list'':[[BR]]
638 36 Luci Stanescu
   A list containing all the contact URIs registered for this SIP account.
639 36 Luci Stanescu
  [[BR]]''expires'':[[BR]]
640 36 Luci Stanescu
   The amount in seconds in which this registration will expire.
641 36 Luci Stanescu
  [[BR]]''registration'':[[BR]]
642 37 Luci Stanescu
   The {{{sipsimple.core.Registration}}} object used to register this account.
643 50 Adrian Georgescu
 '''SIPAccountRegistrationDidFail'''::
644 37 Luci Stanescu
  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:
645 37 Luci Stanescu
  [[BR]]''code'':[[BR]]
646 37 Luci Stanescu
   The status code of the response for the REGISTER request. This is only present if the notification is sent as a result of a response being received.
647 37 Luci Stanescu
  [[BR]]''reason'':[[BR]]
648 37 Luci Stanescu
   The reason for the failure of the REGISTER request.
649 37 Luci Stanescu
  [[BR]]''registration'':[[BR]]
650 37 Luci Stanescu
   The {{{sipsimple.core.Registration}}} object which failed.
651 37 Luci Stanescu
  [[BR]]''next_route'':[[BR]]
652 37 Luci Stanescu
   A {{{sipsimple.core.Route}}} object which will be tried next for registering the account, or {{{None}}} if a new DNS lookup needs to be performed.
653 37 Luci Stanescu
  [[BR]]''delay'':[[BR]]
654 37 Luci Stanescu
   The amount in seconds as a {{{float}}} after which the next route will be tried for registering the account.
655 37 Luci Stanescu
 '''SIPAccountRegistrationDidEnd'''::
656 37 Luci Stanescu
  This notification is sent when a registration is ended (the account is unregistered). The data contained in this notification is:
657 37 Luci Stanescu
  [[BR]]''code'':[[BR]]
658 37 Luci Stanescu
   The status code of the response for the REGISTER with {{{Expires: 0}}} request. This is only present if a response was received.
659 37 Luci Stanescu
  [[BR]]''reason'':[[BR]]
660 37 Luci Stanescu
   The reason returned in the response for the Register with {{{Expires: 0}}} request. This is only present if a response was received
661 37 Luci Stanescu
  [[BR]]''registration'':[[BR]]
662 37 Luci Stanescu
   The {{{sipsimple.core.Registration}}} object which ended.
663 37 Luci Stanescu
664 37 Luci Stanescu
== BonjourAccount ==
665 37 Luci Stanescu
666 37 Luci Stanescu
Implemented in [browser:sipsimple/account.py]
667 37 Luci Stanescu
668 37 Luci Stanescu
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.
669 37 Luci Stanescu
670 1 Adrian Georgescu
=== States ===
671 37 Luci Stanescu
672 37 Luci Stanescu
The {{{BonjourAccount}}} has an {{{enabled}}} flags 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. (Not implemented yet)
673 37 Luci Stanescu
674 37 Luci Stanescu
=== Attributes ===
675 50 Adrian Georgescu
676 48 Adrian Georgescu
The following attributes can be used on an BonjourAccount object and need to be considered read-only.
677 37 Luci Stanescu
678 37 Luci Stanescu
 '''id'''::
679 50 Adrian Georgescu
  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}}}.
680 38 Luci Stanescu
  {{{
681 38 Luci Stanescu
  bonjour_account.id # 'bonjour@local'
682 38 Luci Stanescu
  bonjour_account.id.username # 'bonjour'
683 50 Adrian Georgescu
  bonjour_account.id.domain # 'local'
684 38 Luci Stanescu
  }}}
685 1 Adrian Georgescu
 '''contact'''::
686 38 Luci Stanescu
  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.ContactURI}}} which is a subclass of {{{sipsimple.configuration.datatypes.SIPAddress}}}. In addition to the attributes defined in {{{SIPAddress}}}, it can be indexed by a string representing a transport ({{{'udp'}}}, {{{'tcp'}}} or {{{'tls'}}}) which will return a {{{sipsimple.core.SIPURI}}} object with the appropriate port and transport parameter. The username part is a randomly generated 8 character string consisting of lowercase letters; the domain part is the IP address on which the {{{Engine}}} is listening (as specified by the SIPSimpleSettings.local_ip setting).
687 38 Luci Stanescu
  {{{
688 1 Adrian Georgescu
  account.contact # 'lxzvgack@10.0.0.1'
689 1 Adrian Georgescu
  account.contact.username # 'lxzvgack'
690 1 Adrian Georgescu
  account.contact.domain # '10.0.0.1'
691 1 Adrian Georgescu
  account.contact['udp'] # <SIPURI "sip:lxzvgack@10.0.0.1:53024">
692 38 Luci Stanescu
  account.contact['tls'] # <SIPURI "sip:lxzvgack@10.0.0.1:54478;transport=tls">
693 38 Luci Stanescu
  }}}
694 38 Luci Stanescu
 '''credentials'''::
695 38 Luci Stanescu
  This attribute is of type {{{sipsimple.core.Credentials}}} object which is built from the {{{contact}}} attribute and {{{display_name}}} setting of the BonjourAccount; the password is set to the empty string. Whenever the display_name setting is changed, this attribute is updated.
696 1 Adrian Georgescu
  {{{
697 1 Adrian Georgescu
  account.credentials # <Credentials for '"Alice" <sip:lxzvgack@10.0.0.1>'>
698 1 Adrian Georgescu
  }}}
699 38 Luci Stanescu
700 38 Luci Stanescu
=== Notifications ===
701 1 Adrian Georgescu
702 38 Luci Stanescu
 '''CFGSettingsObjectDidChange'''::
703 38 Luci Stanescu
  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 [wiki:SipConfigurationAPI#SettingsObjectNotifications SettingsObject Notifications].
704 38 Luci Stanescu
 '''SIPAccountDidActivate'''::
705 38 Luci Stanescu
  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. The notification does not contain any data.
706 38 Luci Stanescu
 '''SIPAccountDidDeactivate'''::
707 38 Luci Stanescu
  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}}}. The notification does not contain any data.
708 38 Luci Stanescu
709 38 Luci Stanescu
710 1 Adrian Georgescu
== AccountManager ==
711 38 Luci Stanescu
712 38 Luci Stanescu
Implemented in [browser:sipsimple/account.py]
713 38 Luci Stanescu
714 1 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.
715 1 Adrian Georgescu
716 39 Luci Stanescu
=== Methods ===
717 50 Adrian Georgescu
718 39 Luci Stanescu
 '''!__init!__'''(''self'')::
719 39 Luci Stanescu
  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.
720 39 Luci Stanescu
 '''start'''(''self'')::
721 39 Luci Stanescu
  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 [wiki:SipConfigurationAPI#ConfigurationManager ConfigurationManager] has been started. A '''SIPAccountManagerDidAddAccount''' will be sent for each account loaded.
722 39 Luci Stanescu
 '''stop'''(''self'')::
723 39 Luci Stanescu
  Calling this method will deactivate all accounts managed by the {{{AccountManager}}}.
724 39 Luci Stanescu
 '''has_account'''(''self'', '''id''')::
725 39 Luci Stanescu
  This method returns {{{True}}} if an account which has the specifed SIP ID (must be a string) exists and {{{False}}} otherwise.
726 39 Luci Stanescu
 '''get_account'''(''self'', '''id''')::
727 50 Adrian Georgescu
  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.
728 48 Adrian Georgescu
 '''get_accounts'''(''self'')::
729 39 Luci Stanescu
  Returns a list containing all the managed accounts.
730 39 Luci Stanescu
 '''iter_accounts'''(''self'')::
731 39 Luci Stanescu
  Returns an iterator through all the managed accounts.
732 39 Luci Stanescu
 '''find_account'''(''self'', '''contact_uri''')::
733 50 Adrian Georgescu
  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.
734 39 Luci Stanescu
735 39 Luci Stanescu
=== Notifications ===
736 39 Luci Stanescu
737 39 Luci Stanescu
 '''SIPAccountManagerDidAddAccount'''::
738 39 Luci Stanescu
  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. The data contains a single attribute, {{{account}}} which is the account object which was added.
739 39 Luci Stanescu
 '''SIPAccountManagerDidRemoveAccount'''::
740 39 Luci Stanescu
  This notification is sent when an account is deleted using the {{{delete}}} method. The data contains a single attribute, {{{account}}} which is the account object which was deleted.
741 39 Luci Stanescu
 '''SIPAccountManagerDidChangeDefaultAccount'''::
742 39 Luci Stanescu
  This notification is sent when the default account changes. The notification contains two attributes:
743 39 Luci Stanescu
  [[BR]]''old_account'':[[BR]]
744 39 Luci Stanescu
   This is the account object which used to be the default account.
745 39 Luci Stanescu
  [[BR]]''account'':[[BR]]
746 39 Luci Stanescu
   This is the account object which is the new default account.
747 39 Luci Stanescu
748 39 Luci Stanescu
== IMediaStream ==
749 39 Luci Stanescu
750 39 Luci Stanescu
Implemented in [browser:sipsimple/streams/__init__.py]
751 39 Luci Stanescu
752 39 Luci Stanescu
This module automatically registers media streams to a stream registry
753 39 Luci Stanescu
allowing for a plug and play mechanism of various types of media negoticated
754 39 Luci Stanescu
in a SIP session that can be added to this library by using a generic API.
755 39 Luci Stanescu
756 39 Luci Stanescu
For actual usage see rtp.py and msrp.py that implement media streams based
757 39 Luci Stanescu
on their respective RTP and MSRP protocols.
758 55 Adrian Georgescu
759 55 Adrian Georgescu
760 55 Adrian Georgescu
=== Atributes ===
761 55 Adrian Georgescu
762 55 Adrian Georgescu
 '''type''' (class attribute)::
763 55 Adrian Georgescu
 A string identifying the stream type (ex: audio, video, ...)
764 55 Adrian Georgescu
 '''priority'''::
765 55 Adrian Georgescu
 An integer value indicating the stream priority relative to the other streams types (higher numbers have higher priority)
766 55 Adrian Georgescu
 '''hold_supported'''::
767 55 Adrian Georgescu
 True if the stream supports hold
768 55 Adrian Georgescu
 '''on_hold_by_local'''::
769 55 Adrian Georgescu
 True if the stream is on hold by the local party
770 55 Adrian Georgescu
 '''on_hold_by_remote'''::
771 55 Adrian Georgescu
 True if the stream is on hold by the remote
772 55 Adrian Georgescu
 '''on_hold'''::
773 55 Adrian Georgescu
 True if either on_hold_by_local or on_hold_by_remote is true
774 55 Adrian Georgescu
775 55 Adrian Georgescu
=== Methods ===
776 55 Adrian Georgescu
777 55 Adrian Georgescu
 '''!__init!__'''(''self'', ''account'')::
778 55 Adrian Georgescu
 Initializes the generic stream instance.
779 55 Adrian Georgescu
 '''new_from_sdp'''(''cls'', ''account'', ''remote_sdp'', ''stream_index'')::
780 55 Adrian Georgescu
 '''get_local_media'''(''self'', ''for_offer'')::
781 55 Adrian Georgescu
 '''initialize'''(''self'', ''session'', ''direction'')::
782 55 Adrian Georgescu
 Initializes the stream 
783 55 Adrian Georgescu
 '''start'''(''self'', ''local_sdp'', ''remote_sdp'', ''stream_index'')::
784 55 Adrian Georgescu
 Completes the stream related connection. [[BR]]
785 55 Adrian Georgescu
 When done, must fire StreamChatDidStart notification. 
786 55 Adrian Georgescu
 '''end'''(''self'')::
787 55 Adrian Georgescu
 Ends the stream.  When done, must fire StreamChatDidEnd notification. 
788 55 Adrian Georgescu
 '''validate_update'''(''self'', ''remote_sdp'', ''stream_index'')::
789 55 Adrian Georgescu
 '''update'''(''self'', ''local_sdp'', ''remote_sdp'', ''stream_index'')::
790 55 Adrian Georgescu
 '''deactivate'''(''self'')::
791 55 Adrian Georgescu
 '''hold'''(''self'')::
792 55 Adrian Georgescu
 Puts the stream on hold if supported by the stream. Typically used by audio and video streams.
793 55 Adrian Georgescu
 '''unhold'''(''self'')::
794 55 Adrian Georgescu
 Takes the stream off hold.
795 55 Adrian Georgescu
796 55 Adrian Georgescu
=== Notifications ===
797 55 Adrian Georgescu
798 55 Adrian Georgescu
These notifications must be generated by all streams in order for the upper layer (SIP session) to perform the right decissions.
799 1 Adrian Georgescu
800 55 Adrian Georgescu
 '''MediaStreamDidInitialize'''::
801 58 Adrian Georgescu
 Sent when the {{{Stream}}} instance is initialized
802 55 Adrian Georgescu
 '''MediaStreamDidStart'''::
803 55 Adrian Georgescu
 Sent when the {{{Stream}}} instance has started.
804 55 Adrian Georgescu
 '''MediaStreamDidFail'''::
805 55 Adrian Georgescu
 Sent when the {{{Stream}}} instance has failed.
806 55 Adrian Georgescu
 '''MediaStreamWillEnd'''::
807 55 Adrian Georgescu
 Sent before the {{{Stream}}} instance will end.
808 55 Adrian Georgescu
 '''MediaStreamDidEnd'''::
809 55 Adrian Georgescu
 Sent when the {{{Stream}}} instance did ended.
810 55 Adrian Georgescu
811 55 Adrian Georgescu
== MediaStreamRegistry ==
812 55 Adrian Georgescu
813 55 Adrian Georgescu
The MediaStream registry is used to register streams that can be automatically dealt with by the SIP session layer.
814 55 Adrian Georgescu
815 55 Adrian Georgescu
There are several pre-built streams based on the '''iMediaStream''' API:
816 55 Adrian Georgescu
817 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.MSRPStreamBase}}}  - MSRP base stream, all MSRP derived streams inherit this
818 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.ChatStream}}} - Chat stream based on MSRP 
819 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.FileSelector}}} - Helper for selecting a file for FileTransferStream
820 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.FileTransferStream}}} - File Transfer stream based on MSRP 
821 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.VNCConnectionError}}} - Helper class for DesktopSharingStream
822 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.DesktopSharingHandlerBase}}}  - Helper class for DesktopSharingStream
823 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.InternalVNCViewerHandler}}} - Helper class for DesktopSharingStream
824 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.InternalVNCViewerHandler}}}  - Helper class for DesktopSharingStream
825 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.ExternalVNCViewerHandler}}}  - Helper class for DesktopSharingStream
826 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.ExternalVNCServerHandler}}}  - Helper class for DesktopSharingStream
827 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.DesktopSharingStream}}} -  Desktop Sharing stream based on VNC over MSRP 
828 55 Adrian Georgescu
 * {{{sipsimple.streams.msrp.NotificationProxyLogger}}} - Helper class for handling MSRP library logs
829 55 Adrian Georgescu
830 55 Adrian Georgescu
These classes are used internally by [wiki:SipMiddlewareApi#Session Session], which provides the necessary methods to access their features. The notifications posted by these classes are also handled internally by [wiki:SipMiddlewareApi#Session Session]. The notifications that are relevant to the user are then reposted by the Session instance. Refer to [wiki:SipMiddlewareApi#Session Session documentation] for details on the Session API. 
831 55 Adrian Georgescu
832 55 Adrian Georgescu
== AudioStream ==
833 55 Adrian Georgescu
834 55 Adrian Georgescu
Implemented in [browser:sipsimple/streams/rtp.py]
835 55 Adrian Georgescu
836 55 Adrian Georgescu
=== SDP Example ===
837 55 Adrian Georgescu
838 55 Adrian Georgescu
{{{
839 55 Adrian Georgescu
Content-Type: application/sdp
840 55 Adrian Georgescu
Content-Length:  1093
841 55 Adrian Georgescu
842 55 Adrian Georgescu
v=0
843 55 Adrian Georgescu
o=- 3467525278 3467525278 IN IP4 192.168.1.6
844 55 Adrian Georgescu
s=blink-0.10.7-beta
845 55 Adrian Georgescu
c=IN IP4 80.101.96.20
846 55 Adrian Georgescu
t=0 0
847 57 Adrian Georgescu
m=audio 55328 RTP/AVP 104 103 102 3 9 0 8 101
848 57 Adrian Georgescu
a=rtcp:55329 IN IP4 80.101.96.20
849 57 Adrian Georgescu
a=rtpmap:104 speex/32000
850 57 Adrian Georgescu
a=rtpmap:103 speex/16000
851 57 Adrian Georgescu
a=rtpmap:102 speex/8000
852 57 Adrian Georgescu
a=rtpmap:3 GSM/8000
853 57 Adrian Georgescu
a=rtpmap:9 G722/8000
854 57 Adrian Georgescu
a=rtpmap:0 PCMU/8000
855 57 Adrian Georgescu
a=rtpmap:8 PCMA/8000
856 57 Adrian Georgescu
a=rtpmap:101 telephone-event/8000
857 57 Adrian Georgescu
a=fmtp:101 0-15
858 57 Adrian Georgescu
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:esI6DbLY1+Aceu0JNswN9Z10DcFx5cZwqJcu91jb
859 57 Adrian Georgescu
a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:SHuEMm1BYJqOF4udKl73EaCwnsI57pO86bYKsg70
860 57 Adrian Georgescu
a=ice-ufrag:2701ed80
861 57 Adrian Georgescu
a=ice-pwd:6f8f8281
862 57 Adrian Georgescu
a=candidate:S 1 UDP 31 80.101.96.20 55328 typ srflx raddr 192.168.1.6 rport 55328
863 57 Adrian Georgescu
a=candidate:H 1 UDP 23 192.168.1.6 55328 typ host
864 57 Adrian Georgescu
a=candidate:H 1 UDP 23 10.211.55.2 55328 typ host
865 57 Adrian Georgescu
a=candidate:H 1 UDP 23 10.37.129.2 55328 typ host
866 57 Adrian Georgescu
a=candidate:S 2 UDP 30 80.101.96.20 55329 typ srflx raddr 192.168.1.6 rport 55329
867 57 Adrian Georgescu
a=candidate:H 2 UDP 22 192.168.1.6 55329 typ host
868 57 Adrian Georgescu
a=candidate:H 2 UDP 22 10.211.55.2 55329 typ host
869 57 Adrian Georgescu
a=candidate:H 2 UDP 22 10.37.129.2 55329 typ host
870 57 Adrian Georgescu
a=sendrecv
871 57 Adrian Georgescu
}}}
872 57 Adrian Georgescu
873 57 Adrian Georgescu
=== Atributes ===
874 57 Adrian Georgescu
875 63 Luci Stanescu
 '''sample_rate'''::
876 63 Luci Stanescu
  If the audio stream was started, this attribute contains the sample rate of the audio negotiated.
877 63 Luci Stanescu
 '''codec'''::
878 63 Luci Stanescu
  If the audio stream was started, this attribute contains the name of the audio codec that was negotiated.
879 63 Luci Stanescu
 '''srtp_active'''::
880 63 Luci Stanescu
  If the audio stream was started, this boolean attribute indicates if SRTP is currently being used on the stream.
881 63 Luci Stanescu
 '''local_rtp_address'''::
882 63 Luci Stanescu
  If an audio stream is present within the session, this attribute contains the local IP address used for the audio stream.
883 63 Luci Stanescu
 '''local_rtp_port'''::
884 63 Luci Stanescu
  If an audio stream is present within the session, this attribute contains the local UDP port used for the audio stream.
885 63 Luci Stanescu
 '''remote_rtp_address_sdp'''::
886 63 Luci Stanescu
  If the audio stream was started, this attribute contains the IP address that the remote party gave to send audio to.
887 63 Luci Stanescu
 '''remote_rtp_port_sdp'''::
888 63 Luci Stanescu
  If the audio stream was started, this attribute contains the UDP port that the remote party gave to send audio to.
889 63 Luci Stanescu
 '''remote_rtp_address_received'''::
890 63 Luci Stanescu
  If the audio stream was started, this attribute contains the remote IP address from which the audio stream is being received.
891 63 Luci Stanescu
 '''remote_rtp_port_received'''::
892 63 Luci Stanescu
  If the audio stream was started, this attribute contains the remote UDP port from which the audio stream is being received.
893 63 Luci Stanescu
 '''recording_file_name'''::
894 63 Luci Stanescu
  If the audio stream is currently being recorded to disk, this property contains the name of the {{{.wav}}} file being recorded to.
895 58 Adrian Georgescu
896 58 Adrian Georgescu
=== Methods ===
897 58 Adrian Georgescu
898 63 Luci Stanescu
 '''start_recording'''(''self'', '''filename'''={{{None}}})::
899 63 Luci Stanescu
  If an audio stream is present within this session, calling this method will record the audio to a {{{.wav}}} file.
900 63 Luci Stanescu
  Note that when the session is on hold, nothing will be recorded to the file.
901 63 Luci Stanescu
  Right before starting the recording a {{{SIPSessionWillStartRecordingAudio}}} notification will be emitted, followed by a {{{SIPSessionDidStartRecordingAudio}}}.
902 63 Luci Stanescu
  This method may only be called while in the {{{ESTABLISHED}}} state.
903 63 Luci Stanescu
  [[BR]]''file_name'':[[BR]]
904 63 Luci Stanescu
  The name of the {{{.wav}}} file to record to.
905 63 Luci Stanescu
  If this is set to {{{None}}}, a default file name including the session participants and the timestamp will be generated.
906 63 Luci Stanescu
 '''stop_recording'''(''self'')::
907 63 Luci Stanescu
  This will stop a previously started recording.
908 63 Luci Stanescu
  Before stopping, a {{{SIPSessionWillStopRecordingAudio}}} notification will be sent, followed by a {{{SIPSessionDidStopRecordingAudio}}}.
909 63 Luci Stanescu
  This method may only be called while in the {{{ESTABLISHED}}} state.
910 63 Luci Stanescu
 '''send_dtmf'''(''self'', '''digit''')::
911 63 Luci Stanescu
  If this session currently has an active audio stream, send a DTMF digit to the remote party over it.
912 63 Luci Stanescu
  This method may only be called while in the {{{ESTABLISHED}}} state and if the session has an active audio stream.
913 63 Luci Stanescu
  [[BR]]''digit'':[[BR]]
914 63 Luci Stanescu
  This should a string of length 1, containing a valid DTMF digit value.
915 55 Adrian Georgescu
 
916 55 Adrian Georgescu
=== Notifications ===
917 55 Adrian Georgescu
918 55 Adrian Georgescu
 '''AudioStreamDidChangeHoldState'''::
919 63 Luci Stanescu
 '''AudioStreamWillStartRecordingAudio''::
920 63 Luci Stanescu
  Will be sent when the application requested that the audio stream active within the session be record to a {{{.wav}}} file, just before recording starts.
921 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
922 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
923 63 Luci Stanescu
  [[BR]]''file_name'':[[BR]]
924 63 Luci Stanescu
  The name of the recording {{{.wav}}} file, including full path.
925 55 Adrian Georgescu
 '''AudioStreamDidStartRecordingAudio'''::
926 63 Luci Stanescu
  Will be sent when the application requested that the audio stream active within the session be record to a {{{.wav}}} file, just after recording starts.
927 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
928 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
929 63 Luci Stanescu
  [[BR]]''file_name'':[[BR]]
930 63 Luci Stanescu
  The name of the recording {{{.wav}}} file, including full path.
931 63 Luci Stanescu
 '''AudioStreamWillStopRecordingAudio'''::
932 63 Luci Stanescu
  Will be sent when the application requested ending the recording to a {{{.wav}}} file, just before recording stops.
933 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
934 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
935 63 Luci Stanescu
  [[BR]]''file_name'':[[BR]]
936 63 Luci Stanescu
  The name of the recording {{{.wav}}} file, including full path.
937 57 Adrian Georgescu
 '''AudioStreamDidStopRecordingAudio'''::
938 63 Luci Stanescu
  Will be sent when the application requested ending the recording to a {{{.wav}}} file, just before recording stops.
939 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
940 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
941 63 Luci Stanescu
  [[BR]]''file_name'':[[BR]]
942 63 Luci Stanescu
  The name of the recording {{{.wav}}} file, including full path.
943 63 Luci Stanescu
 '''SIPSessionGotNoAudio'''::
944 63 Luci Stanescu
  This notification will be sent if 5 seconds after the audio stream starts, no audio was received from the remote party.
945 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
946 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
947 57 Adrian Georgescu
 '''AudioStreamGotDTMF'''::
948 63 Luci Stanescu
  Will be send if there is a DMTF digit received from the remote party on the audio stream. 
949 63 Luci Stanescu
  [[BR]]''timestamp'':[[BR]]
950 63 Luci Stanescu
  A {{{datetime.datetime}}} object indicating when the notification was sent.
951 63 Luci Stanescu
  [[BR]]''digit'':[[BR]]
952 63 Luci Stanescu
  The DTMF digit that was received, in the form of a string of length 1.
953 57 Adrian Georgescu
 
954 55 Adrian Georgescu
== MSRPStreamBase ==
955 55 Adrian Georgescu
956 55 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
957 55 Adrian Georgescu
958 55 Adrian Georgescu
=== Atributes ===
959 55 Adrian Georgescu
960 55 Adrian Georgescu
 '''media_type'''::
961 55 Adrian Georgescu
 '''accept_types'''::
962 55 Adrian Georgescu
 '''accept_wrapped_types'''::
963 55 Adrian Georgescu
 '''use_msrp_session'''::
964 55 Adrian Georgescu
965 55 Adrian Georgescu
=== Notifications ===
966 55 Adrian Georgescu
967 55 Adrian Georgescu
 '''MSRPLibraryLog'''::
968 55 Adrian Georgescu
 '''MSRPTransportTrace'''::
969 55 Adrian Georgescu
970 55 Adrian Georgescu
== ChatStream ==
971 55 Adrian Georgescu
972 55 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
973 55 Adrian Georgescu
974 55 Adrian Georgescu
{{{sipsimple.streams.msrp.ChatStream}}} implements Instant Messaging (IM) over MSRP for the [wiki:SipMiddlewareApi middleware]. This class performs the following functions:
975 55 Adrian Georgescu
976 55 Adrian Georgescu
 * automatically wraps outgoing messages with Message/CPIM if that's necessary according to accept-types
977 55 Adrian Georgescu
 * unwraps incoming Message/CPIM messages; for each incoming message, {{{ChatStreamGotMessage}}} is posted
978 55 Adrian Georgescu
 * plays notification sounds on received/sent message
979 55 Adrian Georgescu
 * reacts to and composes iscomposing payloads
980 55 Adrian Georgescu
981 55 Adrian Georgescu
=== SDP Example ===
982 55 Adrian Georgescu
983 55 Adrian Georgescu
{{{
984 55 Adrian Georgescu
Content-Type: application/sdp
985 55 Adrian Georgescu
Content-Length:   283
986 55 Adrian Georgescu
987 55 Adrian Georgescu
v=0
988 55 Adrian Georgescu
o=- 3467525214 3467525214 IN IP4 192.168.1.6
989 55 Adrian Georgescu
s=blink-0.10.7-beta
990 55 Adrian Georgescu
c=IN IP4 192.168.1.6
991 55 Adrian Georgescu
t=0 0
992 55 Adrian Georgescu
m=message 2855 TCP/TLS/MSRP *
993 55 Adrian Georgescu
a=path:msrps://192.168.1.6:2855/ca7940f12ddef14c3c32;tcp
994 55 Adrian Georgescu
a=accept-types:message/cpim text/* application/im-iscomposing+xml
995 55 Adrian Georgescu
a=accept-wrapped-types:*
996 55 Adrian Georgescu
}}}
997 55 Adrian Georgescu
998 55 Adrian Georgescu
=== Methods ===
999 55 Adrian Georgescu
1000 55 Adrian Georgescu
 '''!__init!__'''(''self'', ''account'', ''direction'')::
1001 55 Adrian Georgescu
 Initializes the ChatStream instance.
1002 55 Adrian Georgescu
1003 55 Adrian Georgescu
 '''initialize'''(''self'')::
1004 55 Adrian Georgescu
 Initializes the MSRP connection; connects to the relay if necessary. When done, fires ChatStreamDidInitialize (with 'sdpmedia' attribute, containing the appropriate 'SDPMedia' instance)
1005 55 Adrian Georgescu
1006 55 Adrian Georgescu
 '''start'''(''self'', ''remote_media'')::
1007 55 Adrian Georgescu
 Completes the MSRP connection establishment; this includes binding the MSRP session. [[BR]]
1008 55 Adrian Georgescu
 When done, fires MSRPChatDidStart notification. At this point each incoming message is posted as a {{{ChatStreamGotMessage}}} notification
1009 55 Adrian Georgescu
1010 55 Adrian Georgescu
 '''end'''(''self'')::
1011 55 Adrian Georgescu
 Closes the MSRP connection or cleans up after initialize(), whatever is necessary. [[BR]]
1012 55 Adrian Georgescu
 Before doing anything posts {{{ChatStreamWillEnd}}} notification.
1013 55 Adrian Georgescu
 When done, posts {{{ChatStreamDidEnd}}} notification. If there was an error, posts {{{ChatStreamDidFail}}} notification. 
1014 55 Adrian Georgescu
 {{{ChatStreamDidEnd}}} notification will be posted anyway.
1015 55 Adrian Georgescu
1016 55 Adrian Georgescu
 '''send_message'''(''self'', ''content'', ''content_type''={{{'text/plain'}}}, ''to_uri''={{{None}}}, ''dt''={{{None}}})::
1017 55 Adrian Georgescu
 Sends IM message. Prefer Message/CPIM wrapper if it is supported. If called before the connection was established, the messages will be
1018 55 Adrian Georgescu
 queued until ChatStreamDidStart notification.
1019 55 Adrian Georgescu
 Returns the generated MSRP chunk (MSRPData instance); to get Message-ID use its 'message_id' attribute.
1020 63 Luci Stanescu
 [[BR]]''content'':[[BR]]
1021 55 Adrian Georgescu
 content of the message
1022 55 Adrian Georgescu
1023 63 Luci Stanescu
 ''content_type'' str:[[BR]]
1024 63 Luci Stanescu
 Content-Type of wrapped message if Message/CPIM is used (Content-Type of MSRP message is always Message/CPIM in that case);
1025 63 Luci Stanescu
 otherwise, Content-Type of MSRP message.
1026 63 Luci Stanescu
1027 55 Adrian Georgescu
 ''to_uri'' SIPURI:[[BR]]
1028 55 Adrian Georgescu
 "To" header of CPIM wrapper; use to override the default supplied to {{{__init__}}}.
1029 55 Adrian Georgescu
 May only differ from the one supplied in __init__ if the remote party supports private messages. If it does not, {{{MSRPChatError}}} will be raised;
1030 55 Adrian Georgescu
1031 63 Luci Stanescu
  [[BR]]''dt'':[[BR]]
1032 63 Luci Stanescu
  A {{{datetime.datetime}}} object representing the timestamp to put on the CPIM wrapper of the message.
1033 63 Luci Stanescu
  When set to {{{None}}}, this defaults to now.
1034 55 Adrian Georgescu
1035 55 Adrian Georgescu
 These MSRP headers are used to enable end-to-end success reports and to disable hop-to-hop successful responses:
1036 55 Adrian Georgescu
{{{
1037 55 Adrian Georgescu
Failure-Report: partial
1038 55 Adrian Georgescu
Success-Report: yes
1039 55 Adrian Georgescu
}}}
1040 55 Adrian Georgescu
1041 55 Adrian Georgescu
 '''send_composing_indication'''(''self'', ''state'', ''refresh'', ''last_active=None'', ''remote_identity=None'')::
1042 57 Adrian Georgescu
 Send is composing notification.
1043 57 Adrian Georgescu
1044 57 Adrian Georgescu
=== Notifications ===
1045 57 Adrian Georgescu
1046 57 Adrian Georgescu
To communicate with the middleware, MSRPChat class uses the notification system provided by the [http://pypi.python.org/pypi/python-application python-application] package.
1047 57 Adrian Georgescu
1048 57 Adrian Georgescu
 '''ChatStreamGotMessage'''::
1049 57 Adrian Georgescu
 Sent whenever a new incoming message is received,
1050 57 Adrian Georgescu
  [[BR]]''content'':[[BR]]
1051 57 Adrian Georgescu
  The string that the remote user has typed.
1052 57 Adrian Georgescu
  [[BR]]''content_type'':[[BR]]
1053 57 Adrian Georgescu
  Content-Type of the user message.
1054 57 Adrian Georgescu
  [[BR]]''cpim_headers'':[[BR]]
1055 57 Adrian Georgescu
  A dictionary of CPIM headers. (Empty dictionary if no CPIM wrapper was used).
1056 57 Adrian Georgescu
  [[BR]]''message'':[[BR]]
1057 57 Adrian Georgescu
  A {{{msrplib.protocol.MSRPData}}} instance providing all the MSRP information about the chunk.
1058 57 Adrian Georgescu
 '''ChatStreamDidDeliverMessage'''::
1059 57 Adrian Georgescu
 Sent when a successful report is received.
1060 57 Adrian Georgescu
  [[BR]]''message_id'':[[BR]]
1061 55 Adrian Georgescu
  Text identifier of the message.
1062 55 Adrian Georgescu
  [[BR]]''code'':[[BR]]
1063 55 Adrian Georgescu
  Integer result code.
1064 55 Adrian Georgescu
  [[BR]]''reason'':[[BR]]
1065 55 Adrian Georgescu
  Text comment.
1066 55 Adrian Georgescu
  [[BR]]''message'':[[BR]]
1067 55 Adrian Georgescu
  A {{{msrplib.protocol.MSRPData}}} instance providing all the MSRP information about the report.
1068 55 Adrian Georgescu
 '''ChatStreamDidNotDeliverMessage'''::
1069 55 Adrian Georgescu
 Sent when a failure report of failure transaction response is received.
1070 55 Adrian Georgescu
  [[BR]]''message_id'':[[BR]]
1071 55 Adrian Georgescu
  Text identifier of the message.
1072 56 Adrian Georgescu
  [[BR]]''code'':[[BR]]
1073 56 Adrian Georgescu
  Integer result code.
1074 1 Adrian Georgescu
  [[BR]]''reason'':[[BR]]
1075 57 Adrian Georgescu
  Text comment.
1076 56 Adrian Georgescu
  [[BR]]''message'':[[BR]]
1077 56 Adrian Georgescu
  A {{{msrplib.protocol.MSRPData}}} instance providing all the MSRP information about the report.
1078 56 Adrian Georgescu
 '''ChatStreamDidSendMessage'''::
1079 56 Adrian Georgescu
 Sent when an outgoing message has been sent.
1080 56 Adrian Georgescu
 '''ChatStreamGotComposingIndication'''::
1081 56 Adrian Georgescu
 Sent when a iscomposing payload is received.
1082 56 Adrian Georgescu
1083 56 Adrian Georgescu
1084 56 Adrian Georgescu
== FileTransferStream ==
1085 55 Adrian Georgescu
1086 55 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
1087 55 Adrian Georgescu
1088 55 Adrian Georgescu
=== SDP Example ===
1089 55 Adrian Georgescu
1090 55 Adrian Georgescu
{{{
1091 61 Luci Stanescu
Content-Type: application/sdp
1092 61 Luci Stanescu
Content-Length:   383
1093 61 Luci Stanescu
1094 61 Luci Stanescu
v=0
1095 61 Luci Stanescu
o=- 3467525166 3467525166 IN IP4 192.168.1.6
1096 61 Luci Stanescu
s=blink-0.10.7-beta
1097 61 Luci Stanescu
c=IN IP4 192.168.1.6
1098 61 Luci Stanescu
t=0 0
1099 61 Luci Stanescu
m=message 2855 TCP/TLS/MSRP *
1100 61 Luci Stanescu
a=path:msrps://192.168.1.6:2855/e593357dc9abe90754bd;tcp
1101 61 Luci Stanescu
a=sendonly
1102 61 Luci Stanescu
a=accept-types:*
1103 61 Luci Stanescu
a=accept-wrapped-types:*
1104 61 Luci Stanescu
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
1105 61 Luci Stanescu
}}}
1106 61 Luci Stanescu
1107 61 Luci Stanescu
=== Methods ===
1108 61 Luci Stanescu
=== Notifications ===
1109 61 Luci Stanescu
1110 61 Luci Stanescu
 '''FileTransferStreamDidDeliverChunk'''::
1111 61 Luci Stanescu
 '''FileTransferStreamDidFinish'''::
1112 61 Luci Stanescu
 '''FileTransferStreamDidNotDeliverChunk'''::
1113 1 Adrian Georgescu
 '''FileTransferStreamGotChunk'''::
1114 1 Adrian Georgescu
1115 1 Adrian Georgescu
== DesktopSharingStream ==
1116 1 Adrian Georgescu
1117 1 Adrian Georgescu
Implemented in [browser:sipsimple/streams/msrp.py]
1118 1 Adrian Georgescu
1119 1 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 [http://msrprelay.org MSRP relay] configured for the called party domain is needed. Below is an example of the Session Description Protocol used for establishing a Desktop sharing session. 
1120 1 Adrian Georgescu
1121 1 Adrian Georgescu
=== SDP Example ===
1122 1 Adrian Georgescu
1123 1 Adrian Georgescu
{{{
1124 1 Adrian Georgescu
m=application 2855 TCP/TLS/MSRP *
1125 1 Adrian Georgescu
a=path:msrps://10.0.1.19:2855/b599b22d1b1d6a3324c8;tcp
1126 1 Adrian Georgescu
a=accept-types:application/x-rfb
1127 1 Adrian Georgescu
a=setup:active
1128 1 Adrian Georgescu
}}}
1129 1 Adrian Georgescu
1130 1 Adrian Georgescu
1131 1 Adrian Georgescu
=== Methods ===
1132 1 Adrian Georgescu
1133 1 Adrian Georgescu
=== Notifications ===
1134 1 Adrian Georgescu
1135 1 Adrian Georgescu
 '''DesktopSharingHandlerDidFail'''::
1136 1 Adrian Georgescu
 '''DesktopSharingStreamGotData'''::
1137 1 Adrian Georgescu
1138 1 Adrian Georgescu
1139 1 Adrian Georgescu
=== Route ===
1140 1 Adrian Georgescu
1141 1 Adrian Georgescu
This class provides a means for the application using the SIP core to set the destination address, port and transport for a particular request, i.e. the outbound proxy.
1142 1 Adrian Georgescu
As it is the application's responsibility to look this up and pass it as an argument for every SIP primitive class it creates.
1143 1 Adrian Georgescu
The contents of the {{{Route}}} object will be placed in the {{{Route}}} header of the request.
1144 1 Adrian Georgescu
As with the {{{SIPURI}}} object, the attributes of this object are the same as the arguments to the {{{__init__}}} method.
1145 1 Adrian Georgescu
1146 1 Adrian Georgescu
==== methods ====
1147 1 Adrian Georgescu
1148 1 Adrian Georgescu
 '''!__init!__'''(''self'', '''address''', '''port'''=5060, '''transport'''={{{None}}})::
1149 1 Adrian Georgescu
  Creates the Route object with the specified parameters as attributes.
1150 1 Adrian Georgescu
  Each of these attributes can be accessed on the object once instanced.
1151 1 Adrian Georgescu
  [[BR]]''address'':[[BR]]
1152 1 Adrian Georgescu
  The IPv4 address that the request in question should be sent to as a string.
1153 1 Adrian Georgescu
  [[BR]]''port'':[[BR]]
1154 1 Adrian Georgescu
  The port to send the requests to, represented as an int.
1155 1 Adrian Georgescu
  [[BR]]''transport'':[[BR]]
1156 1 Adrian Georgescu
  The transport to use, this can be a string of either "udp", "tcp" or "tls" (case insensitive), depending on what transports are enabled on the {{{PJSIPUA}}} object.
1157 1 Adrian Georgescu
 '''copy'''(''self'')::
1158 1 Adrian Georgescu
  Returns a copy of the {{{Route}}} object.