doxygen: fix a bunch of errors in parser, db_mysql and xmlrpc modules
[sip-router] / modules / xmlrpc / xmlrpc.c
1 /*
2  * Copyright (C) 2005 iptelorg GmbH
3  * Written by Jan Janak <jan@iptel.org>
4  *
5  * This file is part of SER, a free SIP server.
6  *
7  * SER is free software; you can redistribute it and/or modify it under the
8  * terms of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option) any later
10  * version
11  *
12  * For a license to use the SER software under conditions other than those
13  * described here, or to purchase support for this software, please contact
14  * iptel.org by e-mail at the following addresses: info@iptel.org
15  *
16  * SER is distributed in the hope that it will be useful, but WITHOUT ANY
17  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc., 59
23  * Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */
25
26 #define _XOPEN_SOURCE 4           /* strptime */
27 #define _XOPEN_SOURCE_EXTENDED 1  /* solaris */
28 #define _SVID_SOURCE 1            /* timegm */
29
30 #include <strings.h>
31 #include <time.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdarg.h>
37 #include <sys/types.h>
38 #include <signal.h>
39 #include <libxml/xmlreader.h>
40 #include "../../str.h"
41 #include "../../sr_module.h"
42 #include "../../error.h"
43 #include "../../usr_avp.h"
44 #include "../../mem/mem.h"
45 #include "../../parser/parse_uri.h"
46 #include "../../parser/msg_parser.h"
47 #include "../../ut.h"
48 #include "../../dset.h"
49 #include "../../str.h"
50 #include "../../dprint.h"
51 #include "../../data_lump.h"
52 #include "../../data_lump_rpl.h"
53 #include "../../msg_translator.h"
54 #include "../../select.h"
55 #include "../../receive.h" /* needed by process_rpc / receive_msg() */
56 #include "../../modules/sl/sl.h"
57 #include "../../nonsip_hooks.h"
58 #include "../../action.h" /* run_actions */
59 #include "../../script_cb.h" /* exec_*_script_cb */
60 #include "../../route.h" /* route_get */
61 #include "../../sip_msg_clone.h" /* sip_msg_shm_clone */
62 #include "http.h"
63
64 /** @addtogroup xmlrpc
65  * @ingroup modules
66  * @{
67  *
68  * <h1>Overview of Operation</h1> 
69  * This module provides XML-RPC based interface to management functions in
70  * SER. You can send XML-RPC requests to SER when the module is loaded and
71  * configured and it will send XML-RPC replies back.  XML-RPC requests are
72  * encoded as XML documents in the body of HTTP requests. Due to similarity
73  * between HTTP and SIP SER can easily parse HTTP requests and extract the XML
74  * document from their body.
75  *
76  * When you load this module into SER, it will register a callback function
77  * that will be called whenever the SER core receives a request with method it
78  * does not understand. The main callback function is process_xmlrpc(). The
79  * function first verifies if the protocol identifier inside the request is
80  * HTTP and whether the request method is either GET or POST. If both
81  * conditions are met then it will signal to the SER core that it is
82  * processing the request, otherwise it will reject the request and the SER
83  * core will pass the requests to other callbacks if they exist.
84  *
85  * As the next step the request will be converted from HTTP request to a SIP
86  * request to ensure that it can be processed by SER and its modules. The
87  * conversion will modify the URI in the Request-URI of the request, the new
88  * URI will be a SIP URI. In addition to that it will add a fake Via header
89  * field and copy all remaining header fields from the original HTTP request.
90  * The conversion is implemented in http_xmlrpc2sip() function.
91  * 
92  * After the conversion the module will execute the route statement whose
93  * number is configured in "route" module parameter. That route stament may
94  * perform additional security checks and when it ensures that the client is
95  * authorized to execute management functions then it will call dispatch_rpc()
96  * module function provided by this module.
97  *
98  * dispatch_rpc() function extracts the XML-RPC document from the body of the
99  * request to determine the name of the method to be called and then it
100  * searches through the list of all management functions to find a function
101  * with matching name. If such a function is found then dispatch_rpc() will
102  * pass control to the function to handle the request. dispatch_rpc() will
103  * send a reply back to the client when the management function terminates, if
104  * the function did not do that explicitly.
105  * 
106  * <h2>Memory Management</h2> 
107  * The module provides implementation for all the functions required by the
108  * management interface in SER, such as rpc->printf, rpc->add, rpc->struct_add
109  * and so on. Whenever the management function calls one of the functions then
110  * corresponding function in this module will be called to handle the request.
111  *
112  * The implementation functions build the reply, that will be sent to the
113  * client, as they execute and they need to allocate memory to do that. That
114  * memory must be freed again after the reply has been sent to the client. To
115  * remember all the memory regions allocated during the execution of the
116  * management function all functions within this module record all allocated
117  * memory in the global variable called waste_bin. dispatch_rpc() functions
118  * executes function collect_garbage() after the reply has been sent to the
119  * client to free all memory that was allocated from the management function.
120  * that was executed.
121  *
122  * <h2>Request Context</h2> 
123  * Before the module calls a management function it prepares a structure
124  * called context. The context is defined in structure rpc_ctx and it is
125  * passed as one of parameter to the management function being called. The
126  * context contains all the data that is needed during the execution of the
127  * management function, such as the pointer to the request being processed, a
128  * pointer to the reply being built, and so on.
129  *
130  * Another parameter to the management function being called is a structure
131  * that contains pointers to all implementation functions. This structure is
132  * of type rpc_t, this module keeps one global variable of that type called
133  * func_param and a pointer to that variable is passed to all management
134  * functions. The global variable is initialized in mod_init().
135  */
136
137 /** @file 
138  *
139  * This is the main file of XMLRPC SER module which contains all the functions
140  * related to XML-RPC processing, as well as the module interface.
141  */
142
143 /*
144  * FIXME: Decouple code and reason phrase from reply body
145  *        Escape special characters in strings
146  */
147
148 MODULE_VERSION
149
150 int snprintf(char *str, size_t size, const char *format, ...);
151 int vsnprintf(char *str, size_t size, const char *format, va_list ap);
152
153 static int process_xmlrpc(sip_msg_t* msg);
154 static int dispatch_rpc(sip_msg_t* msg, char* s1, char* s2);
155 static int xmlrpc_reply(sip_msg_t* msg, char* code, char* reason);
156 static int mod_init(void);
157
158 /* first line (w/o the version) of the sip msg created from the http xmlrpc */
159 #define XMLRPC_URI "sip:127.0.0.1:9"
160 #define XMLRPC_URI_LEN (sizeof(XMLRPC_URI)-1)
161
162 #define HTTP_GET                "GET"
163 #define HTTP_GET_LEN    (sizeof(HTTP_GET)-1)
164 #define HTTP_POST               "POST"
165 #define HTTP_POST_LEN   (sizeof(HTTP_POST)-1)
166 #define N_HTTP_GET              0x00746567U
167 #define N_HTTP_POST             0x74736f70U
168
169 #define LF "\n"
170
171 /** The beginning of XML document indicating an error.
172  *
173  * This is the beginning of the XML document that will be sent back to the
174  * client when the server encountered an error.  It will be immediately
175  * followed by a reason phrase.
176  */
177 #define FAULT_PREFIX         \
178 "<?xml version=\"1.0\"?>" LF \
179 "<methodResponse>" LF        \
180 "<fault>" LF                 \
181 "<value>" LF                 \
182 "<struct>" LF                \
183 "<member>" LF                \
184 "<name>faultCode</name>" LF  \
185 "<value><int>"
186
187
188 /** The text of XML document indicating error that goes between reason code
189  * and reason phrase.
190  */
191 #define FAULT_BODY            \
192 "</int></value>" LF           \
193 "</member>" LF                \
194 "<member>" LF                 \
195 "<name>faultString</name>" LF \
196 "<value><string>"
197
198
199 /** The end of XML document that indicates an error.  
200  *
201  * This is the closing part of the XML-RPC document that indicates an error on
202  * the server.
203  */
204 #define FAULT_SUFFIX   \
205 "</string></value>" LF \
206 "</member>" LF         \
207 "</struct>" LF         \
208 "</value>" LF          \
209 "</fault>" LF          \
210 "</methodResponse>"
211
212
213 /** The beginning of XML-RPC reply sent to the client.
214  */
215 #define SUCCESS_PREFIX       \
216 "<?xml version=\"1.0\"?>" LF \
217 "<methodResponse>" LF        \
218 "<params>" LF                \
219 "<param>" LF                 \
220 "<value>"
221
222
223 /** The closing part of XML-RPC reply document sent to
224  * the client.
225  */
226 #define SUCCESS_SUFFIX \
227 "</value>" LF          \
228 "</param>" LF          \
229 "</params>" LF         \
230 "</methodResponse>"
231
232 static str fault_prefix   = STR_STATIC_INIT(FAULT_PREFIX);
233 static str fault_body     = STR_STATIC_INIT(FAULT_BODY);
234 static str fault_suffix   = STR_STATIC_INIT(FAULT_SUFFIX);
235 static str success_prefix = STR_STATIC_INIT(SUCCESS_PREFIX);
236 static str success_suffix = STR_STATIC_INIT(SUCCESS_SUFFIX);
237 static str lf             = STR_STATIC_INIT(LF);
238 static str int_prefix     = STR_STATIC_INIT("<int>");
239 static str int_suffix     = STR_STATIC_INIT("</int>");
240 static str double_prefix  = STR_STATIC_INIT("<double>");
241 static str double_suffix  = STR_STATIC_INIT("</double>");
242 static str string_prefix  = STR_STATIC_INIT("<string>");
243 static str string_suffix  = STR_STATIC_INIT("</string>");
244 static str date_prefix    = STR_STATIC_INIT("<dateTime.iso8601>");
245 static str date_suffix    = STR_STATIC_INIT("</dateTime.iso8601>");
246 static str bool_prefix    = STR_STATIC_INIT("<boolean>");
247 static str bool_suffix    = STR_STATIC_INIT("</boolean>");
248 static str value_prefix   = STR_STATIC_INIT("<value>");
249 static str value_suffix   = STR_STATIC_INIT("</value>");
250 static str array_prefix   = STR_STATIC_INIT("<array><data>" LF);
251 static str array_suffix   = STR_STATIC_INIT("</data></array>");
252 static str struct_prefix  = STR_STATIC_INIT("<struct>");
253 static str struct_suffix  = STR_STATIC_INIT("</struct>");
254 static str member_prefix  = STR_STATIC_INIT("<member>");
255 static str member_suffix  = STR_STATIC_INIT("</member>");
256 static str name_prefix    = STR_STATIC_INIT("<name>");
257 static str name_suffix    = STR_STATIC_INIT("</name>");
258
259
260 /** Garbage collection data structure.
261  *
262  * This is the data structure used by the garbage collector in this module.
263  * When the xmlrpc SER module identifies the management function to be called,
264  * it calls corresponding function in SER. The function being called adds data
265  * to the reply, that will be later sent to the client, as it executes. This
266  * module needs to allocate memory for such data and the memory will be
267  * re-claimed after the reply was sent out.  All the memory allocated this way
268  * is recorded in this data structure so that it can be identified and
269  * re-claimed later (when the reply is being sent out).
270  * 
271  */
272 static struct garbage {
273         enum {
274                 JUNK_XMLCHAR,
275                 JUNK_RPCSTRUCT,    /**< This type indicates that the memory block was
276                                                    * allocated for the RPC structure data type, this
277                                                    * type needs to be freed differently as it may
278                                                    * contain more allocated memory blocks
279                                                    */
280                 JUNK_PKGCHAR      /** This type indicates a pkg_malloc'ed string */
281         } type;               /**< Type of the memory block */
282         void* ptr;            /**< Pointer to the memory block obtained from
283                                                          pkg_malloc */
284         struct garbage* next; /**< The linked list of all allocated memory
285                                                          blocks */
286 } *waste_bin = 0;
287
288
289 /** Representation of the XML-RPC reply being constructed.
290  *  
291  * This data structure describes the XML-RPC reply that is being constructed
292  * and will be sent to the client.
293  */
294 struct xmlrpc_reply {
295         int code;     /**< Reply code which indicates the type of the reply */
296         char* reason; /**< Reason phrase text which provides human-readable
297                                    * description that augments the reply code */
298         str body;     /**< The XML-RPC document body built so far */
299         str buf;      /**< The memory buffer allocated for the reply, this is
300                                    * where the body attribute of the structure points to
301                                    */
302 };
303
304
305 /** The context of the XML-RPC request being processed.
306  * 
307  * This is the data structure that contains all data related to the XML-RPC
308  * request being processed, such as the reply code and reason, data to be sent
309  * to the client in the reply, and so on.
310  *
311  * There is always one context per XML-RPC request.
312  */
313 typedef struct rpc_ctx {
314         sip_msg_t* msg;        /**< The SIP/HTTP through which the RPC has been
315                                                           received */
316         struct xmlrpc_reply reply;  /**< XML-RPC reply to be sent to the client */
317         struct rpc_struct* structs; /**< Structures to be added to the reply */
318         int msg_shm_block_size; /**< non-zero for delayed reply contexts with
319                                                                 shm cloned msgs */
320         int reply_sent;             /**< The flag is set after a reply is sent,
321                                                                    this prevents a single reply being sent
322                                                                    twice */
323         char* method;               /**< Name of the management function to be
324                                                                    called */
325         unsigned int flags;         /**< Various flags, such as return value
326                                                                    type */
327         xmlDocPtr doc;              /**< Pointer to the XML-RPC request
328                                                                    document */
329         xmlNodePtr act_param;       /**< Pointer to the parameter being processed
330                                                                    in the XML-RPC request document */
331 } rpc_ctx_t;
332
333
334 /* extra rpc_ctx_t flags */
335 /* first 8 bits reserved for rpc flags (e.g. RET_ARRAY) */
336 #define XMLRPC_DELAYED_CTX_F    256
337 #define XMLRPC_DELAYED_REPLY_F  512
338
339 /** The structure represents a XML-RPC document structure.
340  *
341  * This is the data structure that represents XML-RPC structures that are sent
342  * to the client in the XML-RPC reply documents. A XML-RPC document structure
343  * is compound consting of name-value pairs.
344  * @sa http://www.xml-rpc.com
345  */
346 struct rpc_struct {
347         xmlNodePtr struct_in;           /**< Pointer to the structure parameter */
348         struct xmlrpc_reply struct_out; /**< Structure to be sent in reply */
349         struct xmlrpc_reply* reply;     /**< Print errors here */
350         int n;                          /**< Number of structure members
351                                                                            created */
352         xmlDocPtr doc;                  /**< XML-RPC document */
353         int offset;                     /**< Offset in the reply where the
354                                                                            structure should be printed */
355         struct rpc_struct* next;
356 };
357
358
359 /** The context of the XML-RPC request being processed.
360  *
361  * This is a global variable that records the context of the XML-RPC request
362  * being currently processed.  
363  * @sa rpc_ctx
364  */
365 static rpc_ctx_t ctx;
366
367 static void close_doc(rpc_ctx_t* ctx);
368 static void set_fault(struct xmlrpc_reply* reply, int code, char* fmt, ...);
369 static int fixup_xmlrpc_reply(void** param, int param_no);
370
371 /** Pointers to the functions that implement the RPC interface
372  * of xmlrpc SER module
373  */
374 static rpc_t func_param;
375
376 /** Enable/disable additional introspection methods.  If set to 1 then the
377  * functions defined in http://scripts.incutio.com/xmlrpc/introspection.html
378  * will be available on the server. If set to 0 then the functions will be
379  * disabled.
380  */
381 static char* xmlrpc_route=0; /* default is the main route */
382
383
384 /** Reference to the sl (stateless replies) module of SER The sl module of SER
385  * is needed so that the xmlrpc SER module can send replies back to clients
386  */
387 sl_api_t slb;
388
389 static int xmlrpc_route_no=DEFAULT_RT;
390 /* if set, try autoconverting to the requested type if possible
391   (e.g. convert 1 to "1" if string is requested) */
392 static int autoconvert=0;
393 /* in replies, escape CR to &#xD (according to the xml specs) */
394 static int escape_cr=1; /* default on */
395 /* convert double LF to CR LF (when on, LFLF becomes an escape for CRLF, needed
396  with some xmlrpc clients that are not escaping CR to &#xD; )*/
397 static int lflf2crlf=0; /* default off */
398 /* do not register for non-sip requests */
399 static int xmlrpc_mode = 0;
400
401 static char* xmlrpc_url_match = NULL;
402 static regex_t xmlrpc_url_match_regexp;
403 static char* xmlrpc_url_skip = NULL;
404 static regex_t xmlrpc_url_skip_regexp;
405
406
407 /*
408  * Exported functions
409  */
410 static cmd_export_t cmds[] = {
411         {"dispatch_rpc", dispatch_rpc, 0, 0,                  REQUEST_ROUTE},
412         {"xmlrpc_reply", xmlrpc_reply, 2, fixup_xmlrpc_reply, REQUEST_ROUTE},
413         {0, 0, 0, 0, 0}
414 };
415
416
417 /*
418  * Exported parameters
419  */
420 static param_export_t params[] = {
421         {"route",             PARAM_STRING, &xmlrpc_route},
422         {"autoconversion",    PARAM_INT,    &autoconvert},
423         {"escape_cr",         PARAM_INT,    &escape_cr},
424         {"double_lf_to_crlf", PARAM_INT,    &lflf2crlf},
425         {"mode",              PARAM_INT,    &xmlrpc_mode},
426         {"url_match",         PARAM_STRING, &xmlrpc_url_match},
427         {"url_skip",          PARAM_STRING, &xmlrpc_url_skip},
428         {0, 0, 0}
429 };
430
431
432 struct module_exports exports = {
433         "xmlrpc",
434         cmds,           /* Exported commands */
435         0,              /* Exported RPC methods */
436         params,         /* Exported parameters */
437         mod_init,       /* module initialization function */
438         0,              /* response function*/
439         0,              /* destroy function */
440         0,              /* oncancel function */
441         0               /* per-child init function */
442 };
443
444 /* XML-RPC reply helper functions */
445
446 #define ESC_LT "&lt;"
447 #define ESC_AMP "&amp;"
448 #define ESC_CR  "&#xD;"
449
450
451 static void clean_context(rpc_ctx_t* ctx);
452
453
454 /** Adds arbitrary text to the XML-RPC reply being constructed, special
455  * characters < and & will be escaped.
456  *
457  * This function adds arbitrary text to the body of the XML-RPC reply being
458  * constructed. Note well that the function does not check whether the XML
459  * document being constructed is well-formed or valid. Use with care.
460  *
461  * @param reply Pointer to the structure representing the XML-RPC reply
462  *              being constructed.
463  * @param text The text to be appended to the XML-RPC reply.
464  * @return -1 on error, 0 if the text was added successfuly.
465  * @sa add_xmlrpc_reply()
466  */
467 static int add_xmlrpc_reply_esc(struct xmlrpc_reply* reply, str* text)
468 {
469     char* p;
470     int i;
471
472     for(i = 0; i < text->len; i++) {
473                 /* 10 must be bigger than size of longest escape sequence */
474                 if (reply->body.len >= reply->buf.len - 10) { 
475                         p = pkg_malloc(reply->buf.len + 1024);
476                         if (!p) {
477                                 set_fault(reply, 500, 
478                                                   "Internal Server Error (No memory left)");
479                                 ERR("No memory left: %d\n", reply->body.len + 1024);
480                                 return -1;
481                         }
482                         memcpy(p, reply->body.s, reply->body.len);
483                         pkg_free(reply->buf.s);
484                         reply->buf.s = p;
485                         reply->buf.len += 1024;
486                         reply->body.s = p;
487                 }
488                 
489                 switch(text->s[i]) {
490                 case '<':
491                         memcpy(reply->body.s + reply->body.len, ESC_LT, 
492                                    sizeof(ESC_LT) - 1);
493                         reply->body.len += sizeof(ESC_LT) - 1;
494                         break;
495                         
496                 case '&':
497                         memcpy(reply->body.s + reply->body.len, ESC_AMP, 
498                                    sizeof(ESC_AMP) - 1);
499                         reply->body.len += sizeof(ESC_AMP) - 1;
500                         break;
501                         
502                 case '\r':
503                         if (likely(escape_cr)){
504                                 memcpy(reply->body.s + reply->body.len, ESC_CR,
505                                         sizeof(ESC_CR) - 1);
506                                 reply->body.len += sizeof(ESC_CR) - 1;
507                                 break;
508                         }
509                         /* no break */
510                 default:
511                         reply->body.s[reply->body.len] = text->s[i];
512                         reply->body.len++;
513                         break;
514                 }
515     }
516     return 0;
517 }
518
519 /** Add arbitrary text to the XML-RPC reply being constructed, no escaping
520  * done.
521  * 
522  * This is a more efficient version of add_xmlrpc_reply_esc(), the function
523  * appends arbitrary text to the end of the XML-RPC reply being constructed,
524  * but the text must not contain any characters that need to be escaped in
525  * XML, such as < and & (or the characters must be escaped already).
526  *
527  * @param reply Pointer to the structure representing the XML-RPC reply
528  *              being constructed.
529  * @param text The text to be appended to the XML-RPC reply.
530  * @return -1 on error, 0 if the text was added successfuly.
531  * @sa add_xmlrpc_reply_esc()
532  */
533 static int add_xmlrpc_reply(struct xmlrpc_reply* reply, str* text)
534 {
535         char* p;
536         if (text->len > (reply->buf.len - reply->body.len)) {
537                 p = pkg_malloc(reply->buf.len + text->len + 1024);
538                 if (!p) {
539                         set_fault(reply, 500, "Internal Server Error (No memory left)");
540                         ERR("No memory left: %d\n", reply->buf.len + text->len + 1024);
541                         return -1;
542                 }
543                 memcpy(p, reply->body.s, reply->body.len);
544                 pkg_free(reply->buf.s);
545                 reply->buf.s = p;
546                 reply->buf.len += text->len + 1024;
547                 reply->body.s = p;
548         }
549         memcpy(reply->body.s + reply->body.len, text->s, text->len);
550         reply->body.len += text->len;
551         return 0;
552 }
553
554
555 /** Adds arbitrary text to the XML-RPC reply being constructed, the text will
556  * be inserted at a specified offset within the XML-RPC reply.
557  *
558  * This function inserts arbitrary text in the XML-RPC reply that is being
559  * constructed, unlike add_xmlrp_reply(), this function will not append the
560  * text at the end of the reply, but it will insert the text in the middle of
561  * the reply at the position provided to the function in "offset"
562  * parameter. The function does not escape special characters and thus the
563  * text must not contain such characters (or the must be escaped already).
564  *
565  * @param reply The XML-RPC reply structure representing the reply being
566  *              constructed.
567  * @param offset The position of the first character where the text should be
568  *               inserted. 
569  * @param text The text to be inserted.
570  * @return 0 of the text was inserted successfuly, a negative number on error.
571  */
572 static int add_xmlrpc_reply_offset(struct xmlrpc_reply* reply, unsigned int offset, str* text)
573 {
574         char* p;
575         if (text->len > (reply->buf.len - reply->body.len)) {
576                 p = pkg_malloc(reply->buf.len + text->len + 1024);
577                 if (!p) {
578                         set_fault(reply, 500, "Internal Server Error (No memory left)");
579                         ERR("No memory left: %d\n", reply->buf.len + text->len + 1024);
580                         return -1;
581                 }
582                 memcpy(p, reply->body.s, reply->body.len);
583                 pkg_free(reply->buf.s);
584                 reply->buf.s = p;
585                 reply->buf.len += text->len + 1024;
586                 reply->body.s = p;
587         }
588         memmove(reply->body.s + offset + text->len, reply->body.s + offset, 
589                         reply->body.len - offset);
590         memcpy(reply->body.s + offset, text->s, text->len);
591         reply->body.len += text->len;
592         return 0;
593 }
594
595
596 /** Returns the current lenght of the XML-RPC reply body.
597  *
598  * @param reply The XML-RPC reply being constructed
599  * @return Number of bytes of the XML-RPC reply body.
600  */
601 static unsigned int get_reply_len(struct xmlrpc_reply* reply)
602 {
603         return reply->body.len;
604 }
605
606
607 /* Resets XMLRPC reply body.
608  *
609  * This function discards everything that has been written so far and starts
610  * constructing the XML-RPC reply body from the beginning.
611  *
612  * @param reply The XML-RPC reply being constructed.
613  */
614 static void reset_xmlrpc_reply(struct xmlrpc_reply* reply)
615 {
616         reply->body.len = 0;
617 }
618
619 /** Initialize XML-RPC reply data structure.
620  *
621  * This function initializes the data structure that contains all data related
622  * to the XML-RPC reply being created. The function must be called before any
623  * other function that adds data to the reply.
624  * @param reply XML-RPC reply structure to be initialized.
625  * @return 0 on success, a negative number on error.
626  */
627 static int init_xmlrpc_reply(struct xmlrpc_reply* reply)
628 {
629         reply->code = 200;
630         reply->reason = "OK";
631         reply->buf.s = pkg_malloc(1024);
632         if (!reply->buf.s) {
633                 set_fault(reply, 500, "Internal Server Error (No memory left)");
634                 ERR("No memory left\n");
635                 return -1;
636         }
637         reply->buf.len = 1024;
638         reply->body.s = reply->buf.s;
639         reply->body.len = 0;
640         return 0;
641 }
642
643 /** Clear the XML-RPC reply code and sets it back to a success reply.
644  *
645  * @param reply XML-RPC reply structure to be cleared.
646  */
647 static void clear_xmlrpc_reply(struct xmlrpc_reply* reply)
648 {
649         reply->code = 200;
650         reply->reason = "OK";
651 }
652
653
654 /* if this a delayed reply context, and it's never been use before, fix it */
655 static int fix_delayed_reply_ctx(rpc_ctx_t* ctx)
656 {
657         if  ((ctx->flags & XMLRPC_DELAYED_CTX_F) && (ctx->reply.buf.s==0)){
658                 if (init_xmlrpc_reply(&ctx->reply) <0) return -1;
659                 add_xmlrpc_reply(&ctx->reply, &success_prefix);
660                 if (ctx->flags & RET_ARRAY)
661                         return add_xmlrpc_reply(&ctx->reply, &array_prefix);
662         }
663         return 0;
664 }
665
666
667
668 /** Free all memory used by the XML-RPC reply structure. */
669 static void clean_xmlrpc_reply(struct xmlrpc_reply* reply)
670 {
671         if (reply->buf.s) pkg_free(reply->buf.s);
672 }
673
674 /** Create XML-RPC reply that indicates an error to the caller.
675  *
676  * This function is used to build the XML-RPC reply body that indicates that
677  * an error ocurred on the server. It is called when a management function in
678  * SER reports an error. The reply will contain the reason code and reason
679  * phrase text provided by the management function that indicated the error.
680  */
681 static int build_fault_reply(struct xmlrpc_reply* reply)
682 {
683         str reason_s, code_s;
684
685         reason_s.s = reply->reason;
686         reason_s.len = strlen(reply->reason);
687         code_s.s = int2str(reply->code, &code_s.len);
688         reset_xmlrpc_reply(reply);
689         if (add_xmlrpc_reply(reply, &fault_prefix) < 0) return -1;
690         if (add_xmlrpc_reply_esc(reply, &code_s) < 0) return -1;
691         if (add_xmlrpc_reply(reply, &fault_body) < 0) return -1;
692         if (add_xmlrpc_reply_esc(reply, &reason_s) < 0) return -1;
693         if (add_xmlrpc_reply(reply, &fault_suffix) < 0) return -1;
694         return 0;
695 }
696
697
698 /** Add a memory registion to the list of memory blocks that
699  * need to be re-claimed later.
700  *
701  * @param type The type of the memory block (ordinary text or structure).
702  * @param ptr A pointer to the memory block.
703  * @param reply The XML-RPC the memory block is associated with.
704  * @return 0 on success, a negative number on error.
705  * @sa collect_garbage()
706  */
707 static int add_garbage(int type, void* ptr, struct xmlrpc_reply* reply)
708 {
709         struct garbage* p;
710
711         p = (struct garbage*)pkg_malloc(sizeof(struct garbage));
712         if (!p) {
713                 set_fault(reply, 500, "Internal Server Error (No memory left)");
714                 ERR("Not enough memory\n");
715                 return -1;
716         }
717
718         p->type = type;
719         p->ptr = ptr;
720         p->next = waste_bin;
721         waste_bin = p;
722         return 0;
723 }
724
725 /** Re-claims all memory allocated in the process of building XML-RPC
726  * reply.
727  */
728 static void collect_garbage(void)
729 {
730         struct rpc_struct* s;
731         struct garbage* p;
732              /* Collect garbage */
733         while(waste_bin) {
734                 p = waste_bin;
735                 waste_bin = waste_bin->next;
736                 switch(p->type) {
737                 case JUNK_XMLCHAR:
738                         if (p->ptr) xmlFree(p->ptr);
739                         break;
740
741                 case JUNK_RPCSTRUCT:
742                         s = (struct rpc_struct*)p->ptr;
743                         if (s && s->struct_out.buf.s) pkg_free(s->struct_out.buf.s);
744                         if (s) pkg_free(s);
745                         break;
746
747                 case JUNK_PKGCHAR:
748                         if (p->ptr){
749                                 pkg_free(p->ptr);
750                                 p->ptr=0;
751                         }
752                         break;
753
754                 default:
755                         ERR("BUG: Unsupported junk type\n");
756                 }
757                 pkg_free(p);
758         }
759 }
760
761
762 /** Extract XML-RPC query from a SIP/HTTP message.
763  *
764  * @param doc A pointer to string descriptor that will be filled
765  *            with the pointer to the beginning of the XML-RPC
766  *            document and length of the document.
767  * @param msg A structure representing the SIP/HTTP message 
768  *            carrying the XML-RPC document in body.
769  */
770 static int get_rpc_document(str* doc, sip_msg_t* msg)
771 {
772         doc->s = get_body(msg);
773         if (!doc->s) {
774                 ERR("Error while extracting message body\n");
775                 return -1;
776         }
777         doc->len = strlen(doc->s);
778         return 0;
779 }
780
781
782 /** Send a reply to the client with given body.
783  *
784  * This function sends a 200 OK reply back to the client, the body of the
785  * reply will contain text provided to the function in "body" parameter.
786  *
787  * @param msg The request that generated the reply.
788  * @param body The text that will be put in the body of the reply.
789  */
790 static int send_reply(sip_msg_t* msg, str* body)
791 {
792         if (add_lump_rpl(msg, body->s, body->len, LUMP_RPL_BODY) < 0) {
793                 ERR("Error while adding reply lump\n");
794                 return -1;
795         }
796
797         if (slb.zreply(msg, 200, "OK") == -1) {
798                 ERR("Error while sending reply\n");
799                 return -1;
800         }
801
802         return 0;
803 }
804
805
806 static int print_structures(struct xmlrpc_reply* reply, 
807                                                         struct rpc_struct* st)
808 {
809         while(st) {
810                      /* Close the structure first */
811                 if (add_xmlrpc_reply(&st->struct_out, &struct_suffix) < 0) return -1;
812                 if (add_xmlrpc_reply_offset(reply, st->offset, 
813                                                                         &st->struct_out.body) < 0) return -1;
814                 st = st->next;
815         }
816         return 0;
817 }
818
819 /** Implementation of rpc_send function required by the management API in SER.
820  *
821  * This is the function that will be called whenever a management function in
822  * SER asks the management interface to send the reply to the client. The
823  * function will generate the XML-RPC document, put it in body of a SIP
824  * response and send the response to the client. The SIP/HTTP reply sent to
825  * the client will be always 200 OK, if an error ocurred on the server then it
826  * will be indicated in the XML document in body.
827  *
828  * @param ctx A pointer to the context structure of the XML-RPC request that
829  *            generated the reply.  
830  * @return 1 if the reply was already sent, 0 on success, a negative number on
831  *            error
832  */
833 static int rpc_send(rpc_ctx_t* ctx)
834 {
835         struct xmlrpc_reply* reply;
836
837         if (ctx->reply_sent) return 1;
838
839         reply = &ctx->reply;
840         if (reply->code >= 300) {
841                 if (build_fault_reply(reply) < 0) return -1;
842         } else {
843                 if (ctx->flags & RET_ARRAY && 
844                         add_xmlrpc_reply(reply, &array_suffix) < 0) return -1;
845                 if (ctx->structs && 
846                         print_structures(reply, ctx->structs) < 0) return -1;
847                 if (add_xmlrpc_reply(reply, &success_suffix) < 0) return -1;
848         }
849         if (send_reply(ctx->msg, &reply->body) < 0) return -1;
850         ctx->reply_sent = 1;
851         return 0;
852 }
853
854
855 #define REASON_BUF_LEN 1024
856
857 static void set_fault(struct xmlrpc_reply* reply, int code, char* fmt, ...)
858 {
859         static char buf[REASON_BUF_LEN];
860         va_list ap;
861
862         reply->code = code;
863         va_start(ap, fmt);
864         vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
865         va_end(ap);
866         reply->reason = buf;
867 }
868
869 /** Implementation of rpc_fault function required by the management API in 
870  * SER.
871  *
872  * This function will be called whenever a management function in SER
873  * indicates that an error ocurred while it was processing the request. The
874  * function takes the reply code and reason phrase as parameters, these will
875  * be put in the body of the reply.
876  *
877  * @param ctx A pointer to the context structure of the request being 
878  *            processed.
879  * @param code Reason code.
880  * @param fmt Formatting string used to build the reason phrase.
881  */
882 static void rpc_fault(rpc_ctx_t* ctx, int code, char* fmt, ...)
883 {
884         static char buf[REASON_BUF_LEN];
885         va_list ap;
886
887         ctx->reply.code = code;
888         va_start(ap, fmt);
889         vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
890         va_end(ap);
891         ctx->reply.reason = buf;
892 }
893
894 /** Create and initialize a new rpc_structure data structure.
895  *
896  * This function allocates and initializes memory for a new rpc_struct
897  * structure. If the caller provided non-NULL pointers in doc and structure
898  * parameters then the structure is coming from an XML-RPC request. If either
899  * of the pointers is NULL then we are creating a structure that will be
900  * attached to a XML-RPC reply sent to the client. The memory allocated in
901  * this function will be added to the garbage collection list.
902  *
903  * @param doc A pointer to the XML-RPC request document or NULL if we create
904  *            a structure that will be put in a reply.
905  * @param structure A pointer to opening tag of the structure in the XML-RPC
906  *                  request document or NULL if we create a structure that
907  *                  will be put in a XML-RPC reply.
908  * @param reply A pointer to xml_reply structure, NULL if it is a structure
909  *              coming from a XML-RPC request.
910  */
911 static struct rpc_struct* new_rpcstruct(xmlDocPtr doc, xmlNodePtr structure, 
912                                                                                 struct xmlrpc_reply* reply)
913 {
914         struct rpc_struct* p;
915
916         p = (struct rpc_struct*)pkg_malloc(sizeof(struct rpc_struct));
917         if (!p) {
918                 set_fault(reply, 500, "Internal Server Error (No Memory Left");
919                 return 0;
920         }
921         memset(p, 0, sizeof(struct rpc_struct));
922         p->struct_in = structure;
923
924         p->reply = reply;
925         p->n = 0;
926         if (doc && structure) {
927                      /* We will be parsing structure from request */
928                 p->doc = doc;
929                 p->struct_in = structure;
930         } else {
931                      /* We will build a reply structure */
932                 if (init_xmlrpc_reply(&p->struct_out) < 0) goto err;
933                 if (add_xmlrpc_reply(&p->struct_out, &struct_prefix) < 0) goto err;
934
935         }
936         if (add_garbage(JUNK_RPCSTRUCT, p, reply) < 0) goto err;
937         return p;
938
939  err:
940         if (p->struct_out.buf.s) pkg_free(p->struct_out.buf.s);
941         pkg_free(p);
942         return 0;
943 }
944
945 /** Converts the variables provided in parameter ap according to formatting
946  * string provided in parameter fmt into parameters in XML-RPC format.
947  *
948  * This function takes the parameters provided in ap parameter and creates
949  * XML-RPC formatted parameters that will be put in the document in res
950  * parameter. The format of input parameters is described in formatting string
951  * fmt which follows the syntax of the management API in SER. In the case of
952  * an error the function will generate an error reply in err_reply parameter
953  * instead.
954  * @param res A pointer to the XML-RPC result structure where the parameters
955  *            will be written.
956  * @param err_reply An error reply document will be generated here if the
957  *                  function encounters a problem while processing input
958  *                  parameters.
959  * @param fmt Formatting string of the management API in SER.
960  * @param ap A pointer to the array of input parameters.
961  *
962  */
963 static int print_value(struct xmlrpc_reply* res, 
964                                            struct xmlrpc_reply* err_reply, char fmt, va_list* ap)
965 {
966         str prefix, body, suffix;
967         str* sp;
968         char buf[256];
969         time_t dt;
970         struct tm* t;
971
972         switch(fmt) {
973         case 'd':
974                 prefix = int_prefix;
975                 suffix = int_suffix;
976                 body.s = int2str(va_arg(*ap, int), &body.len);
977                 break;
978
979         case 'f':
980                 prefix = double_prefix;
981                 suffix = double_suffix;
982                 body.s = buf;
983                 body.len = snprintf(buf, 256, "%f", va_arg(*ap, double));
984                 if (body.len < 0) {
985                         set_fault(err_reply, 400, "Error While Converting double");
986                         ERR("Error while converting double\n");
987                         goto err;
988                 }
989                 break;
990
991         case 'b':
992                 prefix = bool_prefix;
993                 suffix = bool_suffix;
994                 body.len = 1;
995                 body.s = ((va_arg(*ap, int) == 0) ? "0" : "1");
996                 break;
997
998         case 't':
999                 prefix = date_prefix;
1000                 suffix = date_suffix;
1001                 body.s = buf;
1002                 body.len = sizeof("19980717T14:08:55") - 1;
1003                 dt = va_arg(*ap, time_t);
1004                 t = gmtime(&dt);
1005                 if (strftime(buf, 256, "%Y%m%dT%H:%M:%S", t) == 0) {
1006                         set_fault(err_reply, 400, "Error While Converting datetime");
1007                         ERR("Error while converting time\n");
1008                         goto err;
1009                 }
1010                 break;
1011
1012         case 's':
1013                 prefix = string_prefix;
1014                 suffix = string_suffix;
1015                 body.s = va_arg(*ap, char*);
1016                 body.len = strlen(body.s);
1017                 break;
1018
1019         case 'S':
1020                 prefix = string_prefix;
1021                 suffix = string_suffix;
1022                 sp = va_arg(*ap, str*);
1023                 body = *sp;
1024                 break;
1025
1026         default:
1027                 set_fault(err_reply, 500, "Bug In SER (Invalid formatting character)");
1028                 ERR("Invalid formatting character\n");
1029                 goto err;
1030         }
1031
1032         if (add_xmlrpc_reply(res, &prefix) < 0) goto err;
1033         if (add_xmlrpc_reply_esc(res, &body) < 0) goto err;
1034         if (add_xmlrpc_reply(res, &suffix) < 0) goto err;
1035         return 0;
1036  err:
1037         return -1;
1038 }
1039
1040 /** Implementation of rpc_add function required by the management API in SER.
1041  *
1042  * This function will be called when a management function in SER calls
1043  * rpc->add to add a parameter to the XML-RPC reply being generated.
1044  */
1045 static int rpc_add(rpc_ctx_t* ctx, char* fmt, ...)
1046 {
1047         void* void_ptr;
1048         va_list ap;
1049         struct xmlrpc_reply* reply;
1050         struct rpc_struct* p;
1051
1052         fix_delayed_reply_ctx(ctx);
1053         va_start(ap, fmt);
1054         reply = &ctx->reply;
1055
1056         while(*fmt) {
1057                 if (ctx->flags & RET_ARRAY && 
1058                         add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
1059                 if (*fmt == '{') {
1060                         void_ptr = va_arg(ap, void**);
1061                         p = new_rpcstruct(0, 0, reply);
1062                         if (!p) goto err;
1063                         *(struct rpc_struct**)void_ptr = p;
1064                         p->offset = get_reply_len(reply);
1065                         p->next = ctx->structs;
1066                         ctx->structs = p;
1067                 } else {
1068                         if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
1069                 }
1070
1071                 if (ctx->flags & RET_ARRAY && 
1072                         add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
1073                 if (add_xmlrpc_reply(reply, &lf) < 0) goto err;
1074                 fmt++;
1075         }
1076         va_end(ap);
1077         return 0;
1078  err:
1079         va_end(ap);
1080         return -1;
1081 }
1082
1083
1084 /** Convert time in XML-RPC format to time_t */
1085 static time_t xmlrpc2time(const char* str)
1086 {
1087         struct tm time;
1088
1089         memset(&time, '\0', sizeof(struct tm));
1090         strptime(str, "%Y%m%dT%H:%M:%S", &time);
1091         time.tm_isdst = -1;
1092 #ifdef HAVE_TIMEGM
1093         return timegm(&time);
1094 #else
1095         return _timegm(&time);
1096 #endif /* HAVE_TIMEGM */
1097 }
1098
1099
1100
1101 /* get_* flags: */
1102 #define GET_X_AUTOCONV 1
1103 #define GET_X_NOREPLY 2
1104 #define GET_X_LFLF2CRLF 4  /* replace "\n\n" with "\r\n" */
1105
1106 /* xml value types */
1107 enum xmlrpc_val_type{
1108         XML_T_STR,
1109         XML_T_INT,
1110         XML_T_BOOL,
1111         XML_T_DATE,
1112         XML_T_DOUBLE,
1113         XML_T_ERR=-1
1114 };
1115
1116
1117
1118 /** Returns the XML-RPC value type.
1119  * @return value type (>= on success, XML_T_ERR on error/unknown type)
1120  */
1121 static enum xmlrpc_val_type xml_get_type(xmlNodePtr value)
1122 {
1123         if (!xmlStrcmp(value->name, BAD_CAST "string")){
1124                 return XML_T_STR;
1125         } else if ( !xmlStrcmp(value->name, BAD_CAST "i4") ||
1126                                 !xmlStrcmp(value->name, BAD_CAST "int")) {
1127                 return XML_T_INT;
1128         } else if (!xmlStrcmp(value->name, BAD_CAST "boolean")) {
1129                 return XML_T_BOOL;
1130         } else if (!xmlStrcmp(value->name, BAD_CAST "dateTime.iso8601")) {
1131                 return XML_T_DATE;
1132         }else if (!(xmlStrcmp(value->name, BAD_CAST "double"))){
1133                 return XML_T_DOUBLE;
1134         }
1135         return XML_T_ERR;
1136 }
1137
1138
1139
1140 /** Converts an XML-RPC encoded parameter into integer if possible.
1141  *
1142  * This function receives a pointer to a parameter encoded in XML-RPC format
1143  * and tries to convert the value of the parameter into integer.  Only
1144  * &lt;i4&gt;, &lt;int&gt;, &lt;boolean&gt;, &lt;dateTime.iso8601&gt; XML-RPC
1145  * parameters can be converted to integer, attempts to conver other types will
1146  * fail.
1147  * @param val A pointer to an integer variable where the result will be 
1148  *            stored.  
1149  * @param reply A pointer to XML-RPC reply being constructed (used to 
1150  *        indicate conversion errors).  
1151  * @param doc A pointer to the XML-RPC request document.  
1152  * @param value A pointer to the element containing the parameter to be 
1153  *              converted within the document.
1154  * @param flags : GET_X_AUTOCONV - try autoconverting
1155  *                GET_X_NOREPLY - do not reply
1156  * @return <0 on error, 0 on success
1157  */
1158 static int get_int(int* val, struct xmlrpc_reply* reply, 
1159                                    xmlDocPtr doc, xmlNodePtr value, int flags)
1160 {
1161         enum xmlrpc_val_type type;
1162         int ret;
1163         xmlNodePtr i4;
1164         char* val_str;
1165         char* end_ptr;
1166
1167         if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
1168                 if (!(flags & GET_X_NOREPLY))
1169                         set_fault(reply, 400, "Invalid parameter value");
1170                 return -1;
1171         }
1172
1173         i4 = value->xmlChildrenNode;
1174         if (!i4){
1175                 if (!(flags & GET_X_NOREPLY))
1176                         set_fault(reply, 400, "Invalid Parameter Type");
1177                 return -1;
1178         }
1179         type=xml_get_type(i4);
1180         switch(type){
1181                 case XML_T_INT:
1182                 case XML_T_BOOL:
1183                 case XML_T_DATE:
1184                         break;
1185                 case XML_T_DOUBLE:
1186                 case XML_T_STR:
1187                         if (flags & GET_X_AUTOCONV)
1188                                 break;
1189                 case XML_T_ERR:
1190                         if (!(flags & GET_X_NOREPLY))
1191                                 set_fault(reply, 400, "Invalid Parameter Type");
1192                         return -1;
1193         }
1194
1195         val_str = (char*)xmlNodeListGetString(doc, i4->xmlChildrenNode, 1);
1196         if (!val_str) {
1197                 if (!(flags & GET_X_NOREPLY))
1198                         set_fault(reply, 400, "Empty Parameter Value");
1199                 return -1;
1200         }
1201         ret=0;
1202         switch(type){
1203                 case XML_T_INT:
1204                 case XML_T_BOOL:
1205                 case XML_T_STR:
1206                         /* Integer/bool conversion */
1207                         *val = strtol(val_str, &end_ptr, 10);
1208                         if (val_str==end_ptr)
1209                                 ret=-1;
1210                         break;
1211                 case XML_T_DATE:
1212                         *val = xmlrpc2time(val_str);
1213                         break;
1214                 case XML_T_DOUBLE:
1215                         *val = (int)strtod(val_str, &end_ptr);
1216                         if (val_str==end_ptr)
1217                                 ret=-1;
1218                         break;
1219                 case XML_T_ERR:
1220                         *val=0;
1221                         ret=-1;
1222                         break;
1223         }
1224         xmlFree(val_str);
1225         if (ret==-1 && !(flags & GET_X_NOREPLY))
1226                 set_fault(reply, 400, "Invalid Value");
1227         return ret;
1228 }
1229
1230
1231
1232 /** Converts an XML-RPC encoded parameter into double if possible.
1233  *
1234  * This function receives a pointer to a parameter encoded in XML-RPC format
1235  * and tries to convert the value of the parameter into double.  Only
1236  * &lt;i4&gt;, &lt;int&gt;, &lt;double&gt; XML-RPC parameters can be converted
1237  * to double, attempts to conver other types will fail.
1238  * @param val A pointer to an integer variable where the result will be 
1239  *            stored.
1240  * @param reply A pointer to XML-RPC reply being constructed (used to indicate
1241  *              conversion errors).
1242  * @param doc A pointer to the XML-RPC request document.
1243  * @param value A pointer to the element containing the parameter to be 
1244  *              converted within the document.
1245  * @param flags : GET_X_AUTOCONV - try autoconverting
1246  *                GET_X_NOREPLY - do not reply
1247  * @return <0 on error, 0 on success
1248  */
1249 static int get_double(double* val, struct xmlrpc_reply* reply, 
1250                                           xmlDocPtr doc, xmlNodePtr value, int flags)
1251 {
1252         xmlNodePtr dbl;
1253         char* val_str;
1254         char* end_ptr;
1255         enum xmlrpc_val_type type;
1256         int ret;
1257
1258         if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
1259                 if (!(flags & GET_X_NOREPLY))
1260                         set_fault(reply, 400, "Invalid Parameter Value");
1261                 return -1;
1262         }
1263
1264         dbl = value->xmlChildrenNode;
1265         if (!dbl){
1266                 if (!(flags & GET_X_NOREPLY))
1267                         set_fault(reply, 400, "Invalid Parameter Type");
1268                 return -1;
1269         }
1270         type=xml_get_type(dbl);
1271         switch(type){
1272                 case XML_T_DOUBLE:
1273                 case XML_T_INT:
1274                         break;
1275                 case XML_T_BOOL:
1276                 case XML_T_DATE:
1277                 case XML_T_STR:
1278                         if (flags & GET_X_AUTOCONV)
1279                                 break;
1280                 case XML_T_ERR:
1281                         if (!(flags & GET_X_NOREPLY))
1282                                 set_fault(reply, 400, "Invalid Parameter Type");
1283                         return -1;
1284         }
1285
1286         val_str = (char*)xmlNodeListGetString(doc, dbl->xmlChildrenNode, 1);
1287         if (!val_str) {
1288                 if (!(flags & GET_X_NOREPLY))
1289                         set_fault(reply, 400, "Empty Double Parameter");
1290                 return -1;
1291         }
1292         ret=0;
1293         switch(type){
1294                 case XML_T_DOUBLE:
1295                 case XML_T_INT:
1296                 case XML_T_BOOL:
1297                 case XML_T_STR:
1298                         *val = strtod(val_str, &end_ptr);
1299                         if (val_str==end_ptr)
1300                                 ret=-1;
1301                         break;
1302                 case XML_T_DATE:
1303                         *val = (double)xmlrpc2time(val_str);
1304                         break;
1305                 case XML_T_ERR:
1306                         *val=0;
1307                         ret=-1;
1308                         break;
1309         }
1310         xmlFree(val_str);
1311         if (ret==-1 && !(flags & GET_X_NOREPLY))
1312                 set_fault(reply, 400, "Invalid Value");
1313         return ret;
1314 }
1315
1316
1317 /** Convert a parameter encoded in XML-RPC to a zero terminated string.
1318  *
1319  * @param val A pointer to a char* variable where the result will be 
1320  *            stored (the result is dynamically allocated, but it's garbage
1321  *            collected, so it doesn't have to be freed)
1322  * @param reply A pointer to XML-RPC reply being constructed (used to indicate
1323  *              conversion errors).
1324  * @param doc A pointer to the XML-RPC request document.
1325  * @param value A pointer to the element containing the parameter to be 
1326  *              converted within the document.
1327  * @param flags 
1328  *              - GET_X_AUTOCONV - try autoconverting
1329  *              - GET_X_LFLF2CRLF - replace double '\\n' with `\\r\\n'
1330  *              - GET_X_NOREPLY - do not reply
1331  * @return <0 on error, 0 on success
1332  */
1333 static int get_string(char** val, struct xmlrpc_reply* reply, 
1334                                           xmlDocPtr doc, xmlNodePtr value, int flags)
1335 {
1336         static char* null_str = "";
1337         xmlNodePtr dbl;
1338         char* val_str;
1339         char* end_ptr;
1340         char* s;
1341         char* p;
1342         int i;
1343         int len;
1344         enum xmlrpc_val_type type;
1345         int ret;
1346
1347         if (!value || xmlStrcmp(value->name, BAD_CAST "value")) {
1348                 if (!(flags & GET_X_NOREPLY))
1349                         set_fault(reply, 400, "Invalid Parameter Value");
1350                 return -1;
1351         }
1352
1353         dbl = value->xmlChildrenNode;
1354         if (!dbl){
1355                 if (!(flags & GET_X_NOREPLY))
1356                         set_fault(reply, 400, "Invalid Parameter Type");
1357                 return -1;
1358         }
1359         type=xml_get_type(dbl);
1360         switch(type){
1361                 case XML_T_STR:
1362                         break;
1363                 case XML_T_INT:
1364                 case XML_T_BOOL:
1365                 case XML_T_DATE:
1366                 case XML_T_DOUBLE:
1367                         if (flags & GET_X_AUTOCONV)
1368                                 break;
1369                 case XML_T_ERR:
1370                         if (!(flags & GET_X_NOREPLY))
1371                                 set_fault(reply, 400, "Invalid Parameter Type");
1372                         return -1;
1373         }
1374         val_str = (char*)xmlNodeListGetString(doc, dbl->xmlChildrenNode, 1);
1375         if (!val_str) {
1376                 if (type==XML_T_STR){
1377                         *val = null_str;
1378                         return 0;
1379                 }else{
1380                         if (!(flags & GET_X_NOREPLY))
1381                                 set_fault(reply, 400, "Empty Parameter Value");
1382                         return -1;
1383                 }
1384         }
1385         ret=0;
1386         switch(type){
1387                 case XML_T_STR:
1388                         if (flags & GET_X_LFLF2CRLF){
1389                                 p=val_str;
1390                                 while(*p){
1391                                         if (*p=='\n' && *(p+1)=='\n'){
1392                                                 *p='\r';
1393                                                 p+=2;
1394                                                 continue;
1395                                         }
1396                                         p++;
1397                                 }
1398                         }
1399                         /* no break */
1400                 case XML_T_DATE:  /* no special conversion */
1401                 case XML_T_DOUBLE: /* no special conversion */
1402                         if (add_garbage(JUNK_XMLCHAR, val_str, reply) < 0){
1403                                 xmlFree(val_str);
1404                                 return -1;
1405                         }
1406                         *val = val_str;
1407                         break;
1408                 case XML_T_INT:
1409                 case XML_T_BOOL:
1410                         /* convert str to int an back to str */
1411                         i = strtol(val_str, &end_ptr, 10);
1412                         if (val_str==end_ptr){
1413                                 ret=-1;
1414                         }else{
1415                                 s=sint2str(i, &len);
1416                                 p=pkg_malloc(len+1);
1417                                 if (p && add_garbage(JUNK_PKGCHAR, p, reply) == 0){
1418                                         memcpy(p, s, len);
1419                                         p[len]=0;
1420                                         *val=p;
1421                                 }else{
1422                                         ret=-1;
1423                                         if (p) pkg_free(p);
1424                                 }
1425                         }
1426                         xmlFree(val_str);
1427                         break;
1428                 case XML_T_ERR:
1429                         xmlFree(val_str);
1430                         ret=-1;
1431                         break;
1432         }
1433         return ret;
1434 }
1435
1436
1437
1438 /** Implementation of rpc->scan function required by the management API in
1439  * SER.
1440  *
1441  * This is the function that will be called whenever a management function in
1442  * SER calls rpc->scan to get the value of parameter from the XML-RPC
1443  * request. This function will extract the current parameter from the XML-RPC
1444  * document and attempts to convert it to the type requested by the management
1445  * function that called it.
1446  */
1447 static int rpc_scan(rpc_ctx_t* ctx, char* fmt, ...)
1448 {
1449         int read;
1450         int fmt_len;
1451         int* int_ptr;
1452         char** char_ptr;
1453         str* str_ptr;
1454         double* double_ptr;
1455         void** void_ptr;
1456         xmlNodePtr value;
1457         struct xmlrpc_reply* reply;
1458         struct rpc_struct* p;
1459         int modifiers;
1460         int f;
1461         va_list ap;
1462
1463         reply = &ctx->reply;
1464         /* clear the previously saved error code */
1465         clear_xmlrpc_reply(reply);
1466
1467         fmt_len = strlen(fmt);
1468         va_start(ap, fmt);
1469         modifiers=0;
1470         read = 0;
1471         f=(autoconvert?GET_X_AUTOCONV:0) |
1472                 (lflf2crlf?GET_X_LFLF2CRLF:0);
1473         while(*fmt) {
1474                 if (!ctx->act_param) goto error;
1475                 value = ctx->act_param->xmlChildrenNode;
1476
1477                 switch(*fmt) {
1478                 case '*': /* start of optional parameters */
1479                         modifiers++;
1480                         read++;
1481                         fmt++;
1482                         continue; /* do not advance ctx->act-param */
1483                 case '.': /* autoconvert */
1484                         modifiers++;
1485                         read++;
1486                         fmt++;
1487                         f|=GET_X_AUTOCONV;
1488                         continue; /* do not advance ctx->act-param */
1489                 case 'b': /* Bool */
1490                 case 't': /* Date and time */
1491                 case 'd': /* Integer */
1492                         int_ptr = va_arg(ap, int*);
1493                         if (get_int(int_ptr, reply, ctx->doc, value, f) < 0) goto error;
1494                         break;
1495                         
1496                 case 'f': /* double */
1497                         double_ptr = va_arg(ap, double*);
1498                         if (get_double(double_ptr, reply, ctx->doc, value, f) < 0) {
1499                                 goto error;
1500                         }
1501                         break;
1502
1503                 case 's': /* zero terminated string */
1504                         char_ptr = va_arg(ap, char**);
1505                         if (get_string(char_ptr, reply, ctx->doc, value, f) < 0)
1506                                 goto error;
1507                         break;
1508
1509                 case 'S': /* str structure */
1510                         str_ptr = va_arg(ap, str*);
1511                         if (get_string(&str_ptr->s, reply, ctx->doc, value, f) < 0) {
1512                                 goto error;
1513                         }
1514                         str_ptr->len = strlen(str_ptr->s);
1515                         break;
1516
1517                 case '{':
1518                         void_ptr = va_arg(ap, void**);
1519                         if (!value->xmlChildrenNode) goto error;
1520                         p = new_rpcstruct(ctx->doc, value->xmlChildrenNode, reply);
1521                         if (!p) goto error;
1522                         *void_ptr = p;
1523                         break;
1524
1525                 default:
1526                         ERR("Invalid parameter type in formatting string: %c\n", *fmt);
1527                         set_fault(reply, 500, 
1528                                           "Server Internal Error (Invalid Formatting String)");
1529                         goto error;
1530                 }
1531                 ctx->act_param = ctx->act_param->next;
1532                 /* clear autoconv if not globally on */
1533                 f=autoconvert?GET_X_AUTOCONV:(f&~GET_X_AUTOCONV);
1534                 read++;
1535                 fmt++;
1536         }
1537         va_end(ap);
1538         return read-modifiers;
1539
1540  error:
1541         va_end(ap);
1542         return -(read-modifiers);
1543 }
1544
1545 #define RPC_BUF_SIZE 1024
1546
1547
1548 /** Implementation of rpc_printf function required by the management API in
1549  *      SER.
1550  *
1551  * This function will be called whenever a management function in SER calls
1552  * rpc-printf to add a parameter to the XML-RPC reply being constructed.
1553  */
1554 static int rpc_printf(rpc_ctx_t* ctx, char* fmt, ...)
1555 {
1556         int n, buf_size;
1557         char* buf;
1558         va_list ap;
1559         str s;
1560         struct xmlrpc_reply* reply;
1561
1562         fix_delayed_reply_ctx(ctx);
1563         reply = &ctx->reply;
1564         buf = (char*)pkg_malloc(RPC_BUF_SIZE);
1565         if (!buf) {
1566                 set_fault(reply, 500, "Internal Server Error (No memory left)");
1567                 ERR("No memory left\n");
1568                 return -1;
1569         }
1570
1571         buf_size = RPC_BUF_SIZE;
1572         while (1) {
1573                      /* Try to print in the allocated space. */
1574                 va_start(ap, fmt);
1575                 n = vsnprintf(buf, buf_size, fmt, ap);
1576                 va_end(ap);
1577                      /* If that worked, return the string. */
1578                 if (n > -1 && n < buf_size) {
1579                         s.s = buf;
1580                         s.len = n;
1581                         if (ctx->flags & RET_ARRAY && 
1582                                 add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
1583                         if (add_xmlrpc_reply(reply, &string_prefix) < 0) goto err;
1584                         if (add_xmlrpc_reply_esc(reply, &s) < 0) goto err;
1585                         if (add_xmlrpc_reply(reply, &string_suffix) < 0) goto err;
1586                         if (ctx->flags & RET_ARRAY && 
1587                                 add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
1588                         if (add_xmlrpc_reply(reply, &lf) < 0) goto err;
1589                         pkg_free(buf);
1590                         return 0;
1591                 }
1592                      /* Else try again with more space. */
1593                 if (n > -1) {   /* glibc 2.1 */
1594                         buf_size = n + 1; /* precisely what is needed */
1595                 } else {          /* glibc 2.0 */
1596                         buf_size *= 2;  /* twice the old size */
1597                 }
1598                 if ((buf = pkg_realloc(buf, buf_size)) == 0) {
1599                         set_fault(reply, 500, "Internal Server Error (No memory left)");
1600                         ERR("No memory left\n");
1601                         goto err;
1602                 }
1603         }
1604         return 0;
1605  err:
1606         if (buf) pkg_free(buf);
1607         return -1;
1608 }
1609
1610 /* Structure manipulation functions */
1611
1612 /** Find a structure member by name.
1613  */
1614 static int find_member(xmlNodePtr* value, xmlDocPtr doc, xmlNodePtr structure,
1615                                            struct xmlrpc_reply* reply, char* member_name)
1616 {
1617         char* name_str;
1618         xmlNodePtr member, name;
1619
1620         if (!structure) {
1621                 set_fault(reply, 400, "Invalid Structure Parameter");
1622                 return -1;
1623         }
1624
1625         member = structure->xmlChildrenNode;
1626         while(member) {
1627                 name = member->xmlChildrenNode;
1628                      /* Find <name> node in the member */
1629                 while(name) {
1630                         if (!xmlStrcmp(name->name, BAD_CAST "name")) break;
1631                         name = name->next;
1632                 }
1633                 if (!name) {
1634                         set_fault(reply, 400, "Member Name Not Found In Structure");
1635                         return -1;
1636                 }
1637
1638                      /* Check the value of <name> node in the structure member */
1639                 name_str = (char*)xmlNodeListGetString(doc, name->xmlChildrenNode, 1);
1640                 if (!name_str) {
1641                         set_fault(reply, 400, "Empty name Element of Structure Parameter");
1642                         return -1;
1643                 }
1644                 if (strcmp(name_str, member_name)) {
1645                         xmlFree(name_str);
1646                         goto skip;
1647                 }
1648                 xmlFree(name_str);
1649
1650                 *value = member->xmlChildrenNode;
1651                 while(*value) {
1652                         if (!xmlStrcmp((*value)->name, BAD_CAST "value")) break;
1653                         (*value) = (*value)->next;
1654                 }
1655                 if (!(*value)) {
1656                         set_fault(reply, 400, "Member Value Not Found In Structure");
1657                         return -1;
1658                 }
1659                 return 0;
1660         skip:
1661                 member = member->next;
1662         }
1663         return 1;
1664 }
1665
1666 /** Adds a new member to structure.
1667  */
1668 static int rpc_struct_add(struct rpc_struct* s, char* fmt, ...)
1669 {
1670         va_list ap;
1671         str member_name;
1672         struct xmlrpc_reply* reply;
1673
1674         reply = &s->struct_out;
1675
1676         va_start(ap, fmt);
1677         while(*fmt) {
1678                 member_name.s = va_arg(ap, char*);
1679                 member_name.len = (member_name.s ? strlen(member_name.s) : 0);
1680
1681                 if (add_xmlrpc_reply(reply, &member_prefix) < 0) goto err;
1682                 if (add_xmlrpc_reply(reply, &name_prefix) < 0) goto err;
1683                 if (add_xmlrpc_reply_esc(reply, &member_name) < 0) goto err;
1684                 if (add_xmlrpc_reply(reply, &name_suffix) < 0) goto err;
1685                 if (add_xmlrpc_reply(reply, &value_prefix) < 0) goto err;
1686                 if (print_value(reply, reply, *fmt, &ap) < 0) goto err;
1687                 if (add_xmlrpc_reply(reply, &value_suffix) < 0) goto err;
1688                 if (add_xmlrpc_reply(reply, &member_suffix) < 0) goto err;
1689                 fmt++;
1690         }
1691
1692         va_end(ap);
1693         return 0;
1694  err:
1695         va_end(ap);
1696         return -1;
1697 }
1698
1699 /** Create a new member from formatting string and add it to a structure.
1700  */
1701 static int rpc_struct_printf(struct rpc_struct* s, char* member_name, 
1702                                                          char* fmt, ...)
1703 {
1704         int n, buf_size;
1705         char* buf;
1706         va_list ap;
1707         str st, name;
1708         struct xmlrpc_reply* reply;
1709         struct xmlrpc_reply* out;
1710
1711         out = &s->struct_out;
1712         buf = (char*)pkg_malloc(RPC_BUF_SIZE);
1713         reply = s->reply;
1714         if (!buf) {
1715                 set_fault(reply, 500, "Internal Server Error (No memory left)");
1716                 ERR("No memory left\n");
1717                 return -1;
1718         }
1719
1720         buf_size = RPC_BUF_SIZE;
1721         while (1) {
1722                      /* Try to print in the allocated space. */
1723                 va_start(ap, fmt);
1724                 n = vsnprintf(buf, buf_size, fmt, ap);
1725                 va_end(ap);
1726                      /* If that worked, return the string. */
1727                 if (n > -1 && n < buf_size) {
1728                         st.s = buf;
1729                         st.len = n;
1730
1731                         name.s = member_name;
1732                         name.len = strlen(member_name);
1733
1734                         if (add_xmlrpc_reply(out, &member_prefix) < 0) goto err;
1735                         if (add_xmlrpc_reply(out, &name_prefix) < 0) goto err;
1736                         if (add_xmlrpc_reply_esc(out, &name) < 0) goto err;
1737                         if (add_xmlrpc_reply(out, &name_suffix) < 0) goto err;
1738                         if (add_xmlrpc_reply(out, &value_prefix) < 0) goto err;
1739
1740                         if (add_xmlrpc_reply(out, &string_prefix) < 0) goto err;
1741                         if (add_xmlrpc_reply_esc(out, &st) < 0) goto err;
1742                         if (add_xmlrpc_reply(out, &string_suffix) < 0) goto err;
1743
1744                         if (add_xmlrpc_reply(out, &value_suffix) < 0) goto err;
1745                         if (add_xmlrpc_reply(out, &member_suffix) < 0) goto err;
1746
1747                         return 0;
1748                 }
1749                      /* Else try again with more space. */
1750                 if (n > -1) {   /* glibc 2.1 */
1751                         buf_size = n + 1; /* precisely what is needed */
1752                 } else {          /* glibc 2.0 */
1753                         buf_size *= 2;  /* twice the old size */
1754                 }
1755                 if ((buf = pkg_realloc(buf, buf_size)) == 0) {
1756                         set_fault(reply, 500, "Internal Server Error (No memory left)");
1757                         ERR("No memory left\n");
1758                         goto err;
1759                 }
1760         }
1761         return 0;
1762  err:
1763         if (buf) pkg_free(buf);
1764         return -1;
1765
1766 }
1767
1768
1769 static int rpc_struct_scan(struct rpc_struct* s, char* fmt, ...)
1770 {
1771         int read;
1772         va_list ap;
1773         int* int_ptr;
1774         double* double_ptr;
1775         char** char_ptr;
1776         str* str_ptr;
1777         xmlNodePtr value;
1778         char* member_name;
1779         struct xmlrpc_reply* reply;
1780         int ret;
1781         int f;
1782
1783         read = 0;
1784         f=(autoconvert?GET_X_AUTOCONV:0) |
1785                 (lflf2crlf?GET_X_LFLF2CRLF:0);
1786         va_start(ap, fmt);
1787         while(*fmt) {
1788                 member_name = va_arg(ap, char*);
1789                 reply = s->reply;
1790                 /* clear the previously saved error code */
1791                 clear_xmlrpc_reply(reply);
1792                 ret = find_member(&value, s->doc, s->struct_in, reply, member_name);
1793                 if (ret != 0) goto error;
1794
1795                 switch(*fmt) {
1796                 case 'b': /* Bool */
1797                 case 't': /* Date and time */
1798                 case 'd': /* Integer */
1799                         int_ptr = va_arg(ap, int*);
1800                         if (get_int(int_ptr, reply, s->doc, value, f) < 0) goto error;
1801                         break;
1802
1803                 case 'f': /* double */
1804                         double_ptr = va_arg(ap, double*);
1805                         if (get_double(double_ptr, reply, s->doc, value, f) < 0)
1806                                 goto error;
1807                         break;
1808
1809                 case 's': /* zero terminated string */
1810                         char_ptr = va_arg(ap, char**);
1811                         if (get_string(char_ptr, reply, s->doc, value, f) < 0) goto error;
1812                         break;
1813
1814                 case 'S': /* str structure */
1815                         str_ptr = va_arg(ap, str*);
1816                         if (get_string(&str_ptr->s, reply, s->doc, value, f) < 0)
1817                                 goto error;
1818                         str_ptr->len = strlen(str_ptr->s);
1819                         break;
1820                 default:
1821                         ERR("Invalid parameter type in formatting string: %c\n", *fmt);
1822                         return -1;
1823                 }
1824                 fmt++;
1825                 read++;
1826         }
1827         va_end(ap);
1828         return read;
1829  error:
1830         va_end(ap);
1831         return -read;
1832 }
1833
1834
1835 /** Returns the RPC capabilities supported by the xmlrpc driver.
1836  */
1837 static rpc_capabilities_t rpc_capabilities(rpc_ctx_t* ctx)
1838 {
1839         return RPC_DELAYED_REPLY;
1840 }
1841
1842
1843 /** Returns a new "delayed reply" context.
1844  * Creates a new delayed reply context in shm and returns it.
1845  * @return 0 - not supported, already replied, or no more memory;
1846  *         !=0 pointer to the special delayed ctx.
1847  * Note1: one should use the returned ctx reply context to build a reply and
1848  *  when finished call rpc_delayed_ctx_close().
1849  * Note2: adding pieces to the reply in different processes is not supported.
1850  */
1851 static struct rpc_delayed_ctx* rpc_delayed_ctx_new(rpc_ctx_t* ctx)
1852 {
1853         struct rpc_delayed_ctx* ret;
1854         int size;
1855         rpc_ctx_t* r_ctx;
1856         struct sip_msg* shm_msg;
1857         int len;
1858         
1859         ret=0;
1860         shm_msg=0;
1861         
1862         if (ctx->reply_sent)
1863                 return 0; /* no delayed reply if already replied */
1864         /* clone the sip msg */
1865         shm_msg=sip_msg_shm_clone(ctx->msg, &len, 1);
1866         if (shm_msg==0)
1867                 goto error;
1868         
1869         /* alloc into one block */
1870         size=ROUND_POINTER(sizeof(*ret))+sizeof(rpc_ctx_t);
1871         if ((ret=shm_malloc(size))==0)
1872                 goto error;
1873         memset(ret, 0, size);
1874         ret->rpc=func_param;
1875         ret->reply_ctx=(char*)ret+ROUND_POINTER(sizeof(*ret));
1876         r_ctx=ret->reply_ctx;
1877         r_ctx->flags=ctx->flags | XMLRPC_DELAYED_CTX_F;
1878         ctx->flags |= XMLRPC_DELAYED_REPLY_F;
1879         r_ctx->msg=shm_msg;
1880         r_ctx->msg_shm_block_size=len;
1881         
1882         return ret;
1883 error:
1884         if (shm_msg)
1885                 shm_free(shm_msg);
1886         if (ret)
1887                 shm_free(ret);
1888         return 0;
1889 }
1890
1891
1892
1893 /** Closes a "delayed reply" context and sends the reply.
1894  * If no reply has been sent the reply will be built and sent automatically.
1895  * See the notes from rpc_new_delayed_ctx()
1896  */
1897 static void rpc_delayed_ctx_close(struct rpc_delayed_ctx* dctx)
1898 {
1899         rpc_ctx_t* r_ctx;
1900         struct hdr_field* hdr;
1901         
1902         r_ctx=dctx->reply_ctx;
1903         if (unlikely(!(r_ctx->flags & XMLRPC_DELAYED_CTX_F))){
1904                 BUG("reply ctx not marked as async/delayed\n");
1905                 goto error;
1906         }
1907         if (fix_delayed_reply_ctx(r_ctx)<0)
1908                 goto error;
1909         if (!r_ctx->reply_sent){
1910                 rpc_send(r_ctx);
1911         }
1912 error:
1913         clean_context(r_ctx);
1914         /* collect possible garbage (e.g. generated by structures) */
1915         collect_garbage();
1916         /* free added lumps (rpc_send adds a body lump) */
1917         del_nonshm_lump( &(r_ctx->msg->add_rm) );
1918         del_nonshm_lump( &(r_ctx->msg->body_lumps) );
1919         del_nonshm_lump_rpl( &(r_ctx->msg->reply_lump) );
1920         /* free header's parsed structures that were added by failure handlers */
1921         for( hdr=r_ctx->msg->headers ; hdr ; hdr=hdr->next ) {
1922                 if ( hdr->parsed && hdr_allocs_parse(hdr) &&
1923                 (hdr->parsed<(void*)r_ctx->msg ||
1924                 hdr->parsed>=(void*)(r_ctx->msg+r_ctx->msg_shm_block_size))) {
1925                         /* header parsed filed doesn't point inside uas.request memory
1926                          * chunck -> it was added by failure funcs.-> free it as pkg */
1927                         DBG("DBG:free_faked_req: removing hdr->parsed %d\n",
1928                                         hdr->type);
1929                         clean_hdr_field(hdr);
1930                         hdr->parsed = 0;
1931                 }
1932         }
1933         shm_free(r_ctx->msg);
1934         r_ctx->msg=0;
1935         dctx->reply_ctx=0;
1936         shm_free(dctx);
1937 }
1938
1939
1940 /** Starts parsing XML-RPC document, get the name of the method to be called
1941  * and position the cursor at the first parameter in the document.
1942  */
1943 static int open_doc(rpc_ctx_t* ctx, sip_msg_t* msg)
1944 {
1945         str doc;
1946         xmlNodePtr root;
1947         xmlNodePtr cur;
1948         struct xmlrpc_reply* reply;
1949
1950         reply = &ctx->reply;
1951         if (get_rpc_document(&doc, msg) < 0) {
1952                 set_fault(reply, 400, "Malformed Message Body");
1953                 ERR("Error extracting message body\n");
1954                 return -1;
1955         }
1956
1957         ctx->doc = xmlReadMemory(doc.s, doc.len, 0, 0,
1958                                  XML_PARSE_NOBLANKS |
1959                                  XML_PARSE_NONET |
1960                                  XML_PARSE_NOCDATA);
1961
1962         if (!ctx->doc) {
1963                 set_fault(reply, 400, "Invalid XML-RPC Document");
1964                 ERR("Invalid XML-RPC document: \n[%.*s]\n", doc.len, doc.s);
1965                 goto err;
1966         }
1967
1968         root = xmlDocGetRootElement(ctx->doc);
1969         if (!root) {
1970                 set_fault(reply, 400, "Empty XML-RPC Document");
1971                 ERR("Empty XML-RPC document\n");
1972                 goto err;
1973         }
1974
1975         if (xmlStrcmp(root->name, (const xmlChar*)"methodCall")) {
1976                 set_fault(reply, 400, "Root Element Is Not methodCall");
1977                 ERR("Root element is not methodCall\n");
1978                 goto err;
1979         }
1980
1981         cur = root->xmlChildrenNode;
1982         while(cur) {
1983                 if (!xmlStrcmp(cur->name, (const xmlChar*)"methodName")) {
1984                         ctx->method = (char*)xmlNodeListGetString(ctx->doc, cur->xmlChildrenNode, 1);
1985                         if (!ctx->method) {
1986                                 set_fault(reply, 400, "Cannot Extract Method Name");
1987                                 ERR("Cannot extract method name\n");
1988                                 goto err;
1989                         }
1990                         break;
1991                 }
1992                 cur = cur->next;
1993         }
1994         if (!cur) {
1995                 set_fault(reply, 400, "Method Name Not Found");
1996                 ERR("Method name not found\n");
1997                 goto err;
1998         }
1999         cur = root->xmlChildrenNode;
2000         while(cur) {
2001                 if (!xmlStrcmp(cur->name, (const xmlChar*)"params")) {
2002                         ctx->act_param = cur->xmlChildrenNode;
2003                         break;
2004                 }
2005                 cur = cur->next;
2006         }
2007         if (!cur) ctx->act_param = 0;
2008         return 0;
2009
2010  err:
2011         close_doc(ctx);
2012         return -1;
2013 }
2014
2015 static void close_doc(rpc_ctx_t* ctx)
2016 {
2017         if (ctx->method) xmlFree(ctx->method);
2018         if (ctx->doc) xmlFreeDoc(ctx->doc);
2019         ctx->method = 0;
2020         ctx->doc = 0;
2021 }
2022
2023 static int init_context(rpc_ctx_t* ctx, sip_msg_t* msg)
2024 {
2025         ctx->msg = msg;
2026         ctx->msg_shm_block_size=0;
2027         ctx->method = 0;
2028         ctx->reply_sent = 0;
2029         ctx->act_param = 0;
2030         ctx->doc = 0;
2031         ctx->structs = 0;
2032         if (init_xmlrpc_reply(&ctx->reply) < 0) return -1;
2033         add_xmlrpc_reply(&ctx->reply, &success_prefix);
2034         if (open_doc(ctx, msg) < 0) return -1;
2035         return 0;
2036 }
2037
2038
2039 static void clean_context(rpc_ctx_t* ctx)
2040 {
2041         if (!ctx) return;
2042         clean_xmlrpc_reply(&ctx->reply);
2043         close_doc(ctx);
2044 }
2045
2046
2047
2048 /** Creates a SIP message (in "buffer" form) from a HTTP XML-RPC request).
2049  * 
2050  * NOTE: the result must be pkg_free()'ed when not needed anymore.  
2051  * @return 0 on error, buffer allocated using pkg_malloc on success.
2052  */
2053 static char* http_xmlrpc2sip(sip_msg_t* msg, int* new_msg_len)
2054 {
2055         unsigned int len, via_len;
2056         char* via, *new_msg, *p;
2057         str ip, port;
2058         struct hostport hp;
2059         struct dest_info dst;
2060         
2061         /* create a via */
2062         ip.s = ip_addr2a(&msg->rcv.src_ip);
2063         ip.len = strlen(ip.s);
2064         port.s = int2str(msg->rcv.src_port, &port.len);
2065         hp.host = &ip;
2066         hp.port = &port;
2067         init_dst_from_rcv(&dst, &msg->rcv);
2068         via = via_builder(&via_len, &dst, 0, 0, &hp);
2069         if (via == 0) {
2070                 DEBUG("failed to build via\n");
2071                 return 0;
2072         }
2073         len = msg->first_line.u.request.method.len + 1 /* space */ + 
2074                 XMLRPC_URI_LEN + 1 /* space */ + 
2075                 msg->first_line.u.request.version.len + CRLF_LEN + via_len + 
2076                 (msg->len-msg->first_line.len);
2077         p = new_msg = pkg_malloc(len + 1);
2078         if (new_msg == 0) {
2079                 DEBUG("memory allocation failure (%d bytes)\n", len);
2080                 pkg_free(via);
2081                 return 0;
2082         }
2083
2084         /* new message:
2085          * <orig_http_method> sip:127.0.0.1:9 HTTP/1.x 
2086          * Via: <faked via>
2087          * <orig. http message w/o the first line>
2088          */
2089         memcpy(p, msg->first_line.u.request.method.s, 
2090                    msg->first_line.u.request.method.len);
2091         p += msg->first_line.u.request.method.len;
2092         *p = ' ';
2093         p++;
2094         memcpy(p, XMLRPC_URI, XMLRPC_URI_LEN);
2095         p += XMLRPC_URI_LEN;
2096         *p = ' ';
2097         p++;
2098         memcpy(p, msg->first_line.u.request.version.s,
2099                    msg->first_line.u.request.version.len);
2100         p += msg->first_line.u.request.version.len;
2101         memcpy(p, CRLF, CRLF_LEN);
2102         p += CRLF_LEN;
2103         memcpy(p, via, via_len);
2104         p += via_len;
2105         memcpy(p,  SIP_MSG_START(msg) + msg->first_line.len, 
2106                    msg->len - msg->first_line.len);
2107         new_msg[len] = 0; /* null terminate, required by receive_msg() */
2108         pkg_free(via);
2109         *new_msg_len = len;
2110         return new_msg;
2111 }
2112
2113
2114
2115 /** Emulate receive_msg for an XML-RPC request .
2116  */
2117 static int em_receive_request(sip_msg_t* orig_msg, 
2118                                                           char* new_buf, unsigned int new_len)
2119 {
2120         int ret;
2121         sip_msg_t tmp_msg, *msg;
2122         struct run_act_ctx ra_ctx;
2123         
2124         ret=0;
2125         if (new_buf && new_len) {
2126                 memset(&tmp_msg, 0, sizeof(sip_msg_t));
2127                 tmp_msg.buf = new_buf;
2128                 tmp_msg.len = new_len;
2129                 tmp_msg.rcv = orig_msg->rcv;
2130                 tmp_msg.id = orig_msg->id;
2131                 tmp_msg.set_global_address = orig_msg->set_global_address;
2132                 tmp_msg.set_global_port = orig_msg->set_global_port;
2133                 if (parse_msg(new_buf, new_len, &tmp_msg) != 0) {
2134                         ERR("xmlrpc: parse_msg failed\n");
2135                         goto error;
2136                 }
2137                 msg = &tmp_msg;
2138         } else {
2139                 msg = orig_msg;
2140         }
2141         
2142         /* not needed, performed by the "real" receive_msg()
2143            clear_branches();
2144            reset_static_buffer();
2145         */
2146         if ((msg->first_line.type != SIP_REQUEST) || (msg->via1 == 0) ||
2147                 (msg->via1->error != PARSE_OK)) {
2148                 BUG("xmlrpc: strange message: %.*s\n", msg->len, msg->buf);
2149                 goto error;
2150         }
2151         if (exec_pre_script_cb(msg, REQUEST_CB_TYPE) == 0) {
2152                 goto end; /* drop request */
2153         }
2154         /* exec routing script */
2155         init_run_actions_ctx(&ra_ctx);
2156         if (run_actions(&ra_ctx, main_rt.rlist[xmlrpc_route_no], msg) < 0) {
2157                 ret=-1;
2158                 DBG("xmlrpc: error while trying script\n");
2159                 goto end;
2160         }
2161  end:
2162         exec_post_script_cb(msg, REQUEST_CB_TYPE); /* needed for example if tm is used */
2163         /* reset_avps(); non needed, performed by the real receive_msg */
2164         if (msg != orig_msg) { /* avoid double free (freed from receive_msg
2165                                                           too) */
2166                 free_sip_msg(msg);
2167         }
2168         return ret;
2169  error:
2170         return -1;
2171 }
2172
2173
2174 /** The main handler that will be called when SER core receives a non-SIP
2175  * request (i.e. HTTP request carrying XML-RPC document in the body).
2176  */
2177 static int process_xmlrpc(sip_msg_t* msg)
2178 {
2179         int ret;
2180         char* fake_msg;
2181         int fake_msg_len;
2182         unsigned char* method;
2183         unsigned int method_len, n_method;
2184         regmatch_t pmatch;
2185         char c;
2186         
2187         ret=NONSIP_MSG_DROP;
2188         if (!IS_HTTP(msg))
2189                 return NONSIP_MSG_PASS;
2190
2191         if(xmlrpc_url_skip!=NULL || xmlrpc_url_match!=NULL)
2192         {
2193                 c = msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len];
2194                 msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
2195                         = '\0';
2196                 if (xmlrpc_url_skip!=NULL &&
2197                         regexec(&xmlrpc_url_skip_regexp, msg->first_line.u.request.uri.s,
2198                                         1, &pmatch, 0)==0)
2199                 {
2200                         LM_DBG("URL matched skip re\n");
2201                         msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
2202                                 = c;
2203                         return NONSIP_MSG_PASS;
2204                 }
2205                 if (xmlrpc_url_match!=NULL &&
2206                         regexec(&xmlrpc_url_match_regexp, msg->first_line.u.request.uri.s,
2207                                         1, &pmatch, 0)!=0)
2208                 {
2209                         LM_DBG("URL not matched\n");
2210                         msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len]
2211                                 = c;
2212                         return NONSIP_MSG_PASS;
2213                 }
2214                 msg->first_line.u.request.uri.s[msg->first_line.u.request.uri.len] = c;
2215         }
2216
2217         method = (unsigned char*)msg->first_line.u.request.method.s;
2218         method_len = msg->first_line.u.request.method.len;
2219         /* first line is always > 4, so it's always safe to try to read the
2220          * 1st 4 bytes from method, even if method is shorter*/
2221         n_method = method[0] + (method[1] << 8) + (method[2] << 16) +
2222                         (method[3] << 24);
2223         n_method |= 0x20202020;
2224         n_method &= ((method_len < 4) * (1U << method_len * 8) - 1);
2225         /* accept only GET or POST */
2226         if ((n_method == N_HTTP_GET) ||
2227                         ((n_method == N_HTTP_POST) && (method_len == HTTP_POST_LEN))) {
2228                 if (msg->via1 == 0){
2229                         /* create a fake sip message */
2230                         fake_msg = http_xmlrpc2sip(msg, &fake_msg_len);
2231                         if (fake_msg == 0) {
2232                                 ERR("xmlrpc: out of memory\n");
2233                                 ret=NONSIP_MSG_ERROR;
2234                         } else {
2235                         /* send it */
2236                                 DBG("new fake xml msg created (%d bytes):\n<%.*s>\n",
2237                                         fake_msg_len, fake_msg_len, fake_msg);
2238                                 if (em_receive_request(msg, fake_msg, fake_msg_len)<0)
2239                                         ret=NONSIP_MSG_ERROR;
2240                                 pkg_free(fake_msg);
2241                         }
2242                         return ret; /* we "ate" the message, stop processing */
2243                 } else { /* the message has a via */
2244                         DBG("http xml msg unchanged (%d bytes):\n<%.*s>\n",
2245                                 msg->len, msg->len, msg->buf);
2246                         if (em_receive_request(msg, 0, 0)<0)
2247                                 ret=NONSIP_MSG_ERROR;
2248                         return ret;
2249                 }
2250         } else {
2251                 ERR("xmlrpc: bad HTTP request method: \"%.*s\"\n",
2252                         msg->first_line.u.request.method.len,
2253                         msg->first_line.u.request.method.s);
2254                 /* the message was for us, but it is an error */
2255                 return NONSIP_MSG_ERROR;
2256         }
2257         return NONSIP_MSG_PASS; /* message not for us, maybe somebody 
2258                                                                    else needs it */
2259 }
2260
2261
2262 /** The main processing function of xmlrpc module.
2263  *
2264  * This is the main function of this module. It extracts the name
2265  * of the method to be called from XML-RPC request and then it
2266  * searches through the list of all available management function,
2267  * when a function with matching name is found then it will be
2268  * executed.
2269  */
2270 static int dispatch_rpc(sip_msg_t* msg, char* s1, char* s2)
2271 {
2272         rpc_export_t* exp;
2273         int ret = 1;
2274
2275         if (init_context(&ctx, msg) < 0) goto skip;
2276
2277         exp = find_rpc_export(ctx.method, 0);
2278         if (!exp || !exp->function) {
2279                 rpc_fault(&ctx, 500, "Method Not Found");
2280                 goto skip;
2281         }
2282         ctx.flags = exp->flags;
2283         if (exp->flags & RET_ARRAY && 
2284                 add_xmlrpc_reply(&ctx.reply, &array_prefix) < 0) goto skip;
2285         exp->function(&func_param, &ctx);
2286
2287  skip:
2288              /* The function may have sent the reply itself */
2289         if (!ctx.reply_sent && !(ctx.flags&XMLRPC_DELAYED_REPLY_F)) {
2290                 ret = rpc_send(&ctx);
2291         }
2292         clean_context(&ctx);
2293         collect_garbage();
2294         if (ret < 0) return -1;
2295         else return 1;
2296 }
2297
2298
2299 /** This function can be called from SER scripts to generate
2300  * an XML-RPC reply.
2301  */
2302 static int xmlrpc_reply(sip_msg_t* msg, char* p1, char* p2)
2303 {
2304         str reason;
2305         static str succ = STR_STATIC_INIT("1");
2306         struct xmlrpc_reply reply;
2307
2308         memset(&reply, 0, sizeof(struct xmlrpc_reply));
2309         if (init_xmlrpc_reply(&reply) < 0) return -1;
2310
2311         if (get_int_fparam(&reply.code, msg, (fparam_t*)p1) < 0) return -1;
2312         if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) return -1;
2313
2314         reply.reason = as_asciiz(&reason);
2315         if (reply.reason == NULL) {
2316             ERR("No memory left\n");
2317             return -1;
2318         }
2319
2320         if (reply.code >= 300) { 
2321                 if (build_fault_reply(&reply) < 0) goto error;
2322         } else {
2323                 if (add_xmlrpc_reply(&reply, &success_prefix) < 0) goto error;
2324                 if (add_xmlrpc_reply(&reply, &int_prefix) < 0) goto error;
2325                 if (add_xmlrpc_reply_esc(&reply, &succ) < 0) goto error;
2326                 if (add_xmlrpc_reply(&reply, &int_suffix) < 0) goto error;
2327                 if (add_xmlrpc_reply(&reply, &success_suffix) < 0) return -1;
2328         }
2329         if (send_reply(msg, &reply.body) < 0) goto error;
2330         if (reply.reason) pkg_free(reply.reason);
2331         clean_xmlrpc_reply(&reply);
2332         return 1;
2333  error:
2334         if (reply.reason) pkg_free(reply.reason);
2335         clean_xmlrpc_reply(&reply);
2336         return -1;
2337 }
2338
2339
2340 /** Implementation of \@xmlrpc.method select that can be used in
2341  * SER scripts to retrieve the method string from XML-RPC documents
2342  */
2343 static int select_method(str* res, struct select* s, sip_msg_t* msg)
2344 {
2345         static char buf[1024];
2346         str doc;
2347         xmlDocPtr xmldoc;
2348         xmlNodePtr cur;
2349         char* method;
2350
2351         xmldoc = 0;
2352         method = 0;
2353
2354         if (get_rpc_document(&doc, msg) < 0) goto err;
2355         xmldoc = xmlReadMemory(doc.s, doc.len, 0, 0, 
2356                                                    XML_PARSE_NOBLANKS | 
2357                                                    XML_PARSE_NONET | 
2358                                                    XML_PARSE_NOCDATA);
2359         
2360         if (!xmldoc) goto err;
2361         cur = xmlDocGetRootElement(xmldoc);
2362         if (!cur) goto err;
2363         if (xmlStrcmp(cur->name, (const xmlChar*)"methodCall")) goto err;
2364         cur = cur->xmlChildrenNode;
2365         while(cur) {
2366                 if (!xmlStrcmp(cur->name, (const xmlChar*)"methodName")) {
2367                         method = (char*)xmlNodeListGetString(xmldoc, cur->xmlChildrenNode,
2368                                                                                                  1);
2369                         if (!method) goto err;
2370                         break;
2371                 }
2372                 cur = cur->next;
2373         }
2374         if (!cur) goto err;
2375         res->len = strlen(method);
2376         if (res->len >= 1024) goto err;
2377         memcpy(buf, method, res->len);
2378         res->s = buf;
2379         return 0;
2380  err:
2381         if (method) xmlFree(method);
2382         if (xmldoc) xmlFreeDoc(xmldoc);
2383         return -1;
2384 }
2385
2386 static ABSTRACT_F(select_xmlrpc);
2387
2388 select_row_t xmlrpc_sel[] = {
2389         { NULL,          SEL_PARAM_STR, STR_STATIC_INIT("xmlrpc"), select_xmlrpc, SEL_PARAM_EXPECTED},
2390         { select_xmlrpc, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_method, 0},
2391         { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
2392 };
2393
2394
2395 static int mod_init(void)
2396 {
2397         struct nonsip_hook nsh;
2398         int route_no;
2399         
2400         /* try to fix the xmlrpc route */
2401         if (xmlrpc_route){
2402                 route_no=route_get(&main_rt, xmlrpc_route);
2403                 if (route_no==-1){
2404                         ERR("xmlrpc: failed to fix route \"%s\": route_get() failed\n",
2405                                         xmlrpc_route);
2406                         return -1;
2407                 }
2408                 if (main_rt.rlist[route_no]==0){
2409                         WARN("xmlrpc: xmlrpc route \"%s\" is empty / doesn't exist\n",
2410                                         xmlrpc_route);
2411                 }
2412                 xmlrpc_route_no=route_no;
2413         }
2414
2415         /* bind the SL API */
2416         if (sl_load_api(&slb)!=0) {
2417                 LM_ERR("cannot bind to SL API\n");
2418                 return -1;
2419         }
2420
2421         func_param.send = (rpc_send_f)rpc_send;
2422         func_param.fault = (rpc_fault_f)rpc_fault;
2423         func_param.add = (rpc_add_f)rpc_add;
2424         func_param.scan = (rpc_scan_f)rpc_scan;
2425         func_param.printf = (rpc_printf_f)rpc_printf;
2426         func_param.struct_add = (rpc_struct_add_f)rpc_struct_add;
2427         func_param.struct_scan = (rpc_struct_scan_f)rpc_struct_scan;
2428         func_param.struct_printf = (rpc_struct_printf_f)rpc_struct_printf;
2429         func_param.capabilities = (rpc_capabilities_f)rpc_capabilities;
2430         func_param.delayed_ctx_new = (rpc_delayed_ctx_new_f)rpc_delayed_ctx_new;
2431         func_param.delayed_ctx_close =
2432                 (rpc_delayed_ctx_close_f)rpc_delayed_ctx_close;
2433         register_select_table(xmlrpc_sel);
2434         
2435         /* register non-sip hooks */
2436         if(xmlrpc_mode==0)
2437         {
2438                 memset(&nsh, 0, sizeof(nsh));
2439                 nsh.name="xmlrpc";
2440                 nsh.destroy=0;
2441                 nsh.on_nonsip_req=process_xmlrpc;
2442                 if (register_nonsip_msg_hook(&nsh)<0){
2443                         ERR("Failed to register non sip msg hooks\n");
2444                         return -1;
2445                 }
2446         }
2447         if(xmlrpc_url_match!=NULL)
2448         {
2449                 memset(&xmlrpc_url_match_regexp, 0, sizeof(regex_t));
2450                 if (regcomp(&xmlrpc_url_match_regexp, xmlrpc_url_match, REG_EXTENDED)!=0) {
2451                         LM_ERR("bad match re %s\n", xmlrpc_url_match);
2452                         return E_BAD_RE;
2453                 }
2454         }
2455         if(xmlrpc_url_skip!=NULL)
2456         {
2457                 memset(&xmlrpc_url_skip_regexp, 0, sizeof(regex_t));
2458                 if (regcomp(&xmlrpc_url_skip_regexp, xmlrpc_url_skip, REG_EXTENDED)!=0) {
2459                         LM_ERR("bad skip re %s\n", xmlrpc_url_skip);
2460                         return E_BAD_RE;
2461                 }
2462         }
2463
2464         return 0;
2465 }
2466
2467
2468 static int fixup_xmlrpc_reply(void** param, int param_no)
2469 {
2470         int ret;
2471
2472         if (param_no == 1) {
2473                 ret = fix_param(FPARAM_AVP, param);
2474                 if (ret <= 0) return ret;               
2475             if (fix_param(FPARAM_INT, param) != 0) return -1;
2476         } else if (param_no == 2) {
2477                 return fixup_var_str_12(param, 2);
2478         }
2479         return 0;
2480 }
2481
2482 /** @} */