SipMiddlewareApi » History » Version 36
Luci Stanescu, 04/16/2009 12:29 PM
1 | 1 | Adrian Georgescu | = Middleware API = |
---|---|---|---|
2 | |||
3 | [[TOC(WikiStart, Sip*, depth=3)]] |
||
4 | |||
5 | 21 | 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 library. |
6 | 14 | Adrian Georgescu | |
7 | 25 | Adrian Georgescu | * To communicate with other sub-systems, the middleware uses the notification system provided by the [http://pypi.python.org/pypi/python-application python-application] package |
8 | 34 | Adrian Georgescu | * The middleware use the [wiki:SipConfigurationAPI configuration API] to access general and SIP account settings |
9 | 1 | Adrian Georgescu | |
10 | 33 | Adrian Georgescu | [[Image(sipsimple-middleware.png)]] |
11 | 1 | Adrian Georgescu | |
12 | == Classes == |
||
13 | |||
14 | === Session === |
||
15 | |||
16 | A {{{sipsimple.session.Session}}} object represents a complete SIP session between the local and a remote endpoints, including media streams. |
||
17 | The currently supported media streams are audio and MSRP chat. |
||
18 | Both incoming and outgoing sessions are represented by this class. |
||
19 | |||
20 | 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. |
||
21 | State changes are triggered by methods called on the object by the application or by received network events. |
||
22 | 26 | Luci Stanescu | Every time this attribute changes, a {{{SIPSessionChangedState}}} notification is sent by the object. |
23 | 1 | Adrian Georgescu | These states and their transitions are represented in the following diagram: |
24 | |||
25 | 2 | Adrian Georgescu | [[Image(sipsimple-session-state-machine.png)]] |
26 | 1 | Adrian Georgescu | |
27 | 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 different set of notifications is also emitted, which provide all the necessary information to the application. |
||
28 | |||
29 | ==== attributes ==== |
||
30 | |||
31 | '''state''':: |
||
32 | The state the object is currently in, being one of the states from the diagram above. |
||
33 | 18 | Ruud Klaver | '''account''':: |
34 | The {{{sipsimple.account.Account}}} or {{{sipsimple.account.BonjourAccount}}} object that the {{{Session}}} is associated with. |
||
35 | On an outbound session, this is the account the application specified on object instantiation. |
||
36 | 1 | Adrian Georgescu | '''direction''':: |
37 | A string indicating the direction of the initial negotiation of the session. |
||
38 | This can be either {{{None}}}, "incoming" or "outgoing". |
||
39 | '''start_time''':: |
||
40 | The time the session started as a {{{datetime.datetime}}} object, or {{{None}}} if the session was not yet started. |
||
41 | '''stop_time''':: |
||
42 | The time the session stopped as a {{{datetime.datetime}}} object, or {{{None}}} if the session has not yet terminated. |
||
43 | '''on_hold_by_local''':: |
||
44 | Boolean indicating whether the session was put on hold by the local party. |
||
45 | '''on_hold_by_remote''':: |
||
46 | Boolean indicating whether the session was put on hold by the remote party. |
||
47 | '''on_hold''':: |
||
48 | Boolean indicating whether the session was put on hold, either by the local or the remote party. |
||
49 | '''remote_user_agent''':: |
||
50 | A string indicating the remote user agent, if it provided one. |
||
51 | Initially this will be {{{None}}}, it will be set as soon as this information is received from the remote party (which may be never). |
||
52 | '''local_uri''':: |
||
53 | The {{{sipsimple.core.SIPURI}}} of the local party, if the session is active. |
||
54 | '''remote_uri''':: |
||
55 | The {{{sipsimple.core.SIPURI}}} of the remote party, if the session is active. |
||
56 | '''caller_uri''':: |
||
57 | The {{{sipsimple.core.SIPURI}}} of the calling party, if the session is active. |
||
58 | Depending on the direction, this is either {{{local_uri}}} or {{{remote_uri}}}. |
||
59 | '''callee_uri''':: |
||
60 | The {{{sipsimple.core.SIPURI}}} of the called party, if the session is active. |
||
61 | Depending on the direction, this is either {{{local_uri}}} or {{{remote_uri}}}. |
||
62 | '''route''':: |
||
63 | 20 | Ruud Klaver | A copy of the {{{sipsimple.core.Route}}} object passed when the {{{connect()}}} method was called. |
64 | 1 | Adrian Georgescu | On incoming or inactive sessions this is {{{None}}}. |
65 | '''audio_transport''':: |
||
66 | The {{{sipsimple.core.AudioTransport}}} object used by the session, if it currently contains an audio stream. |
||
67 | Normally the application will not need to access this directly. |
||
68 | '''has_audio''':: |
||
69 | 23 | Ruud Klaver | A boolean indicating if this {{{Session}}} currently has an active audio stream. |
70 | 1 | Adrian Georgescu | '''audio_sample_rate''':: |
71 | If the audio stream was started, this attribute contains the sample rate of the audio negotiated. |
||
72 | '''audio_codec''':: |
||
73 | If the audio stream was started, this attribute contains the name of the audio codec that was negotiated. |
||
74 | '''audio_srtp_active''':: |
||
75 | If the audio stream was started, this boolean attribute indicates if SRTP is currently being used on the stream. |
||
76 | '''audio_local_rtp_address''':: |
||
77 | If an audio stream is present within the session, this attribute contains the local IP address used for the audio stream. |
||
78 | '''audio_local_rtp_port''':: |
||
79 | If an audio stream is present within the session, this attribute contains the local UDP port used for the audio stream. |
||
80 | '''audio_remote_rtp_address_sdp''':: |
||
81 | If the audio stream was started, this attribute contains the IP address that the remote party gave to send audio to. |
||
82 | '''audio_remote_rtp_port_sdp''':: |
||
83 | If the audio stream was started, this attribute contains the UDP port that the remote party gave to send audio to. |
||
84 | '''audio_remote_rtp_address_received''':: |
||
85 | If the audio stream was started, this attribute contains the remote IP address from which the audio stream is being received. |
||
86 | '''audio_remote_rtp_port_received''':: |
||
87 | If the audio stream was started, this attribute contains the remote UDP port from which the audio stream is being received. |
||
88 | '''audio_was_received''':: |
||
89 | This boolean property indicates if audio was actually received on the audio stream contained within this session. |
||
90 | '''audio_recording_file_name''':: |
||
91 | If the audio stream is currently being recorded to disk, this property contains the name of the {{{.wav}}} file being recorded to. |
||
92 | '''chat_transport''':: |
||
93 | The {{{sipsimple.msrp.MSRPChat}}} object used by the session as chat transport, if the session currently contains a chat stream. |
||
94 | Normally the application will not need to access this directly. |
||
95 | '''has_chat''':: |
||
96 | 23 | Ruud Klaver | A boolean property indicating if this {{{Session}}} currently has an active chat stream. |
97 | 1 | Adrian Georgescu | |
98 | ==== methods ==== |
||
99 | |||
100 | 18 | Ruud Klaver | '''!__init!__'''(''self'', '''account'''):: |
101 | 1 | Adrian Georgescu | Creates a new {{{Session}}} object in the {{{NULL}}} state. |
102 | 19 | Ruud Klaver | [[BR]]''account'':[[BR]] |
103 | The local account to be associated with this {{{Session}}}. |
||
104 | '''connect'''(''self'', '''callee_uri''', '''routes''', '''audio'''={{{False}}}, '''chat'''={{{False}}}):: |
||
105 | 1 | Adrian Georgescu | Will set up the {{{Session}}} as outbound and propose the new session to the specified remote party and move the state machine to the {{{CALLING}}} state. |
106 | 26 | Luci Stanescu | Before contacting the remote party, a {{{SIPSessionNewOutgoing}}} notification will be emitted. |
107 | If there is a failure or the remote party rejected the offer, a {{{SIPSessionDidFail}}} notification will be sent, followed by a {{{SIPSessionDidEnd}}}. |
||
108 | Any time a ringing indication is received from the remote party, a {{{SIPSessionGotRingIndication}}} notification is sent. |
||
109 | If the remote party accepted the session, a {{{SIPSessionWillStart}}} notification will be sent, followed by a {{{SIPSessionDidStart}}} notification when the session is actually established. |
||
110 | 1 | Adrian Georgescu | This method may only be called while in the {{{NULL}}} state. |
111 | [[BR]]''callee_uri'':[[BR]] |
||
112 | A {{{sipsimple.core.SIPURI}}} object representing the remote host to initiate the session to. |
||
113 | 19 | Ruud Klaver | [[BR]]''routes'':[[BR]] |
114 | An iterable of {{{sipsimple.core.Route}}} objects, specifying the IP, port and transport to the outbound proxy. |
||
115 | These routes will be tried in order, until one of them succeeds. |
||
116 | 1 | Adrian Georgescu | [[BR]]''audio'':[[BR]] |
117 | A boolean indicating whether an audio stream should be initially included in this session. |
||
118 | [[BR]]''chat'':[[BR]] |
||
119 | A boolean indicating whether a chat stream should be initially included in this session. |
||
120 | 19 | Ruud Klaver | '''accept'''(''self'', '''audio'''={{{False}}}, '''chat'''={{{False}}}):: |
121 | 1 | Adrian Georgescu | Calling this methods will accept an incoming session and move the state machine to the {{{ACCEPTING}}} state. |
122 | 26 | 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. |
123 | After this method is called, {{{SIPSessionWillStart}}} followed by {{{SIPSessionDidStart}}} will be emitted, or {{{SIPSessionDidFail}}} followed by {{{SIPSessionDidEnd}}} on an error. |
||
124 | 1 | Adrian Georgescu | This method may only be called while in the {{{INCOMING}}} state. |
125 | [[BR]]''audio'':[[BR]] |
||
126 | A boolean indicating whether an audio stream should be accepted for this session. |
||
127 | Note that this may only be set to {{{True}}} if an audio stream was actually proposed by the remote party. |
||
128 | [[BR]]''chat'':[[BR]] |
||
129 | A boolean indicating whether a chat stream should be accepted for this session. |
||
130 | Note that this may only be set to {{{True}}} if a chat stream was actually proposed by the remote party. |
||
131 | '''reject'''(''self''):: |
||
132 | Reject an incoming session and move it to the {{{TERMINATING}}} state, which eventually leads to the {{{TERMINATED}}} state. |
||
133 | 26 | Luci Stanescu | Calling this method will cause the {{{Session}}} object to emit a {{{SIPSessionWillEnd}}} notification, followed by a {{{SIPSessionDidEnd}}} notification. |
134 | 1 | Adrian Georgescu | This method may only be called while in the {{{INCOMING}}} state. |
135 | '''hold'''(''self''):: |
||
136 | Put the session on hold. |
||
137 | 26 | Luci Stanescu | This will cause a {{{SIPGotHoldRequest}}} notification to be sent. |
138 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
139 | '''unhold'''(''self''):: |
||
140 | Take the session out of hold. |
||
141 | 26 | Luci Stanescu | This will cause a {{{SIPGotUnholdRequest}}} notification to be sent. |
142 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
143 | 19 | Ruud Klaver | '''start_recording_audio'''(''self'', '''file_name'''={{{None}}}):: |
144 | 1 | Adrian Georgescu | If an audio stream is present within this session, calling this method will record the audio to a {{{.wav}}} file. |
145 | Note that when the session is on hold, nothing will be recorded to the file. |
||
146 | 26 | Luci Stanescu | Right before starting the recording a {{{SIPSessionWillStartRecordingAudio}}} notification will be emitted, followed by a {{{SIPSessionDidStartRecordingAudio}}}. |
147 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
148 | [[BR]]''file_name'':[[BR]] |
||
149 | The name of the {{{.wav}}} file to record to. |
||
150 | If this is set to {{{None}}}, a default file name including the session participants and the timestamp will be generated. |
||
151 | '''stop_recording_audio'''(''self''):: |
||
152 | This will stop a previously started recording. |
||
153 | 26 | Luci Stanescu | Before stopping, a {{{SIPSessionWillStopRecordingAudio}}} notification will be sent, followed by a {{{SIPSessionDidStopRecordingAudio}}}. |
154 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state. |
155 | '''send_dtmf'''(''self'', '''digit'''):: |
||
156 | If this session currently has an active audio stream, send a DTMF digit to the remote party over it. |
||
157 | 23 | Ruud Klaver | This method may only be called while in the {{{ESTABLISHED}}} state and if the session has an active audio stream. |
158 | 1 | Adrian Georgescu | [[BR]]''digit'':[[BR]] |
159 | This should a string of length 1, containing a valid DTMF digit value. |
||
160 | 13 | Luci Stanescu | '''send_message'''(''self'', '''content''', '''content_type'''="text/plain", '''to_uri'''={{{None}}}, '''dt'''={{{None}}}):: |
161 | 1 | Adrian Georgescu | If this session currently has an active MSRP chat with the remote party, send a message over with the with the specified parameters. |
162 | 26 | Luci Stanescu | This will result in either a {{{SIPSessionDidDeliverMessage}}} or a {{{SIPSessionDidNotDeliverMessage}}} notification being sent. |
163 | 1 | Adrian Georgescu | These notifications include a unique ID as data attribute which is also returned by this method. |
164 | This method may only be called while in the {{{ESTABLISHED}}} state. |
||
165 | [[BR]]''content'':[[BR]] |
||
166 | The body of the MSRP message as a string. |
||
167 | [[BR]]''content_type'':[[BR]] |
||
168 | The Content-Type of the body as a string |
||
169 | 22 | Ruud Klaver | [[BR]]''to_uri'':[[BR]] |
170 | 1 | Adrian Georgescu | The {{{sipsimple.core.SIPURI}}} that should be put in the {{{To:}}} header of the CPIM wrapper of the message. |
171 | This defaults to the SIP URI of the remote party of the session if the argument is set to {{{None}}} |
||
172 | [[BR]]''dt'':[[BR]] |
||
173 | A {{{datetime.datetime}}} object representing the timestamp to put on the CPIM wrapper of the message. |
||
174 | When set to {{{None}}}, this defaults to now. |
||
175 | '''add_audio'''(''self''):: |
||
176 | Propose the remote party to add an audio stream to this session. |
||
177 | 26 | Luci Stanescu | Calling this method will cause a {{{SIPSessionGotStreamProposal}}} notification to be emitted. |
178 | After this, the state machine will move into the {{{PROPOSING}}} state until either a {{{SIPSessionAcceptedStreamProposal}}} or {{{SIPSessionRejectedStreamProposal}}} notification is sent, informing the application if the remote party accepted the proposal. |
||
179 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that does not currently have an audio stream. |
180 | '''remove_audio'''(''self''):: |
||
181 | Stop the audio stream currently active within the session and inform the remote party of this. |
||
182 | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that has an audio stream. |
||
183 | '''add_chat'''(''self''):: |
||
184 | Propose the remote party to add a chat stream to this session. |
||
185 | 26 | Luci Stanescu | Calling this method will cause a {{{SIPSessionGotStreamProposal}}} notification to be emitted. |
186 | After this, the state machine will move into the {{{PROPOSING}}} state until either a {{{SIPSessionAcceptedStreamProposal}}} or {{{SIPSessionRejectedStreamProposal}}} notification is sent, informing the application if the remote party accepted the proposal. |
||
187 | 1 | Adrian Georgescu | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that does not currently have a chat stream. |
188 | '''remove_chat'''(''self''):: |
||
189 | Stop the chat stream currently active within the session and inform the remote party of this. |
||
190 | This method may only be called while in the {{{ESTABLISHED}}} state on a {{{Session}}} object that has a chat stream. |
||
191 | 19 | Ruud Klaver | '''accept_proposal'''(''self'', '''audio'''={{{False}}}, '''chat'''={{{False}}}):: |
192 | 26 | Luci Stanescu | When the remote party proposes to add a new stream, signaled by the {{{SIPSessionGotStreamProposal}}} notification, the application can use this method to accept the stream(s) being proposed. |
193 | After calling this method a {{{SIPSessionAcceptedStreamProposal}}} notification is sent, unless an error occurs while setting up the new stream, in which case a {{{SIPSessionRejectedStreamProposal}}} notification is sent and a rejection is sent to the remote party. |
||
194 | 1 | Adrian Georgescu | This method may only be called while in the {{{PROPOSED}}} state. |
195 | 19 | Ruud Klaver | [[BR]]''audio'':[[BR]] |
196 | A boolean indicating whether an audio stream should be accepted for this proposal. |
||
197 | Note that this may only be set to {{{True}}} if an audio stream was actually proposed by the remote party. |
||
198 | [[BR]]''chat'':[[BR]] |
||
199 | A boolean indicating whether a chat stream should be accepted for this proposal. |
||
200 | Note that this may only be set to {{{True}}} if a chat stream was actually proposed by the remote party. |
||
201 | 1 | Adrian Georgescu | '''reject_proposal'''(''self''):: |
202 | 26 | Luci Stanescu | When the remote party proposes (a) stream(s) that the application does not want to accept, this method can be used to reject the proposal, after which a {{{SIPSessionRejectedStreamProposal}}} notification is sent. |
203 | 1 | Adrian Georgescu | This method may only be called while in the {{{PROPOSED}}} state. |
204 | 23 | Ruud Klaver | '''end'''(''self''):: |
205 | 1 | Adrian Georgescu | This method may be called any time when the {{{Session}}} object is active (i.e. not in the {{{NULL}}}, {{{TERMINATING}}} or {{{TERMINATED}}} states) in order to terminate the session. |
206 | 26 | Luci Stanescu | Right before termination a {{{SIPSessionWillEnd}}} notification is sent, after termination {{{SIPSessionDidEnd}}} is sent. |
207 | 1 | Adrian Georgescu | |
208 | ==== notifications ==== |
||
209 | |||
210 | 26 | Luci Stanescu | '''SIPSessionChangedState''':: |
211 | 1 | Adrian Georgescu | Will be sent whenever the {{{Session}}} object changes its state. |
212 | [[BR]]''timestamp'':[[BR]] |
||
213 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
214 | [[BR]]''prev_state'':[[BR]] |
||
215 | The previous state state the object was in. |
||
216 | [[BR]]''state'':[[BR]] |
||
217 | The new state the object is in. |
||
218 | 26 | Luci Stanescu | '''SIPSessionNewIncoming''':: |
219 | 1 | Adrian Georgescu | Will be sent when a new incoming {{{Session}}} is received. |
220 | The application should listen for this notification from all objects specifically to get informed of incoming sessions. |
||
221 | [[BR]]''timestamp'':[[BR]] |
||
222 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
223 | 19 | Ruud Klaver | [[BR]]''streams'':[[BR]] |
224 | A list of strings indicating the streams that were proposed by the remote party. |
||
225 | 26 | Luci Stanescu | '''SIPSessionNewOutgoing''':: |
226 | 1 | Adrian Georgescu | Will be sent when the applcation requests a new outgoing {{{Session}}}. |
227 | [[BR]]''timestamp'':[[BR]] |
||
228 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
229 | 19 | Ruud Klaver | [[BR]]''streams'':[[BR]] |
230 | 32 | Adrian Georgescu | A list of strings indicating the streams that were proposed to the remote party. |
231 | 26 | Luci Stanescu | '''SIPSessionGotRingIndication''':: |
232 | 1 | Adrian Georgescu | Will be sent when an outgoing {{{Session}}} receives an indication that a remote device is ringing. |
233 | [[BR]]''timestamp'':[[BR]] |
||
234 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
235 | 26 | Luci Stanescu | '''SIPSessionWillStart''':: |
236 | 1 | Adrian Georgescu | Will be sent just before a {{{Session}}} completes negotiation. |
237 | In terms of SIP, this is sent after the final response to the {{{INVITE}}}, but before the {{{ACK}}}. |
||
238 | [[BR]]''timestamp'':[[BR]] |
||
239 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
240 | 26 | Luci Stanescu | '''SIPSessionDidStart''':: |
241 | 1 | Adrian Georgescu | Will be sent when a {{{Session}}} completes negotiation. |
242 | In terms of SIP this is sent after the {{{ACK}}} was sent or received. |
||
243 | [[BR]]''timestamp'':[[BR]] |
||
244 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
245 | 26 | Luci Stanescu | '''SIPSessionDidFail''':: |
246 | 1 | Adrian Georgescu | This notification is sent whenever the session fails. |
247 | The failure reason is included in the data attributes. |
||
248 | 26 | Luci Stanescu | This notification is always followed by {{{SIPSessionDidEnd}}}. |
249 | 1 | Adrian Georgescu | [[BR]]''timestamp'':[[BR]] |
250 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
251 | [[BR]]''originator'':[[BR]] |
||
252 | A string indicating the origin of the failure. |
||
253 | This will either be "local" or "remote". |
||
254 | [[BR]]''code'':[[BR]] |
||
255 | The SIP error code of the failure. |
||
256 | If this is 0, the error was an internal exception. |
||
257 | [[BR]]''reason'':[[BR]] |
||
258 | A string explaining the reason of the failure. |
||
259 | 26 | Luci Stanescu | '''SIPSessionWillEnd''':: |
260 | 1 | Adrian Georgescu | Will be sent just before terminating a {{{Session}}} at the request of the application. |
261 | [[BR]]''timestamp'':[[BR]] |
||
262 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
263 | 26 | Luci Stanescu | '''SIPSessionDidEnd''':: |
264 | Will be sent always when a {{{Session}}} ends, either because of a failure (in which case it is preceded by {{{SIPSessionDidFail}}}), remote or local session termination. |
||
265 | 1 | Adrian Georgescu | [[BR]]''timestamp'':[[BR]] |
266 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
267 | [[BR]]''originator'':[[BR]] |
||
268 | A string indicating who originated the termination. |
||
269 | This will either be "local" or "remote". |
||
270 | 26 | Luci Stanescu | '''SIPSessionGotHoldRequest''':: |
271 | 1 | Adrian Georgescu | Will be sent when the session got put on hold, either by the local or the remote party. |
272 | [[BR]]''timestamp'':[[BR]] |
||
273 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
274 | [[BR]]''originator'':[[BR]] |
||
275 | A string indicating who originated the hold request, and consequently in which direction the session got put on hold. |
||
276 | 26 | Luci Stanescu | '''SIPSessionGotUnholdRequest''':: |
277 | 1 | Adrian Georgescu | Will be sent when the session got taken out of hold, either by the local or the remote party. |
278 | [[BR]]''timestamp'':[[BR]] |
||
279 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
280 | [[BR]]''originator'':[[BR]] |
||
281 | A string indicating who sent the original hold request, and consequently in which direction the session got taken out of hold. |
||
282 | 26 | Luci Stanescu | '''SIPSessionWillStartRecordingAudio''':: |
283 | 1 | Adrian Georgescu | 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. |
284 | [[BR]]''timestamp'':[[BR]] |
||
285 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
286 | [[BR]]''file_name'':[[BR]] |
||
287 | The name of the recording {{{.wav}}} file, including full path. |
||
288 | 26 | Luci Stanescu | '''SIPSessionDidStartRecordingAudio''':: |
289 | 1 | Adrian Georgescu | 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. |
290 | [[BR]]''timestamp'':[[BR]] |
||
291 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
292 | [[BR]]''file_name'':[[BR]] |
||
293 | The name of the recording {{{.wav}}} file, including full path. |
||
294 | 26 | Luci Stanescu | '''SIPSessionWillStopRecordingAudio''':: |
295 | 1 | Adrian Georgescu | Will be sent when the application requested ending the recording to a {{{.wav}}} file, just before recording stops. |
296 | [[BR]]''timestamp'':[[BR]] |
||
297 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
298 | [[BR]]''file_name'':[[BR]] |
||
299 | The name of the recording {{{.wav}}} file, including full path. |
||
300 | 26 | Luci Stanescu | '''SIPSessionDidStopRecordingAudio''':: |
301 | 1 | Adrian Georgescu | Will be sent when the application requested ending the recording to a {{{.wav}}} file, just before recording stops. |
302 | [[BR]]''timestamp'':[[BR]] |
||
303 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
304 | [[BR]]''file_name'':[[BR]] |
||
305 | The name of the recording {{{.wav}}} file, including full path. |
||
306 | 26 | Luci Stanescu | '''SIPSessionGotNoAudio''':: |
307 | 1 | Adrian Georgescu | This notification will be sent if 5 seconds after the audio stream starts, no audio was received from the remote party. |
308 | [[BR]]''timestamp'':[[BR]] |
||
309 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
310 | 26 | Luci Stanescu | '''SIPSessionGotDTMF''':: |
311 | 1 | Adrian Georgescu | Will be send if there is a DMTF digit received from the remote party on the audio stream. |
312 | [[BR]]''timestamp'':[[BR]] |
||
313 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
314 | [[BR]]''digit'':[[BR]] |
||
315 | The DTMF digit that was received, in the form of a string of length 1. |
||
316 | 26 | Luci Stanescu | '''SIPSessionGotMessage''':: |
317 | 1 | Adrian Georgescu | Will be sent whenever a MSRP message is received on the chat stream of the session. |
318 | [[BR]]''content'':[[BR]] |
||
319 | The body of the message. |
||
320 | [[BR]]''content_type'':[[BR]] |
||
321 | The Content-Type of the body. |
||
322 | [[BR]]''cpim_headers'':[[BR]] |
||
323 | A dictionary of headers included in the CPIM wrapper. |
||
324 | [[BR]]''message'':[[BR]] |
||
325 | 5 | Redmine Admin | Raw MSRP message, an msrplib.protocol.MSRPData instance |
326 | 26 | Luci Stanescu | '''SIPSessionDidDeliverMessage''':: |
327 | 1 | Adrian Georgescu | Will be sent when a previously sent MSRP chat message got delivered to the remote party. |
328 | [[BR]]''message_id'':[[BR]] |
||
329 | The unique identifier of this message as a string, as previously returned by the {{{send_message()}}} method. |
||
330 | [[BR]]''code'':[[BR]] |
||
331 | The response code of the confirmation report. |
||
332 | [[BR]]''reason'':[[BR]] |
||
333 | 5 | Redmine Admin | The reason string of the confirmation report. |
334 | 1 | Adrian Georgescu | [[BR]]''message'':[[BR]] |
335 | Raw MSRP message, an msrplib.protocol.MSRPData instance |
||
336 | 26 | Luci Stanescu | '''SIPSessionDidDeliverMessage''':: |
337 | 1 | Adrian Georgescu | Will be sent when a previously sent MSRP chat message did not get delivered to the remote party. |
338 | [[BR]]''message_id'':[[BR]] |
||
339 | The unique identifier of this message as a string, as previously returned by the {{{send_message()}}} method. |
||
340 | [[BR]]''code'':[[BR]] |
||
341 | The response code of the confirmation report. |
||
342 | [[BR]]''reason'':[[BR]] |
||
343 | 5 | Redmine Admin | The reason string of the confirmation report. |
344 | 1 | Adrian Georgescu | [[BR]]''message'':[[BR]] |
345 | Raw MSRP message, an msrplib.protocol.MSRPData instance |
||
346 | 26 | Luci Stanescu | '''SIPSessionGotStreamProposal''':: |
347 | 1 | Adrian Georgescu | Will be sent when either the local or the remote party proposes to add a stream to the session. |
348 | [[BR]]''timestamp'':[[BR]] |
||
349 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
350 | [[BR]]''proposer'':[[BR]] |
||
351 | The party that did the stream proposal, can be either "local" or "remote". |
||
352 | 19 | Ruud Klaver | [[BR]]''streams'':[[BR]] |
353 | A list of strings indicating the streams that were proposed. |
||
354 | 26 | Luci Stanescu | '''SIPSessionRejectedStreamProposal''':: |
355 | 1 | Adrian Georgescu | Will be sent when either the local or the remote party rejects a proposal to have (a) stream(s) added to the session. |
356 | [[BR]]''timestamp'':[[BR]] |
||
357 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
358 | [[BR]]''proposer'':[[BR]] |
||
359 | The party that did the stream proposal, can be either "local" or "remote". |
||
360 | [[BR]]''reason'':[[BR]] |
||
361 | The reason for rejecting the stream proposal. |
||
362 | '''SIPSessionRejectedStreamProposal''':: |
||
363 | 26 | Luci Stanescu | Will be sent when either the local or the remote party accepts a proposal to have (a) stream(s) added to the session. |
364 | 1 | Adrian Georgescu | [[BR]]''timestamp'':[[BR]] |
365 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
366 | [[BR]]''proposer'':[[BR]] |
||
367 | The party that did the stream proposal, can be either "local" or "remote". |
||
368 | '''SIPSessionGotStreamUpdate''':: |
||
369 | 26 | Luci Stanescu | Will be sent when a media stream is either activated or deactivated. |
370 | 23 | Ruud Klaver | An application should listen to this notification in order to know when a media stream can be used. |
371 | [[BR]]''timestamp'':[[BR]] |
||
372 | A {{{datetime.datetime}}} object indicating when the notification was sent. |
||
373 | [[BR]]''streams'':[[BR]] |
||
374 | A list indicating which streams are active on the session from this point onwards. |
||
375 | |||
376 | 30 | 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: |
377 | 6 | Ruud Klaver | |
378 | {{{ |
||
379 | 24 | Ruud Klaver | import sys |
380 | 6 | Ruud Klaver | from threading import Event |
381 | from zope.interface import implements |
||
382 | from application.notification import IObserver, NotificationCenter |
||
383 | 1 | Adrian Georgescu | |
384 | 24 | Ruud Klaver | from sipsimple.configuration import ConfigurationManager |
385 | from sipsimple.account import AccountManager |
||
386 | from sipsimple.engine import Engine |
||
387 | from sipsimple.session import Session |
||
388 | from sipsimple.core import SIPURI, Route |
||
389 | |||
390 | 1 | Adrian Georgescu | class SimpleOutboundCall(object): |
391 | # indicate that we implement the application.notification.IObserver interface |
||
392 | implements(IObserver) |
||
393 | |||
394 | 24 | Ruud Klaver | def __init__(self, remote_uri, route): |
395 | 1 | Adrian Georgescu | # setup a threading.Event to signal that the Engine has stopped |
396 | self.engine_ended_event = Event() |
||
397 | 24 | Ruud Klaver | # start the configuration manager |
398 | ConfigurationManager().start() |
||
399 | # start the account manager |
||
400 | am = AccountManager() |
||
401 | am.start() |
||
402 | # start the Engine with configuration framework parameters |
||
403 | Engine().start_cfg() |
||
404 | # create a new Session using the default account |
||
405 | self.session = Session(am.default_account) |
||
406 | 6 | Ruud Klaver | # listen for the notification that the Engine stopped |
407 | 26 | Luci Stanescu | NotificationCenter().add_observer(self, "SIPEngineDidEnd", Engine()) |
408 | 6 | Ruud Klaver | # listen for the notification that the Session ended |
409 | 26 | Luci Stanescu | NotificationCenter().add_observer(self, "SIPSessionDidEnd", self.session) |
410 | 6 | Ruud Klaver | # start a new outbound session |
411 | 24 | Ruud Klaver | self.session.connect(remote_uri, [route], audio=True) |
412 | 6 | Ruud Klaver | |
413 | 23 | Ruud Klaver | def end(self): |
414 | 6 | Ruud Klaver | # if the Session is still active, terminate it |
415 | self.session.end() |
||
416 | # wait for the engine to stop, processed in handle_notification |
||
417 | self.engine_ended_event.wait() |
||
418 | # quit the progam, as this can only be done from the main thread |
||
419 | sys.exit() |
||
420 | |||
421 | 1 | Adrian Georgescu | def handle_notification(self, notification): |
422 | if notification.name == "SIPSessionDidEnd": |
||
423 | # if for whatever reason the session ended, stop the Engine |
||
424 | print "Session ended" |
||
425 | Engine().stop() |
||
426 | elif notification.name == "SIPEngineDidEnd": |
||
427 | # once the Engine has stopped, signal the (possibly) waiting main |
||
428 | # thread through a threading.Event |
||
429 | self.engine_ended_event.set() |
||
430 | |||
431 | # place an audio call from the specified account to the specified URI, through |
||
432 | # the specified SIP proxy |
||
433 | # edit this to reflect real settings |
||
434 | call = SimpleOutboundCall(SIPURI(user="bob", host="example.com"), Route("1.2.3.4")) |
||
435 | # block waiting for user input |
||
436 | print "Placing call, press enter to quit program" |
||
437 | raw_input() |
||
438 | # block in end() until the Engine has stopped |
||
439 | 26 | Luci Stanescu | call.end() |
440 | 6 | Ruud Klaver | }}} |
441 | 30 | Adrian Georgescu | |
442 | === SessionManager === |
||
443 | |||
444 | 31 | Adrian Georgescu | The {{{sipsimple.session.SessionManager}}} class is a singleton, which acts as the central aggregation point for sessions within the middleware. |
445 | 30 | Adrian Georgescu | Although it is mainly used internally, the application can use it to query information about all active sessions. |
446 | The SessionManager is implemented as a singleton, meaning that only one instance of this class exists within the middleware. |
||
447 | Note that, in order to be able to receive calls, the application has to instantiate this object. |
||
448 | |||
449 | ==== attributes ==== |
||
450 | |||
451 | '''sessions''':: |
||
452 | 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. |
||
453 | |||
454 | ==== methods ==== |
||
455 | |||
456 | '''!__init!__'''(''self''):: |
||
457 | This either returns a new {{{SessionManager}}} object with default configuration objects, or returns a copy of the already existing instance. |
||
458 | 35 | Luci Stanescu | |
459 | |||
460 | === Account === |
||
461 | |||
462 | 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]. |
||
463 | |||
464 | 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}}}. |
||
465 | |||
466 | 36 | Luci Stanescu | ==== states ==== |
467 | 35 | Luci Stanescu | |
468 | 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: |
||
469 | {{{ |
||
470 | account.enabled = True |
||
471 | account.save() |
||
472 | }}} |
||
473 | |||
474 | 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: |
||
475 | |||
476 | '''Account.registration.enabled''':: |
||
477 | This flag controls the automatic registration of the account. The notifications '''SIPAccountRegistrationDidSucceed''', '''SIPAccountRegistrationDidFail''' and '''SIPAccountRegistrationDidEnd''' are used to inform the status of this registration. |
||
478 | '''Account.presence.enabled''':: |
||
479 | This flag controls the automatic subscription to buddies for the ''presence'' event and the publication of data in this event. (Not implemented yet) |
||
480 | '''Account.dialog_event.enabled''':: |
||
481 | This flag controls the automatic subscription to buddies for the ''dialog-info'' event and the publication of data in this event. (Not implemented yet) |
||
482 | '''Account.message_summary.enabled''':: |
||
483 | This flag controls the automatic subscription to the ''message-summary'' event in order to find out about voicemail messages. (Not implemented yet) |
||
484 | |||
485 | 1 | Adrian Georgescu | The {{{save()}}} method needs to be called after changing these flags in order for them to take effect. |
486 | 36 | Luci Stanescu | |
487 | ==== attributes ==== |
||
488 | |||
489 | The following attributes can be used on an Account object and need to be considered read-only. |
||
490 | |||
491 | '''id''':: |
||
492 | 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}}}. |
||
493 | {{{ |
||
494 | account.id # 'alice@example.com' |
||
495 | account.id.username # 'alice' |
||
496 | account.id.domain # 'example.com' |
||
497 | }}} |
||
498 | '''contact''':: |
||
499 | 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). |
||
500 | {{{ |
||
501 | account.contact # 'hnfkybrt@10.0.0.1' |
||
502 | account.contact.username # 'hnfkybrt' |
||
503 | account.contact.domain # '10.0.0.1' |
||
504 | account.contact['udp'] # <SIPURI "sip:hnfkybrt@10.0.0.1:53024"> |
||
505 | account.contact['tls'] # <SIPURI "sip:hnfkybrt@10.0.0.1:54478;transport=tls"> |
||
506 | }}} |
||
507 | '''credentials''':: |
||
508 | 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. |
||
509 | {{{ |
||
510 | account.credentials # <Credentials for '"Alice" <sip:alice@example.com>'> |
||
511 | }}} |