Browse code

doc: xmlrpc README added

Andrei Pelinescu-Onciul authored on 11/05/2009 14:51:05
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,521 @@
1
+Jan Janak
2
+
3
+   iptelorg GmbH
4
+
5
+   Copyright � 2005 iptelorg GmbH
6
+   Revision History
7
+   Revision $Revision$ $Date$
8
+     __________________________________________________________________
9
+
10
+   1.1. Design Goals
11
+   1.2. Overview of Operation
12
+   1.3. XML-RPC Implementation
13
+
14
+        1.3.1. Requests
15
+        1.3.2. Replies
16
+        1.3.3. Type Conversion
17
+        1.3.4. Limitations
18
+
19
+   1.4. Client Examples
20
+   1.5. Parameters
21
+
22
+        1.5.1. route (string)
23
+
24
+   1.6. Functions
25
+
26
+        1.6.1. dispatch_rpc()
27
+        1.6.2. xmlrpc_reply(code, reason)
28
+
29
+1.1. Design Goals
30
+
31
+     * Implemented as a module.
32
+     * API independent of transport protocols.
33
+     * Reuse transports available in SER.
34
+     * The possibility to encrypt all communication.
35
+     * The possibility to authenticate clients.
36
+     * Easy integration with existing languages and implementations.
37
+     * Easy and straightforward implementation of management functions in
38
+       SER modules.
39
+
40
+1.2. Overview of Operation
41
+
42
+   This module implements the XML-RPC transport and encoding interface for
43
+   ser RPCs.
44
+
45
+   The XML-RPC protocol encodes the name of the method to be called along
46
+   with its parameter in an XML document which is then conveyed using HTTP
47
+   (Hyper Text Transfer Protocol) to the server. The server will extract
48
+   the name of the function to be called along with its parameters from
49
+   the XML document, execute the function, and encode any data returned by
50
+   the function into another XML document which is then returned to the
51
+   client in the body of a 200 OK reply to the HTTP request.
52
+
53
+   XML-RPC is similar to more popular SOAP (Simple Object Access
54
+   Protocol), which is an XML-based messaging framework used in Web
55
+   Services developed within the World Wide Web Consortium. Both protocols
56
+   are using HTTP as the transport protocol for XML documents, but XML-RPC
57
+   is much simpler and easier to implement than SOAP.
58
+
59
+   Here is an example of single XML-RPC function call to determine current
60
+   time:
61
+POST /RPC2 HTTP/1.0
62
+User-Agent: Radio UserLand/7.1b7 (WinNT)
63
+Host: time.xmlrpc.com
64
+Content-Type: text/xml
65
+Content-length: 131
66
+
67
+<?xml version="1.0"?>
68
+<methodCall>
69
+<methodName>currentTime.getCurrentTime</methodName>
70
+<params>
71
+</params>
72
+</methodCall>
73
+
74
+   And the response returned by the server:
75
+HTTP/1.1 200 OK
76
+Connection: close
77
+Content-Length: 183
78
+Content-Type: text/xml
79
+Date: Wed, 03 Oct 2001 15:53:38 GMT
80
+Server: UserLand Frontier/7.0.1-WinNT
81
+
82
+<?xml version="1.0"?>
83
+<methodResponse>
84
+<params>
85
+<param>
86
+<value><dateTime.iso8601>20011003T08:53:38</dateTime.iso8601>
87
+</value>
88
+</param>
89
+</params>
90
+</methodResponse>
91
+
92
+   XML-RPC specification spells HTTP as the official transport protocol
93
+   for XML-RPC documents. SER does not directly support HTTP, it is a SIP
94
+   server so SIP is the only protocol supported by SER. Because we would
95
+   like to reuse all transport protocols available in SER, such as TCP and
96
+   TLS, it would be natural to use modified version of XML-RPC which would
97
+   run on top of SIP instead of HTTP. XML-RPC documents would be then
98
+   encoded in the bodies of SIP requests and replies would be sent by the
99
+   server in the bodies of SIP replies. This way we could reuse all
100
+   transport protocols (including UDP) and message parsers available in
101
+   SER.
102
+
103
+   Although this approach seems to be the logical choice, there is one big
104
+   drawback. No existing XML-RPC implementations support SIP as the
105
+   transport protocol, and there are many existing implementations
106
+   available for vast majority of existing languages. See the XML-RPC
107
+   implementation page for more details. Extending existing
108
+   implementations with SIP support would not be easy.
109
+
110
+   Because extending available XML-RPC implementation would be too
111
+   expensive, we could also do it the other way around, keep existing
112
+   XML-RPC implementations and extend SER to support HTTP. Extending SER
113
+   with HTTP support is easier than it might seem at a first glance, due
114
+   to the similarity between SIP requests and HTTP requests.
115
+
116
+   SER already supports TCP, so existing HTTP implementations can send
117
+   HTTP requests to it. HTTP requests are missing certain mandatory SIP
118
+   header fields, such as Via, From, and CSeq. The contents of the header
119
+   fields is mainly used for transaction matching. A SIP server could
120
+   perform two basic operations when processing an HTTP request:
121
+     * Terminate the request, execute the function and send a reply back.
122
+     * Forward the request to another SIP server.
123
+
124
+   Nothing special is needed on the SIP server terminating the request,
125
+   except that it has to know where it should send the reply. Parsing of
126
+   HTTP header field bodies would fail because we do not have parsers for
127
+   them in SER, but that does not matter anyway because all the
128
+   information is encoded in the body of the request. HTTP requests
129
+   contain no Via header fields. Via header fields are used by SIP
130
+   implementations to determine the destination (IP, transport protocol,
131
+   and port number) for replies. When processing HTTP requests the SIP
132
+   server needs to create a fake Via header field based on the source IP
133
+   address and port number of the TCP connection. The SIP server will use
134
+   this information when sending a reply back.
135
+
136
+   Forwarding of HTTP requests by SIP proxies is a little bit more
137
+   complicated and there are several limitations. First of all, we can
138
+   only use stateless forwarding, no transactional forwarding, because
139
+   HTTP requests do not contain all the header fields needed for
140
+   transaction matching. Any attempt to call t_relay on an HTTP requests
141
+   would fail. HTTP requests always use TCP and thus we could use
142
+   stateless forwarding on the SIP server, provided that the request will
143
+   be also forwarded over TCP. Stateless forwarding does not require the
144
+   mandatory header fields (which are missing here) and it would work. In
145
+   addition to that, the SIP server would also append fake Via header
146
+   field to the request and change the contents of the Request-URI. The
147
+   Request-URI of HTTP requests sent by XML-RPC implementations typically
148
+   contain something like "/RPC2" and the first SIP server processing the
149
+   request should rewrite the value with a valid SIP URI.
150
+
151
+   Figure RPC Example shows a scenario which involves two SIP servers, one
152
+   performs HTTP request "normalization" and forwarding, and the other
153
+   terminates the request, executes corresponding function, and generates
154
+   a reply.
155
+
156
+                              [rpc_example.png]
157
+
158
+   Example RPC Scenario
159
+
160
+   Step 1. An HTTP user agent sends an ordinary HTTP request to a SIP
161
+   server. The user agent can either establish a connection directly to
162
+   port 5060 or the SIP server can be configured to listen on port 80. The
163
+   request contains standard HTTP headers and an XML-RPC document in the
164
+   body:
165
+POST / HTTP/1.0.
166
+Host: localhost:5060
167
+User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)
168
+Content-Type: text/xml
169
+Content-Length: 111
170
+
171
+<?xml version='1.0'?>
172
+<methodCall>
173
+<methodName>usrloc.statistics</methodName>
174
+<params>
175
+</params>
176
+</methodCall>
177
+
178
+   This particular request calls method "statistics" from from usrloc
179
+   module of SER. The method has no parameters.
180
+
181
+   The outbound SIP server receives the HTTP request and performs a set of
182
+   actions called "SIP-normalization". This includes creation of fake Via
183
+   header field based on the source IP and port of the TCP connection,
184
+   looking up of the target SIP server that should terminate and process
185
+   the request, and rewriting of the Request-URI with the SIP URI of the
186
+   target SIP server. Modified HTTP request will be then forwarded
187
+   statelessly to the target SIP server.
188
+POST sip:proxy01.sip-server.net HTTP/1.0
189
+Via: SIP/2.0/TCP 127.0.0.1:3571
190
+Host: localhost:5060
191
+User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)
192
+Content-Type: text/xml
193
+Content-Length: 111
194
+
195
+<?xml version='1.0'?>
196
+<methodCall>
197
+<methodName>usrloc.statistics</methodName>
198
+<params>
199
+</params>
200
+</methodCall>
201
+
202
+   Step 2. "normalized" HTTP request is statelessly forwarded to the
203
+   target SIP server over TCP.
204
+
205
+   Step 3. The target SIP server receives the HTTP request and executes
206
+   function called dispatch_rpc from xmlrpc SER module. This function will
207
+   parse the XML-RPC document in the body of the request and lookup the
208
+   function to be called among all RPC functions exported by the SER core
209
+   and modules. Function dispatch_rpc will be called from the
210
+   configuration file just like any other function:
211
+if (method == "POST" || method == "GET") {
212
+    dispatch_rpc();
213
+    break;
214
+};
215
+
216
+   This particular configuration snippet executes the function whenever
217
+   SER receives GET or POST requests. These two method names indicate
218
+   HTTP.
219
+
220
+   Step 4. Function dispatch_rpc scans through the list of all exported
221
+   RPC functions searching for statistics function of usrloc module. The
222
+   SER RPC Module API describes in detail how modules export RPC
223
+   functions.
224
+
225
+   Step 5. As the RPC function from usrloc module is running and gathering
226
+   statistics, it calls functions of RPC interface to prepare the result
227
+   for the caller.
228
+
229
+   Step 6. Once the RPC function finishes, xmlrpc module will build the
230
+   XML-RPC document from the data received from usrloc module and generate
231
+   a reply which will be sent to the caller.
232
+
233
+   Steps 7. and 8. HTTP reply is sent back to the caller and the remote
234
+   procedure call finishes.
235
+HTTP/1.0 200 OK
236
+Via: SIP/2.0/TCP 127.0.0.1:3571
237
+Server: Sip EXpress router (0.10.99-janakj_experimental (i386/linux))
238
+Content-Length: 651
239
+Warning: 392 127.0.0.1:5060 "Noisy feedback tells:  pid=9975 req_src_ip=127.0.0
240
+1 req_src_port=3571 in_uri=/ out_uri=sip:proxy01.sip-server.net via_cnt==1"
241
+
242
+<?xml version="1.0" encoding="UTF-8"?>
243
+<methodResponse>
244
+<params>
245
+<param><value><array><data>
246
+<value><struct>
247
+<member><name>domain</name>
248
+<value><string>aliases</string></value></member>
249
+<member><name>users</name>
250
+<value><i4>0</i4></value></member>
251
+<member><name>expired</name>
252
+<value><i4>0</i4></value></member>
253
+</struct></value>
254
+<value><struct>
255
+<member><name>domain</name>
256
+<value><string>location</string></value></member>
257
+<member><name>users</name>
258
+<value><i4>0</i4></value></member>
259
+<member><name>expired</name>
260
+<value><i4>0</i4></value></member>
261
+</struct></value>
262
+</data></array></value></param>
263
+</params>
264
+</methodResponse>
265
+
266
+Note
267
+
268
+   The scenario described on Figure RPC Example involves two SIP servers.
269
+   This is just to demonstrate that in setups containing more SIP servers
270
+   it is possible to forward HTTP requests from one SIP server to another
271
+   and use standard SIP routing mechanisms to decide which SIP server
272
+   should process the request. There is no need to have multiple SIP
273
+   servers in simple setups, because one SIP server can both add fake Via
274
+   header field and process the RPC at the same time. Modified
275
+   configuration file snipped could then look like this:
276
+if (method == "POST" || method == "GET") {
277
+    dispatch_rpc(); # Process the request
278
+    break;
279
+};
280
+
281
+1.3. XML-RPC Implementation
282
+
283
+   The purpose of the functions of this module is to convert XML-RPC
284
+   document carried in the body of HTTP requests into data returned by the
285
+   RPC interface and back. The module also contains functions necessary to
286
+   "normalize" HTTP requests. The module uses xmlrpc-c library to perform
287
+   XML-RPC related functions.
288
+
289
+   The module always returns 200 OK HTTP reply, it will never return any
290
+   other HTTP reply. Failures are expressed in XML-RPC documents in the
291
+   body of the reply. There is basic method introspection support in the
292
+   module. Currently the module can list all functions exported by the
293
+   server and for each function it can return the documentation string
294
+   describing the function.
295
+
296
+1.3.1. Requests
297
+
298
+   Requests processed by the module are standard XML-RPC requests encoded
299
+   in bodies of HTTP requests.
300
+POST / HTTP/1.0
301
+Host: localhost:5060
302
+User-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)
303
+Content-Type: text/xml
304
+Content-Length: 112
305
+
306
+<?xml version='1.0'?>
307
+<methodCall>
308
+<methodName>system.listMethods</methodName>
309
+<params>
310
+</params>
311
+</methodCall>
312
+
313
+   The name of the method to be called in this example is "listMethods".
314
+   This is one of the introspection methods. SER will call dispatch_rpc
315
+   function of xmlrpc module to handle the request. The function will
316
+   parse the XML-RPC document, lookup listMethods function in the list of
317
+   all export RPC functions, prepare the context for the function and
318
+   execute it.
319
+
320
+1.3.2. Replies
321
+
322
+   The module will always generate 200 OK. Other response codes and
323
+   classes are reserved for SER. The status code of the XML-RPC reply,
324
+   response code, and additional data will be encoded in the body of the
325
+   reply. Failure replies do not contain any data, just the response code
326
+   and reason phrase:
327
+HTTP/1.0 200 OK
328
+Via: SIP/2.0/TCP 127.0.0.1:2464
329
+Server: Sip EXpress router (0.10.99-janakj_experimental (i386/linux))
330
+Content-Length: 301
331
+
332
+<?xml version="1.0" encoding="UTF-8"?>
333
+<methodResponse>
334
+
335
+<fault>
336
+<value><struct>
337
+<member><name>faultCode</name>
338
+<value><i4>501</i4></value></member>
339
+<member><name>faultString</name>
340
+<value><string>Method Not Implemented</string></value></member>
341
+</struct></value>
342
+</fault>
343
+
344
+</methodResponse>
345
+
346
+   This particular reply indicates that there is no such RPC method
347
+   available on the server.
348
+
349
+   Success replies always contain at least one return value. In our case
350
+   the simplest success replies contain single boolean with value 1:
351
+HTTP/1.0 200 OK
352
+Via: SIP/2.0/TCP 127.0.0.1:4626
353
+Server: Sip EXpress router (0.10.99-janakj_experimental (i386/linux))
354
+Content-Length: 150
355
+
356
+<?xml version="1.0" encoding="UTF-8"?>
357
+<methodResponse>
358
+<params>
359
+<param><value><boolean>1</boolean></value></param>
360
+</params>
361
+</methodResponse>
362
+
363
+   This is exactly how the reply looks like when an RPC function does not
364
+   add any data to the reply set.
365
+
366
+   If an RPC function adds just a single item (it calls add once with just
367
+   one character in the formatting string) then the data will be converted
368
+   to XML-RPC representation according to the rules described in SER RPC
369
+   Type Converion and the reply will contain just the single value:
370
+HTTP/1.0 200 OK
371
+Via: SIP/2.0/TCP 127.0.0.1:3793
372
+Server: Sip EXpress router (0.10.99-janakj_experimental (i386/linux))
373
+Content-Length: 216
374
+
375
+<?xml version="1.0" encoding="UTF-8"?>
376
+<methodResponse>
377
+<params>
378
+<param><value><string>Server: Sip EXpress router (0.10.99-janakj_experimental (i
379
+386/linux))</string></value></param>
380
+</params>
381
+</methodResponse>
382
+
383
+   If an RPC function adds more than one data items to the result set then
384
+   the module will return an array containing all the data items:
385
+HTTP/1.0 200 OK
386
+Via: SIP/2.0/TCP 127.0.0.1:2932
387
+Server: Sip EXpress router (0.10.99-janakj_experimental (i386/linux))
388
+Content-Length: 276
389
+
390
+<?xml version="1.0" encoding="UTF-8"?>
391
+<methodResponse>
392
+<params>
393
+<param><value><array><data>
394
+<value><string>./ser</string></value>
395
+<value><string>-f</string></value>
396
+<value><string>ser.cfg</string></value>
397
+</data></array></value></param>
398
+</params>
399
+</methodResponse>
400
+
401
+   This is probably the most common scenario.
402
+
403
+1.3.3. Type Conversion
404
+
405
+   The data types of the RPC API are converted to the data types of
406
+   XML-RPC and vice versa. Table 1, "Data Type Conversion" shows for each
407
+   RPC API data type corresponding XML-RPC data type.
408
+
409
+   Table 1. Data Type Conversion
410
+   RPC API XML-RPC RPC Example XML-RPC Example
411
+   Integer <i4></i4> rpc->add("d", 42) <i4>42</i4>
412
+   Float <double></double> rpc->add("f", -12.214) <double>-12.214</double>
413
+   String <string></string> rpc->add("s","Don't panic") <string>Don't
414
+   panic</string>
415
+   Struct <struct></struct>
416
+   rpc->struct_add(handle,"sd","param1",42,"param2",-12.214)
417
+<struct>
418
+  <member>
419
+    <name>param1</name>
420
+    <value>
421
+      <i4>42</i4>
422
+    </value>
423
+  </member>
424
+  <member>
425
+    <name>param2</name>
426
+    <value>
427
+      <double>-12.214</i4>
428
+    </value>
429
+  </member>
430
+</struct>
431
+
432
+1.3.4. Limitations
433
+
434
+   SER xmlrpc modules does not implement all data types allowed in
435
+   XML-RPC. As well it does not implement arrays and nested structures.
436
+   This simplification is a feature, not bug. In our case the XML-RPC
437
+   interface will be used mainly for management purposes and we do not
438
+   need all the bells and whistles of XML-RPC. Parsing and interpreting
439
+   nested structures is complex and we try to avoid it.
440
+
441
+1.4. Client Examples
442
+
443
+     * ser_ctl (python application that uses the XML-RPC interface
444
+       implemented by the xmlrpc module).
445
+     * serweb (php application that can use the XML-RPC interface to call
446
+       ser functions).
447
+
448
+1.5. Parameters
449
+
450
+   Revision History
451
+   Revision $Revision$ $Date$
452
+
453
+1.5.1. route (string)
454
+
455
+   Name of the route called for XMLRPC messages.
456
+
457
+   This route will be called only for HTTP messages whose method is either
458
+   GET or POST. The message visible inside the route will be a HTTP
459
+   request converted to SIP (the uri will be fixed and a fake via will be
460
+   added).
461
+
462
+   The route should perform additional security checks to ensure the
463
+   client is authorized to execute management/RPC functions and then it
464
+   should call the dispatch_rpc().
465
+
466
+   Default: the main route is used.
467
+
468
+   Example 1. Set route parameter
469
+modparam("xmlrpc", "route", "route_for_xmlrpcs")
470
+
471
+1.6. Functions
472
+
473
+   Revision History
474
+   Revision $Revision$ $Date$
475
+
476
+1.6.1.  dispatch_rpc()
477
+
478
+   This function processes an XMLRPC request, found in the body of the
479
+   request.
480
+
481
+   It should be used only in a route specified using the "route" module
482
+   parameter or if the request method is GET or POST (using it for other
483
+   request methods will not have adverse side-effects, but it will
484
+   probably not work).
485
+
486
+   dispatch_rpc() extracts the XML-RPC document from the body of the
487
+   request to determine the name of the RPC method to be called and then
488
+   it searches through the list of all the RPC functions to find a
489
+   function with matching name. If such a function is found then
490
+   dispatch_rpc() will pass control to the function to handle the request.
491
+
492
+   Example 2. dispatch_rpc usage
493
+#...
494
+modparam("xmlrpc", "route", "XMLRPC");
495
+#...
496
+route[XMLRPC]{
497
+        dispatch_rpc();
498
+}
499
+
500
+1.6.2.  xmlrpc_reply(code, reason)
501
+
502
+   This function can be called from the config script to directly generate
503
+   an XML-RPC reply.
504
+
505
+   Example 3. xmlrpc_reply usage
506
+#...
507
+modparam("xmlrpc", "route", "XMLRPC");
508
+#...
509
+route[XMLRPC]{
510
+        # allow XMLRPC requests only on TLS and only if the client
511
+        # certificate is valid
512
+        if (proto!=TLS){
513
+                xmlrpc_reply("400", "xmlrpc allowed only over TLS");
514
+                return;
515
+        }
516
+        if (@tls.peer.verified!=""){
517
+                xmlrpc_reply("400", "Unauthorized");
518
+                return;
519
+        }
520
+        dispatch_rpc();
521
+}