kamailio_rpc.txt 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. 1. The Kamailio RPC Control Interface
  2. __________________________________________________________________
  3. 1.1. Overview of Operation
  4. 1.2. Module API
  5. 1.2.1. RPC Functions
  6. 1.2.2. Data Types
  7. 1.2.3. Getting Parameters
  8. 1.2.3.1. scan
  9. 1.2.3.2. struct_scan
  10. 1.2.3.3. Retrieving Parameters Example
  11. 1.2.4. Building Reply
  12. 1.2.4.1. fault
  13. 1.2.4.2. send
  14. 1.2.4.3. add
  15. 1.2.4.4. rpl_printf
  16. 1.2.4.5. struct_add
  17. 1.2.5. Real World Example
  18. 1.3. Client Examples
  19. 1.4. Implementing New Transports
  20. 1.5. Examples using xmlrpc
  21. 1.1. Overview of Operation
  22. The RPC (Remote Procedure Call) interface is an interface for
  23. communicating with external applications. Using it an external
  24. application can call a function or procedure that will be executed
  25. inside Kamailio. Function parameters are supported as well as returning
  26. multiple values as results.
  27. By itself RPC consists of two APIs, one for defining RPC functions in a
  28. transport independent way (called the rpc module api) and one for
  29. implementing RPC transports.
  30. The RPC transports are implemented by writting a RPC transport module.
  31. The most used transport modules are ctl , xmlrpc and jsonrpc-s .
  32. ctl implements a proprietary fast and space efficient RPC encoding over
  33. different protocols (unix sockets, UDP, TCP, fifo).
  34. xmlrpc uses the de-facto XML-RPC standard encoding (over HTTP TCP or
  35. TLS).
  36. jsonrpc-s uses the de-facto JSON-RPC standard encoding (over HTTP TCP
  37. or TLS).
  38. For more information about the existing transport modules, please refer
  39. to their documentation.
  40. When writing a RPC procedure or function, one needs only use the RPC
  41. API and it will work automatically with all the transports and
  42. encodings. One needs only to load the desired RPC transport module
  43. (e.g. xmlrpc).
  44. The RPC interface (or API) was created in such a way that would allow
  45. supporting XML-RPC (because XML-RPC is a de-facto standard), while in
  46. the same time being very easy to use.
  47. 1.2. Module API
  48. Each module can export RPC functions just like it can export parameters
  49. and functions to be called from the script. Whenever Kamailio receives
  50. an RPC request, it will search through the list of exported RPC
  51. functions and the function with matching name will be executed. A
  52. couple of essential RPC functions are also embedded into the SIP server
  53. core.
  54. This section gives a detailed overview of the whole RPC API.
  55. Section 1.2.1, "RPC Functions" describes the prototype and conventions
  56. used in RPC functions. Section 1.2.2, "Data Types" gives a detailed
  57. overview of available data types that can be used in function
  58. parameters and return value. Section 1.2.3, "Getting Parameters"
  59. describes functions of the RPC API that can be used to retrieve
  60. parameters of the function, and finally Section 1.2.4, "Building Reply"
  61. describes functions of the API that can be used to build the result
  62. value that will be sent in the reply to the caller.
  63. The whole RPC API is described in header file kamailio/rpc.h. This file
  64. defines the set of functions that must be implemented by RPC transport
  65. modules, as described in Section 1.4, "Implementing New Transports",
  66. prototypes of RPC functions and structures used for the communication
  67. between RPC transport modules and ordinary modules exporting RPC
  68. functions.
  69. 1.2.1. RPC Functions
  70. RPC functions are standard C functions with the following prototype:
  71. typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
  72. RPC functions take two parameters, first parameter is a pointer to
  73. rpc_t structure and the context. The rpc_t structure contains
  74. references to all API functions available to the RPC function as well
  75. as all data necessary to create the response. RPC functions do not
  76. return any value, instead the return value is created using functions
  77. from the context. The motivation for this decision is the fact that RPC
  78. functions should always return a response and even the API functions
  79. called from RPC functions should have the possibility to indicate an
  80. error (and should not rely on RPC functions doing so).
  81. If no reply is sent explicitely, the RPC transport module will
  82. automatically send a "success" reply (e.g. 200 OK for XML-RPC) when the
  83. RPC function finishes. If no values are added to the response, the
  84. reponse will be an empty "success" reply (e.g. a 200 OK with empty body
  85. for XML-RPC). RPC API functions will automatically send an error reply
  86. upon a failure.
  87. Each RPC function has associated an array of documentation strings. The
  88. purpose of the documentation strings is to give a short overview of the
  89. function, accepted parameters, and format of the reply. By convention
  90. the name of the documentation string array is same as the name of the
  91. function with "_doc" suffix.
  92. Each module containing RPC functions has to export all the RPC
  93. functions to the Kamailio core in order to make them visible to the RPC
  94. transport modules. The export process involves a rpc_export_t structure
  95. (either by itself or in an array):
  96. typedef struct rpc_export {
  97. const char* name; /* Name of the RPC function (null terminated) */
  98. rpc_function_t function; /* Pointer to the function */
  99. const char** doc_str; /* Documentation strings, method signature and desc
  100. ription */
  101. unsigned int flags; /* Various flags, reserved for future use */
  102. } rpc_export_t;
  103. The flags attribute of the rpc_export structure is reserved for future
  104. use and is currently unused.
  105. There are several ways of exporting the RPC functions to the Kamailio
  106. core:
  107. * register a null terminated array of rpc_export_t structures using
  108. the rpc_register_array() function (defined in rpc_lookup.h), from
  109. the module init function (mod_init()). This is the recommended
  110. method for all the new modules.
  111. Example 1. usrloc RPC Exports Declaration
  112. The rpc_export_t array for the modules_s/usrloc module looks like:
  113. rpc_export_t ul_rpc[] = {
  114. {"usrloc.statistics", rpc_stats, rpc_stats_doc, 0},
  115. {"usrloc.delete_aor", rpc_delete_aor, rpc_delete_aor_doc, 0},
  116. {"usrloc.delete_contact", rpc_delete_contact, rpc_delete_contact_doc, 0},
  117. {"usrloc.dump", rpc_dump, rpc_dump_doc, 0},
  118. {"usrloc.flush", rpc_flush, rpc_flush_doc, 0},
  119. {"usrloc.add_contact", rpc_add_contact, rpc_add_contact_doc, 0},
  120. {"usrloc.show_contacts", rpc_show_contacts, rpc_show_contacts_doc, 0},
  121. {0, 0, 0, 0}
  122. };
  123. To register it from the module init function one would use
  124. something similar to:
  125. if (rpc_register_array(ul_rpc) != 0) {
  126. ERR("failed to register RPC commands\n");
  127. return -1;
  128. }
  129. * register RPCs one by one using the rpc_register_function() (defined
  130. in rpc_lookup.h), from the module init function.
  131. * register a null terminated array of rpc_export_t structures using
  132. the Kamailio module interface SER_MOD_INTERFACE For this purpose,
  133. the module_exports structure of the Kamailio module API contains a
  134. new attribute called rpc_methods:
  135. struct module_exports {
  136. char* name; /* null terminated module name */
  137. cmd_export_t* cmds; /* null terminated array of the exported command
  138. s */
  139. rpc_export_t* rpc_methods; /* null terminated array of exported rpc methods
  140. */
  141. param_export_t* params; /* null terminated array of the exported module
  142. parameters */
  143. init_function init_f; /* Initialization function */
  144. response_function response_f; /* function used for responses */
  145. destroy_function destroy_f; /* function called upon shutdown */
  146. onbreak_function onbreak_f;
  147. child_init_function init_child_f; /* function called by all processes after
  148. the fork */
  149. };
  150. rpc_methods is a pointer to an array of rpc_export_t structures.
  151. The last element of the array is a bumper containing zeroes in all
  152. the attributes of the structure. The following program listing
  153. shows the exported RPC functions of the modules_s/usrloc module,
  154. using the rpc_export_t array ul_rpc defined above, in the
  155. rpc_register_array() example:
  156. Example 2. usrloc Module Exports Declaration
  157. struct module_exports exports = {
  158. "usrloc",
  159. cmds, /* Exported functions */
  160. ul_rpc, /* RPC methods */
  161. params, /* Export parameters */
  162. mod_init, /* Module initialization function */
  163. 0, /* Response function */
  164. destroy, /* Destroy function */
  165. 0, /* OnCancel function */
  166. child_init /* Child initialization function */ };
  167. Note
  168. This mode works only with modules using the SER flavour module
  169. interface. It does not work for Kamailio modules and it will
  170. probably not work for future sip-router modules. It is safer and
  171. recommended to use instead the rpc_register_array() function.
  172. By convention the name of every exported function consists of two parts
  173. delimited by a dot. The first part is the name of the module or
  174. Kamailio subsystem this function belongs to. The second part is the
  175. name of the function.
  176. 1.2.2. Data Types
  177. The RPC API defines several basic and one compound data type that can
  178. be used in communication with the caller of RPC functions. The RPC API
  179. uses formating strings to describe data types. Each data type is
  180. described by exactly one character in the formating string. For
  181. example, if an RPC function calls function add of the RPC API and it
  182. passes two parameters to it, the first one of type string and the
  183. second one of type integer, the function parameters will look like:
  184. add("sd", string_param, int_param);
  185. Character "s" in the formating string tells to the function that the
  186. 2nd parameter should be interpreted as string, character "d" in the
  187. formating string tells to the function that the 3rd parameter should be
  188. interpreted as signed integer.
  189. Integer. Integer type represents a signed 32-bit integer.
  190. Corresponding character in the formating string is "d". This parameter
  191. can be stored in C-style variable with type int.
  192. Float. Float type represents a signed floating point number.
  193. Corresponding character in the formating string is "f". Data of this
  194. type can be stored in C-style variables of type double.
  195. String. String type represents a string of characters. The string may
  196. contain zeroes. This data type is represented by two characters in the
  197. formatting string, either "s" or "S". "s" indicates to the conversion
  198. function that the result should be stored in a variable of type char*
  199. and it should be zero terminated. "S" indicates to the conversion
  200. function that the result will be stored in a variable of type str which
  201. contains both the pointer to the beginning of the string and its
  202. length.
  203. Structure. Structure is the only compound data type currently defined
  204. in the API. A structure is a collection of attributes. Each attribute
  205. is identified using name (string) and each attribute can be one of the
  206. basic data types, that is integer, float, or string. Nesting of
  207. structures is not allowed (in other words, structure attributes cannot
  208. be of type struct again). Corresponding character in the formatting
  209. string is "{".
  210. Optional parameters. Optional parameters can be used, but only in the
  211. scan function. For optional parameters the scan function will not
  212. automatically generate a rpc fault if the input ends. Note that in this
  213. case the scan will still return a negative value (minus the number of
  214. parameters successfully read). Optional parameters can be marked in the
  215. format string by preceding the first optional parameter type with a
  216. "*". All the parameters following a "*" are considered to be optional.
  217. For example for the format string "ds*dds", the last 3 parameters (2
  218. ints and a string) are optional.
  219. Table 1. Data Type Overview
  220. Name Formating String Char C-Style Variable
  221. Integer d int
  222. Float f double
  223. String s char*
  224. String S str*
  225. Optional modifier * marks all further parameters as optional
  226. Autoconvert modifier . requires auto-conversion for the next parameter
  227. 1.2.3. Getting Parameters
  228. Each RPC function call can contain parameters. Parameters have no name,
  229. their meaning is determined by their position in the parameter set.
  230. Note
  231. You can pass all parameters to a function within a structure if you
  232. want to make them position independent. Then each parameter can be
  233. retrieved by its name regardless of its position.
  234. There are two functions in the RPC API that can be used to obtain
  235. function call parameters: scan and struct_scan.
  236. 1.2.3.1. scan
  237. Function scan can be used to retrieve parameters from the parameter
  238. set. The function accepts variable number of parameters. The first
  239. parameter is the formatting string that determines the type of the
  240. parameters to be retrieved. Each parameter is represented by exactly
  241. one parameter type character in the string. The variable part of
  242. parameters must contain as many pointers to C variables as there are
  243. formatting non-modifiers characters in the formatting string.
  244. Warning
  245. The function will crash if you fail to provide enough parameters.
  246. Besides characters representing parameter types, the formatting string
  247. can contain two special modifiers: "*" and ".". The modifiers do not
  248. have a correspondent in the variable part of the parameters.
  249. The meaning of "*" modifier is that any further parameters (defined by
  250. other type characters in the formatting string) are optional (they can
  251. be missing in the input and no rpc fault will automatically be
  252. generated).
  253. The '.' modifiers turns on type autoconversion for the next parameter.
  254. This means that if the type of the next parameter differs from the type
  255. specified in the formatting string, the parameter will be automatically
  256. converted to the formatting string type (if possible) and if the
  257. automatic conversion succeeds, no fault will be generated.
  258. The function returns the number of parameters read on success (a number
  259. greater or equal 0) and - (minus) the number of parameters read on
  260. error (for example for an error after reading 2 parameters it will
  261. return -2). When a failure occurs (incorrect parameter type or no more
  262. parameters in the parameter set) the function will return a negative
  263. number (- number of parameters read so far) and it will also
  264. automatically change the reply that will be sent to the caller to
  265. indicate that a failure has occurred on the server (unless the "*" is
  266. used and the error is lack of more parameters).
  267. The prototype of the function is:
  268. int scan((void* ctx, char* fmt, ...)
  269. It is possible to either call the function once to scan all the
  270. parameters:
  271. rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
  272. Or you can call the same function several times and it will continue
  273. where it left off previously:
  274. rpc->scan(ctx, "s", &string_val);
  275. rpc->scan(ctx, "d", &int_val);
  276. rpc->scan(ctx, "f", &double_val);
  277. 1.2.3.2. struct_scan
  278. Function struct_scan can be used to retrieve named attributes from a
  279. parameter of type structure.
  280. Note
  281. This function is obsolete and not implemented by all the rpc transports
  282. (e.g.: ctl / binrpc). Consider using the normal scan instead.
  283. When retrieving a structure parameter from the parameter set:
  284. rpc->scan(ctx, "{", &handle);
  285. The corresponding variable (named handle in the example above) will
  286. contain the index of the structure parameter within the parameter set,
  287. but the index cannot be used to retrieve the contents of the structure.
  288. To retrieve the contents of the structure you can use function
  289. struct_scan. The function gets the handle as the first parameter:
  290. rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
  291. The second parameter is the formatting string followed by pairs of
  292. parameters. First parameter in each pair is the name of the attribute
  293. to retrieve (string) and the second parameter in each pair is the
  294. pointer to the variable to store the value of the parameter. The
  295. function returns the number of parameters (name value pairs) read on
  296. success and - number of parameters read so far on an error (just like
  297. the scan function). The function also indicates an error if a requested
  298. attribute is missing in the structure.
  299. 1.2.3.3. Retrieving Parameters Example
  300. Example 3. Retrieving Parameters
  301. static void rpc_delete_contact(rpc_t* rpc, void* ctx)
  302. {
  303. str aor, contact;
  304. char* table;
  305. void *handle;
  306. int expires;
  307. double q;
  308. if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
  309. /* Reply is set automatically by scan upon failure,
  310. * no need to do anything here
  311. */
  312. return;
  313. }
  314. if (rpc->struct_scan(handle, "Sdf", "Contact", &contact,
  315. "Expires", &expires,
  316. "Q", &q ) < 0) {
  317. /* Reply is set automatically by struct_scan upon failure,
  318. * no need to do anything here
  319. */
  320. return;
  321. }
  322. /* Process retrieved parameters here */
  323. }
  324. /* variable number of parameters:
  325. echo back all the parameters, string type required */
  326. static void core_prints(rpc_t* rpc, void* c)
  327. {
  328. char* string = 0;
  329. while((rpc->scan(c, "*s", &string)>0))
  330. rpc->add(c, "s", string);
  331. }
  332. /* variable number of parameters and auto conversion:
  333. echo back all the parameters, works with any type (everything is
  334. internally converted to string, notice the '.' modifier) */
  335. static void core_echo(rpc_t* rpc, void* c)
  336. {
  337. char* string = 0;
  338. while((rpc->scan(c, "*.s", &string)>0))
  339. rpc->add(c, "s", string);
  340. }
  341. 1.2.4. Building Reply
  342. The RPC API contains several functions that can be used to modify
  343. and/or send a reply. The functions use formatting strings and parameter
  344. lists just like functions described in Section 1.2.3, "Getting
  345. Parameters".
  346. Each RPC function call must return a reply. The reply can be either a
  347. failure reply or success reply. Failure replies contain only the status
  348. code and reason phrase. Success replies can have arbitrary amount of
  349. data attached to them. Status codes 3xx, 4xx, 5xx, and 6xx indicate
  350. failures. Status code 2xx indicates success.
  351. The default reply is 200 OK with no data attached to it. This is what
  352. will be returned by the RPC transport module if you do not call any of
  353. the reply-related functions described in this section.
  354. Example 4. Sending default reply
  355. static void rpc_dummy(rpc_t* rpc, void *ctx)
  356. {
  357. /* 200 OK with no data will be returned */
  358. }
  359. 1.2.4.1. fault
  360. You can use fault function to indicate that an error has occurred on
  361. the server to the caller. The function accepts two parameters. The
  362. first parameter is the status code and the second parameter is the
  363. reason phrase.
  364. static void rpc_my_function(rpc_t* rpc, void *ctx)
  365. {
  366. rpc->fault(ctx, 600, "Not Yet Implemented");
  367. }
  368. If your function first creates some result using add, or printf
  369. functions then all the data will be lost once you call fault function.
  370. Failure replies must not contain any data:
  371. static void rpc_my_function(rpc_t* rpc, void *ctx)
  372. {
  373. rpc->add(ctx, "s", "result1");
  374. rpc->add(ctx, "d", variable);
  375. /* Reply created by previous functions will be
  376. * deleted and a failure reply 600 Not Yet Implemented
  377. * will be created instead
  378. */
  379. rpc->fault(ctx, 600, "Not Yet Implemented");
  380. /* You can also add data here, but that will have no
  381. * effect
  382. */
  383. rpc->add(ctx, "s", "result2");
  384. }
  385. Similarly you can also call add or printf functions after calling
  386. fault, in this case they will have no effect:
  387. static void rpc_my_function(rpc_t* rpc, void *ctx)
  388. {
  389. rpc->fault(ctx, 600, "Not Yet Implemented");
  390. /* You can also add data here, but that will have no
  391. * effect and only 600 Not Yet Implemented will be returned
  392. */
  393. rpc->add(ctx, "s", "result2");
  394. }
  395. 1.2.4.2. send
  396. RPC functions can use function send to explicitly send the reply. Each
  397. RPC function call generates exactly one reply. No reply will be sent
  398. after the function finishes if it already sent the reply using send
  399. function explicitly. This function is especially useful if the RPC
  400. function needs to perform some (potentially destructive) actions after
  401. the reply has been sent.
  402. Example 5. Kill the server
  403. static void core_kill(rpc_t* rpc, void *ctx)
  404. {
  405. int sig_no;
  406. if (rpc->scan(ctx, "d", &sig_no) < 0) return;
  407. rpc->send(ctx, ); /* First send a reply */
  408. kill(0, sig_no); /* Then kill the server */
  409. }
  410. 1.2.4.3. add
  411. Function add can be used to add arbitrary data to the result set. Its
  412. parameters and use are analogical to scan function described in
  413. Section 1.2.3.1, "scan". The first parameter of the function is the
  414. formatting string that determines the types of additional parameters:
  415. static void rpc_func(rpc_t* rpc, void *ctx)
  416. {
  417. str str_result;
  418. int int_result;
  419. void *handle;
  420. double float_result;
  421. if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) <
  422. 0) return;
  423. }
  424. Naturally you can call this function several times, adding only one
  425. piece of data at a time. The function returns 0 on success and -1 on an
  426. error. In case of an error the reply is set automatically with
  427. corresponding error code and reason phrase.
  428. The last character in the formatting string of the function above
  429. indicates that the last data to be added will be a structure. This
  430. deserves some clarification. In this case, the function will create an
  431. empty structure and the handle to the newly created structure will be
  432. stored in handle variable (hence the last parameter is pointer to an
  433. integer). In this particular example parameters str_result, int_result,
  434. and float_result will be used for reading while parameter handle will
  435. be used for writing by the function.
  436. You can set the attributes of the newly created structure using
  437. struct_add function described in Section 1.2.4.5, "struct_add".
  438. 1.2.4.4. rpl_printf
  439. rpl_printf is a convenience function. The function adds data of type
  440. string to the result set. The first parameter of the function is again
  441. a formatting string, but this time it is standard printf-like
  442. formatting string:
  443. if (rpc->rpl_printf(ctx, "Unable to delete %d entries from table %s", num_entrie
  444. s, table_name) < 0) return;
  445. The return value of the function is the same as of add function.
  446. 1.2.4.5. struct_add
  447. Function struct_add can be used to add attributes to a structure
  448. (created previously by add function). The first parameter of the
  449. function is handle obtained through add function, the second parameters
  450. is formatting string that determines the types of attributes to be
  451. added. There must be two parameters per each character in the
  452. formatting string, the first one is the name of the attribute, the
  453. second parameter is the value of the attribute. If a parameter with
  454. such a name already exist in the structure then it will be overwritten
  455. with the new value.
  456. static void rpc_func(rpc_t* rpc, void *ctx)
  457. {
  458. void *handle;
  459. /* Create empty structure and obtain its handle */
  460. if (rpc->add(ctx, "{", &handle) < 0) return;
  461. /* Fill-in the structure */
  462. if (rpc->struct_add(handle, "sd", "attr1", str_val,
  463. "attr2", int_val ) < 0)
  464. return;
  465. }
  466. The function returns -1 on an error (and sets the status code and
  467. reason phrase of the reply accordingly) and 0 on success.
  468. 1.2.5. Real World Example
  469. The following example illustrates the use of most of the functions from
  470. the API together:
  471. Example 6. Real World Example RPC Function
  472. static void rpc_register(rpc_t* rpc, void *ctx)
  473. {
  474. char* domain;
  475. str aor;
  476. contact_t contact, new_contact;
  477. void *handle;
  478. /* Extract the domain, address of record from the request */
  479. if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
  480. /* Extract the structure describing the contact to be processed */
  481. if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
  482. "Expires", &contact.expires,
  483. "Q", &contact.q ) < 0)
  484. return;
  485. /* Process the contact, new_contact will contain updated value after pro
  486. cessing */
  487. if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
  488. /* Processing failed, indicate the failure to the caller */
  489. rpc->fault(ctx, 500, "Error While Processing Contact");
  490. return;
  491. }
  492. /* Return the domain and the address of record */
  493. rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
  494. /* And also add the new values for contact, q, and expires parameters */
  495. rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
  496. "Expires", &new_contact.expires,
  497. "Q", &new_contact.q );
  498. }
  499. 1.3. Client Examples
  500. * sercmd (C application that uses the binrpc interface implemented by
  501. the ctl module).
  502. * ser_ctl (python application that uses the XML-RPC interface
  503. implemented by the xmlrpc module).
  504. * serweb (php application that can use the XML-RPC interface to call
  505. ser functions).
  506. 1.4. Implementing New Transports
  507. To be done.
  508. Examples:
  509. * ctl
  510. * xmlrpc
  511. 1.5. Examples using xmlrpc
  512. See the xmlrpc module documentation: modules/xmlrpc/README.