SipMSRPApi

Version 10 (Adrian Georgescu, 03/31/2009 02:28 pm)

1 1 Adrian Georgescu
= MSRP API =
2 1 Adrian Georgescu
3 1 Adrian Georgescu
[[TOC(WikiStart, Sip*, depth=3)]]
4 1 Adrian Georgescu
5 1 Adrian Georgescu
Message Session Relay Protocol (MSRP) is a protocol for transmitting a series of related instant messages in the context of a session. Message sessions are treated like any other media stream when set up via a rendezvous or session creation protocol such as the Session Initiation Protocol (SIP). 
6 1 Adrian Georgescu
7 1 Adrian Georgescu
 * MSRP sessions are defined in [http://tools.ietf.org/html/rfc4975 RFC 4975].
8 1 Adrian Georgescu
 * MSRP relay extension used for NAT traversal of instant messaging and file transfer sessions is defined in [http://tools.ietf.org/html/rfc4976 RFC 4976].
9 1 Adrian Georgescu
10 5 Oliver Bril
The MSRP protocol is implemented by [http://devel.ag-projects.com/cgi-bin/darcsweb.cgi?r=python-msrplib;a=summary msrplib] Python package. On top of it, {{{sipsimple}}} provides higher level classes integrated into middleware notification and configuration systems:
11 1 Adrian Georgescu
12 4 Oliver Bril
 * {{{sipsimple.msrp.MSRPChat}}}
13 4 Oliver Bril
 * {{{sipsimple.msrp.MSRPFileTransfer}}}
14 1 Adrian Georgescu
 * {{{sipsimple.msrp.MSRPDesktopSharing}}}
15 1 Adrian Georgescu
16 10 Adrian Georgescu
Those 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.
17 1 Adrian Georgescu
18 10 Adrian Georgescu
To communicate with other sub-systems, the MSRP high level classes use the notification system provided by the [http://pypi.python.org/pypi/python-application python-application] package.
19 10 Adrian Georgescu
20 4 Oliver Bril
== MSRPChat ==
21 1 Adrian Georgescu
22 10 Adrian Georgescu
{{{sipsimple.msrp.MSRPChat}}} implements Instant Messaging over MSRP in the context of SIPSIMPLE middleware. This class
23 1 Adrian Georgescu
24 5 Oliver Bril
 * automatically wraps outgoing messages with Message/CPIM if that's necessary according to accept-types
25 7 Oliver Bril
 * unwraps incoming Message/CPIM messages; for each incoming message, {{{MSRPChatGotMessage}}} is posted.
26 5 Oliver Bril
 * plays notification sounds on received/sent message
27 5 Oliver Bril
28 5 Oliver Bril
=== methods ===
29 5 Oliver Bril
30 5 Oliver Bril
 '''!__init!__'''(''self'', ''account'', ''remote_uri'', ''outgoing'')::
31 5 Oliver Bril
 Initialize MSRPChat instance.
32 5 Oliver Bril
33 5 Oliver Bril
 '''initialize'''(''self'')::
34 5 Oliver Bril
 Initialize the MSRP connection; connect to the relay if necessary. When done, fire MSRPChatDidInitialize (with 'sdpmedia' attribute, containing the appropriate 'SDPMedia' instance)
35 5 Oliver Bril
36 5 Oliver Bril
 '''start'''(''self'', ''remote_media'')::
37 5 Oliver Bril
 Complete the MSRP connection establishment; this includes binding the MSRP session. [[BR]]
38 5 Oliver Bril
 When done, fire MSRPChatDidStart. At this point each incoming message is posted as a {{{MSRPChatGotMessage}}} notification
39 5 Oliver Bril
40 5 Oliver Bril
 '''end'''(''self'')::
41 5 Oliver Bril
 Close the MSRP connection or cleanup after initialize(), whatever is necessary. [[BR]]
42 5 Oliver Bril
 Before doing anything post {{{MSRPChatWillEnd}}}.
43 7 Oliver Bril
 When done, post {{{MSRPChatDidEnd}}}. If there was an error, post {{{MSRPChatDidFail}}}. 
44 5 Oliver Bril
 {{{MSRPChatDidEnd}}} will be posted anyway.
45 5 Oliver Bril
46 6 Oliver Bril
 '''send_message'''(''self'', ''content'', ''content_type''={{{'text/plain'}}}, ''to_uri''={{{None}}}, ''dt''={{{None}}})::
47 6 Oliver Bril
 Send IM message. Prefer Message/CPIM wrapper if it is supported. If called before the connection was established, the messages will be
48 6 Oliver Bril
 queued until MSRPChatDidStart notification.
49 6 Oliver Bril
50 6 Oliver Bril
 Return generated MSRP chunk (MSRPData instance); to get Message-ID use its 'message_id' attribute.
51 6 Oliver Bril
52 6 Oliver Bril
 ''content'' str:[[BR]]
53 6 Oliver Bril
 content of the message
54 6 Oliver Bril
55 6 Oliver Bril
 ''to_uri'' SIPURI:[[BR]]
56 6 Oliver Bril
 "To" header of CPIM wrapper; use to override the default supplied to {{{__init__}}}.
57 6 Oliver Bril
 May only differ from the one supplied in __init__ if the remote party supports private messages. If it does not, {{{MSRPChatError}}} will be raised;
58 6 Oliver Bril
59 6 Oliver Bril
 ''content_type'' str:[[BR]]
60 6 Oliver Bril
 Content-Type of wrapped message if Message/CPIM is used (Content-Type of MSRP message is always Message/CPIM in that case);
61 6 Oliver Bril
 otherwise, Content-Type of MSRP message.
62 6 Oliver Bril
63 6 Oliver Bril
 These MSRP headers are used to enable end-to-end success reports and to disable hop-to-hop successful responses:
64 6 Oliver Bril
{{{
65 6 Oliver Bril
Failure-Report: partial
66 6 Oliver Bril
Success-Report: yes
67 6 Oliver Bril
}}}
68 6 Oliver Bril
69 5 Oliver Bril
70 1 Adrian Georgescu
=== notifications ===
71 1 Adrian Georgescu
72 7 Oliver Bril
 * MSRPChatDidInitialize
73 7 Oliver Bril
 * MSRPChatDidStart
74 7 Oliver Bril
 * MSRPChatWillEnd
75 7 Oliver Bril
 * MSRPChatDidEnd
76 7 Oliver Bril
 * MSRPChatDidFail
77 7 Oliver Bril
 * MSRPChatGotMessage
78 7 Oliver Bril
  - cpim_headers (dict)
79 7 Oliver Bril
  - message  (MSRPData)
80 7 Oliver Bril
  - content (str) - the actual string that the remote user has typed
81 7 Oliver Bril
 * MSRPChatDidDeliverMessage
82 7 Oliver Bril
 * MSRPChatDidNotDeliverMessage
83 5 Oliver Bril
84 4 Oliver Bril
== MSRPFileTransfer ==
85 4 Oliver Bril
86 4 Oliver Bril
== MSRPDesktopSharing ==
87 4 Oliver Bril
88 4 Oliver Bril
== msrplib ==
89 4 Oliver Bril
90 1 Adrian Georgescu
{{{msrplib}}} is based upon [http://twistedmatrix.com twisted] and [http://devel.ag-projects.com/~denis/eventlet/ eventlet] and provides a set of
91 1 Adrian Georgescu
classes for establishing and managing MSRP connection.
92 1 Adrian Georgescu
93 1 Adrian Georgescu
The library consist of the following modules:
94 1 Adrian Georgescu
95 1 Adrian Georgescu
 '''msrplib.transport'''::
96 1 Adrian Georgescu
 Defines {{{MSRPTransport}}} class, which provides low level control over MSRP connection.
97 2 Redmine Admin
98 1 Adrian Georgescu
 '''msrplib.connect'''::
99 1 Adrian Georgescu
 Defines means to establish a connection, bind it, and provide an initialized {{{MSRPTransport}}} instance.
100 1 Adrian Georgescu
101 1 Adrian Georgescu
 '''msrplib.session'''::
102 1 Adrian Georgescu
 Defines {{{MSRPSession}}} class, which provides high level control over a MSRP connection.
103 1 Adrian Georgescu
104 1 Adrian Georgescu
 '''msrplib.protocol'''::
105 1 Adrian Georgescu
 Provides representation and parsing of MSRP entities - chunks and URIs.
106 1 Adrian Georgescu
107 1 Adrian Georgescu
 '''msrplib.trafficlog'''::
108 1 Adrian Georgescu
 Defines {{{Logger}}} class that is used through out the library to log the connection state.
109 1 Adrian Georgescu
  
110 4 Oliver Bril
=== Usage ===
111 1 Adrian Georgescu
112 4 Oliver Bril
==== Establish a connection ====
113 3 Oliver Bril
114 1 Adrian Georgescu
{{{msrplib.connect}}} provides a number of classes to establish a connection, so the first
115 1 Adrian Georgescu
thing to do is to select which one applies to your situation:
116 1 Adrian Georgescu
117 1 Adrian Georgescu
    1. Calling endpoint, not using a relay ({{{ConnectorDirect}}})
118 1 Adrian Georgescu
    2. Answering endpoint, not using a relay ({{{AcceptorDirect}}})
119 1 Adrian Georgescu
    3. Calling endpoint, using a relay ({{{ConnectorRelay}}})
120 1 Adrian Georgescu
    4. Answering endpoint, using a relay ({{{AcceptorRelay}}})
121 1 Adrian Georgescu
122 1 Adrian Georgescu
The answering endpoint may skip using the relay if sure that it's accessible
123 1 Adrian Georgescu
directly. The calling endpoint is unlikely to need the relay.
124 1 Adrian Georgescu
125 1 Adrian Georgescu
Once you have an instance of the right class (use the convenience functions
126 1 Adrian Georgescu
{{{get_connector()}}} and {{{get_acceptor()}}} to get one), the procedure to establish the
127 1 Adrian Georgescu
connection is the same:
128 1 Adrian Georgescu
129 1 Adrian Georgescu
{{{
130 1 Adrian Georgescu
full_local_path = connector.prepare()
131 1 Adrian Georgescu
try:
132 1 Adrian Georgescu
    ... put full_local_path in SDP 'a:path' attribute
133 1 Adrian Georgescu
    ... get full_remote_path from remote's 'a:path: attribute
134 1 Adrian Georgescu
    ... (the order of the above steps is reversed if you're the
135 1 Adrian Georgescu
    ... answering party, but that does not affect connector's usage)
136 1 Adrian Georgescu
    msrptransport = connector.complete(full_remote_path)
137 1 Adrian Georgescu
finally:
138 1 Adrian Georgescu
    connector.cleanup()
139 1 Adrian Georgescu
}}}
140 1 Adrian Georgescu
141 1 Adrian Georgescu
To customize connection's parameters, create a new {{{protocol.URI}}} object and pass
142 1 Adrian Georgescu
it to prepare() function, e.g.
143 1 Adrian Georgescu
{{{
144 1 Adrian Georgescu
local_uri = protocol.URI(use_tls=False, port=5000)
145 1 Adrian Georgescu
connector.prepare(local_uri)
146 1 Adrian Georgescu
}}}
147 1 Adrian Georgescu
148 1 Adrian Georgescu
{{{prepare()}}} may update {{{local_uri}}} in place with the actual connection parameters
149 1 Adrian Georgescu
used (e.g. if you specified port=0). 'port' attribute of {{{local_uri}}} is currently
150 1 Adrian Georgescu
only respected by {{{AcceptorDirect}}}.
151 1 Adrian Georgescu
152 1 Adrian Georgescu
Note that, acceptors and connectors are one-use only. Which means, that {{{AcceptorDirect}}}
153 1 Adrian Georgescu
will open a port just to handle one incoming connection and close it right after.
154 1 Adrian Georgescu
If your application behaves more like a server, i.e. opens a port and listens on it
155 1 Adrian Georgescu
constantly, use {{{MSRPServer}}} class.
156 3 Oliver Bril
157 4 Oliver Bril
=== Components ===
158 1 Adrian Georgescu
159 4 Oliver Bril
==== a connector or acceptor ====
160 3 Oliver Bril
161 8 Oliver Bril
 {{{msrplib.connect}}} provides 2 connectors (with and without relay) and 2 acceptors (likewise, with or without relay). All of them have the exact same interface,
162 8 Oliver Bril
163 8 Oliver Bril
 '''prepare'''(''self'', ''local_uri''={{{None}}})::
164 8 Oliver Bril
 Depending on type of the connector, use local_uri to prepare the MSRP connection, which means:
165 8 Oliver Bril
 * connecting and authenticating at the relay if a relay is used ({{{ConnectorRelay}}} and {{{AcceptorRelay}}})
166 8 Oliver Bril
 * start listening on a local port for DirectAcceptor
167 8 Oliver Bril
168 8 Oliver Bril
 ''local_uri'' is used to specify the connection parameters, e.g. local port and local ip.
169 8 Oliver Bril
 If not provided, suitable ''local_uri'' will be generated.
170 8 Oliver Bril
 ''local_uri'' maybe updated in place by {{{prepare()}}} method if the real settings used are different from those specified.
171 8 Oliver Bril
172 8 Oliver Bril
 {{{prepare}}} returns a full local path - list of {{{protocol.URI}}} instances, suitable to be put in SDP {{{'a:path'}}} attribute.
173 8 Oliver Bril
 
174 8 Oliver Bril
 '''complete'''(''self'', ''full_remote_path'')::
175 8 Oliver Bril
 Complete establishing the MSRP connection, which means
176 8 Oliver Bril
 * establishing the connection if it wasn't already established ({{{ConnectorDirect}}})
177 8 Oliver Bril
 * bind the connection, i.e. exchange empty chunk to verify each other's From-Path and To-Path
178 8 Oliver Bril
179 8 Oliver Bril
 ''full_remote_path'' should be a list of {{{protocol.URI}}} instances, obtained by parsing {{{'a:path'}}} put in SDP by the remote party.
180 8 Oliver Bril
181 8 Oliver Bril
 {{{complete}}} returns {{{transport.MSRPTransport}}} instance, ready to read and send chunks.
182 9 Oliver Bril
183 9 Oliver Bril
 '''cleanup'''(''self'')::
184 9 Oliver Bril
 Call this method to cleanup after {{{initialize()}}} if it's impossible to call {{{complete()}}}
185 8 Oliver Bril
 
186 1 Adrian Georgescu
187 4 Oliver Bril
==== transport.MSRPTransport ====
188 1 Adrian Georgescu
189 1 Adrian Georgescu
Low level access to MSRP connection.
190 1 Adrian Georgescu
191 4 Oliver Bril
===== attributes =====
192 3 Oliver Bril
193 4 Oliver Bril
===== methods =====
194 3 Oliver Bril
195 3 Oliver Bril
 '''make_chunk'''(''self'', ''transaction_id''={{{None}}}, ''method''={{{'SEND'}}}, ''code''={{{None}}}, ''comment''={{{None}}}, ''data''={{{''}}}, ''contflag''={{{None}}}, ''start''={{{1}}}, ''end''={{{None}}}, ''length''={{{None}}}, ''message_id''={{{None}}})::
196 1 Adrian Georgescu
 Make a new chunk ({{{protocol.MSRPData}}} instance) with proper {{{From-Path}}}, {{{To-Path}}}, {{{Byte-Range}}} and {{{Message-ID}}} headers set up based on MSRPTransport's state and the parameters provided. Use ''data'' for payload, and ''start''/''end''/''length'' to generate {{{Byte-Range}}} header. Generate new random strings for default values of ''transaction_id'' and ''message_id''. 
197 1 Adrian Georgescu
 [[BR]]''contflag'':[[BR]]
198 1 Adrian Georgescu
 MSRP chunk's continuation flag ({{{'$'}}}, {{{'+'}}} or {{{'#'}}}). Default is {{{'$'}}}, unless you have a partial {{{SEND}}} chunk, in which case it is {{{'+'}}}
199 1 Adrian Georgescu
200 4 Oliver Bril
==== session.MSRPSession ====
201 4 Oliver Bril
===== attributes =====
202 4 Oliver Bril
===== methods =====
203 1 Adrian Georgescu
204 4 Oliver Bril
==== connect.MSRPServer ====
205 4 Oliver Bril
===== attributes =====
206 4 Oliver Bril
===== methods =====