Browse code

xhttp_rpc: new module providing a web interface for RPC management interface

Ovidiu Sas authored on 11/11/2011 23:54:15
Showing 9 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,14 @@
0
+# $Id$
1
+#
2
+# 
3
+# WARNING: do not run this directly, it should be run by the master Makefile
4
+
5
+include ../../Makefile.defs
6
+auto_gen=
7
+NAME=xhttp_rpc.so
8
+DEFS +=
9
+LIBS +=
10
+
11
+DEFS+=-DOPENSER_MOD_INTERFACE
12
+
13
+include ../../Makefile.modules
0 14
new file mode 100644
... ...
@@ -0,0 +1,165 @@
0
+xHTTP_RPC Module
1
+
2
+Ovidiu Sas
3
+
4
+   <osas@voipembedded.com>
5
+
6
+Edited by
7
+
8
+Ovidiu Sas
9
+
10
+   <osas@voipembedded.com>
11
+
12
+   Copyright © 2011 VoIPEmbedded Inc.
13
+     __________________________________________________________________
14
+
15
+   Table of Contents
16
+
17
+   1. Admin Guide
18
+
19
+        1. Overview
20
+
21
+              1.1. Limitations
22
+
23
+        2. Dependencies
24
+
25
+              2.1. Kamailio Modules
26
+              2.2. External Libraries or Applications
27
+
28
+        3. Parameters
29
+
30
+              3.1. xhttp_rpc_root (str)
31
+              3.2. xhttp_rpc_buf_size (str)
32
+
33
+        4. Functions
34
+
35
+              4.1. dispatch_xhttp_rpc()
36
+
37
+   List of Examples
38
+
39
+   1.1. Set xhttp_rpc_root parameter
40
+   1.2. Set xhttp_rpc_buf_size parameter
41
+   1.3. dispatch_xhttp_rpc usage
42
+
43
+Chapter 1. Admin Guide
44
+
45
+   Table of Contents
46
+
47
+   1. Overview
48
+
49
+        1.1. Limitations
50
+
51
+   2. Dependencies
52
+
53
+        2.1. Kamailio Modules
54
+        2.2. External Libraries or Applications
55
+
56
+   3. Parameters
57
+
58
+        3.1. xhttp_rpc_root (str)
59
+        3.2. xhttp_rpc_buf_size (str)
60
+
61
+   4. Functions
62
+
63
+        4.1. dispatch_xhttp_rpc()
64
+
65
+1. Overview
66
+
67
+   1.1. Limitations
68
+
69
+   This module provides an HTTP transport layer implementation for the RPC
70
+   management interface in a human easy readable format.
71
+
72
+   The xHTTP_RPC module uses the xHTTP module to handle HTTP requests.
73
+   Read the documentation of the xHTTP module for more details.
74
+
75
+1.1. Limitations
76
+
77
+   This module does not implement asynchronous RPC commands. It is
78
+   unlikely that asynchronous RPC commands will be executed from an RPC
79
+   web interface.
80
+
81
+   This module does not accept parameters embedded in a structure (see RPC
82
+   documentation for more info about how parameters can be passed to RPC).
83
+
84
+   At startup, all RPC commands are sorted and grouped based on their
85
+   format. The expected format is [group].[subcommand]. The initial
86
+   xhttp_rpc webpage displays all the retrieved groups. All RPC commands
87
+   are disponible as submenus of each [group]. If an RPC command is not in
88
+   the expected format, it will be dropped from the initial xhttp_rpc home
89
+   page menu.
90
+
91
+2. Dependencies
92
+
93
+   2.1. Kamailio Modules
94
+   2.2. External Libraries or Applications
95
+
96
+2.1. Kamailio Modules
97
+
98
+   The following modules must be loaded before this module:
99
+     * xhttp - xHTTP.
100
+
101
+2.2. External Libraries or Applications
102
+
103
+   The following libraries or applications must be installed before
104
+   running Kamailio with this module loaded:
105
+     * None
106
+
107
+3. Parameters
108
+
109
+   3.1. xhttp_rpc_root (str)
110
+   3.2. xhttp_rpc_buf_size (str)
111
+
112
+3.1. xhttp_rpc_root (str)
113
+
114
+   It specifies the root path for RPC http requests. The link to the RPC
115
+   web interface must be constructed using the following patern:
116
+   http://[server_IP]:[tcp_port]/[xhttp_rpc_root]
117
+
118
+   Default value is "rpc".
119
+
120
+   Example 1.1. Set xhttp_rpc_root parameter
121
+...
122
+modparam("xhttp_rpc", "xhttp_rpc_root", "http_rpc")
123
+...
124
+
125
+3.2. xhttp_rpc_buf_size (str)
126
+
127
+   It specifies the maximum length of the buffer used to write in the RPC
128
+   reply information in order to build the html response.
129
+
130
+   Default value is 0 (auto set to 1/3 of the size of the configured pkg
131
+   mem).
132
+
133
+   Example 1.2. Set xhttp_rpc_buf_size parameter
134
+...
135
+modparam("xhttp", "xhttp_rpc_buf_size", )
136
+...
137
+
138
+4. Functions
139
+
140
+   4.1. dispatch_xhttp_rpc()
141
+
142
+4.1.  dispatch_xhttp_rpc()
143
+
144
+   Handle the HTTP request and generate back a response.
145
+
146
+   Example 1.3. dispatch_xhttp_rpc usage
147
+...
148
+tcp_accept_no_cl=yes
149
+...
150
+loadmodule "sl.so"
151
+loadmodule "xhttp.so"
152
+loadmodule "xhttp_rpc.so"
153
+...
154
+modparam("xhttp_rpc", "xhttp_rpc_root", "http_rpc")
155
+...
156
+event_route[xhttp:request] {
157
+        $var(xhttp_rpc_root) = $(hu{s.substr,0,9});
158
+        if ($var(xhttp_rpc_root) == "/http_rpc")
159
+                dispatch_xhttp_rpc();
160
+        else
161
+                xhttp_reply("200", "OK", "text/html",
162
+                        "<html><body>Wrong URL $hu</body></html>");
163
+}
164
+...
0 165
new file mode 100644
... ...
@@ -0,0 +1,4 @@
0
+docs = xhttp_rpc.xml
1
+
2
+docbook_dir = ../../../docbook
3
+include $(docbook_dir)/Makefile.module
0 4
new file mode 100644
... ...
@@ -0,0 +1,37 @@
0
+<?xml version="1.0" encoding='ISO-8859-1'?>
1
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
2
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+
4
+<!-- Include general documentation entities -->
5
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
6
+%docentities;
7
+
8
+]>
9
+
10
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
11
+    <bookinfo>
12
+	<title>xHTTP_RPC Module</title>
13
+	<productname class="trade">sip-router.org</productname>
14
+	<authorgroup>
15
+	    <author>
16
+		<firstname>Ovidiu</firstname>
17
+		<surname>Sas</surname>
18
+		<email>osas@voipembedded.com</email>
19
+	    </author>
20
+	    <editor>
21
+		<firstname>Ovidiu</firstname>
22
+		<surname>Sas</surname>
23
+		<email>osas@voipembedded.com</email>
24
+	    </editor>
25
+	</authorgroup>
26
+	<copyright>
27
+	    <year>2011</year>
28
+	    <holder><ulink url='http://www.voipembedded.com'>VoIPEmbedded Inc.</ulink></holder>
29
+	</copyright>
30
+    </bookinfo>
31
+    <toc></toc>
32
+    
33
+    <xi:include href="xhttp_rpc_admin.xml"/>
34
+    
35
+    
36
+</book>
0 37
new file mode 100644
... ...
@@ -0,0 +1,162 @@
0
+<?xml version="1.0" encoding='ISO-8859-1'?>
1
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
2
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
3
+
4
+<!-- Include general documentation entities -->
5
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
6
+%docentities;
7
+
8
+]>
9
+<!-- Module User's Guide -->
10
+
11
+<chapter>
12
+	
13
+	<title>&adminguide;</title>
14
+	
15
+	<section>
16
+	<title>Overview</title>
17
+	<para>
18
+		This module provides an HTTP transport layer implementation for
19
+		the RPC management interface in a human easy readable format.
20
+	<para>
21
+	</para>
22
+		The xHTTP_RPC module uses the xHTTP module to handle HTTP requests.
23
+		Read the documentation of the xHTTP module for more details.
24
+	</para>
25
+
26
+	<section>
27
+	<title>Limitations</title>
28
+	<para>
29
+		This module does not implement asynchronous RPC commands.
30
+		It is unlikely that asynchronous RPC commands will be executed
31
+		from an RPC web interface.
32
+	</para>
33
+	<para>
34
+		This module does not accept parameters embedded in a structure
35
+		(see RPC documentation for more info about how parameters can be
36
+		passed to RPC).
37
+	</para>
38
+	<para>
39
+		At startup, all RPC commands are sorted and grouped based on
40
+		their format.  The expected format is [group].[subcommand].
41
+		The initial xhttp_rpc webpage displays all the retrieved groups.
42
+		All RPC commands are disponible as submenus of each [group].
43
+		If an RPC command is not in the expected format, it will be
44
+		dropped from the initial xhttp_rpc home page menu.
45
+	</para>
46
+	</section>
47
+	</section>
48
+
49
+	<section>
50
+	<title>Dependencies</title>
51
+	<section>
52
+		<title>&kamailio; Modules</title>
53
+		<para>
54
+		The following modules must be loaded before this module:
55
+			<itemizedlist>
56
+			<listitem>
57
+			<para>
58
+				<emphasis>xhttp</emphasis> - xHTTP.
59
+			</para>
60
+			</listitem>
61
+			</itemizedlist>
62
+		</para>
63
+	</section>
64
+	<section>
65
+		<title>External Libraries or Applications</title>
66
+		<para>
67
+		The following libraries or applications must be installed before running
68
+		&kamailio; with this module loaded:
69
+			<itemizedlist>
70
+			<listitem>
71
+			<para>
72
+				<emphasis>None</emphasis>
73
+			</para>
74
+			</listitem>
75
+			</itemizedlist>
76
+		</para>
77
+	</section>
78
+	</section>
79
+	<section>
80
+	<title>Parameters</title>
81
+	<section>
82
+		<title><varname>xhttp_rpc_root</varname> (str)</title>
83
+		<para>
84
+			It specifies the root path for RPC http requests.
85
+			The link to the RPC web interface must be constructed
86
+			using the following patern:
87
+			http://[server_IP]:[tcp_port]/[xhttp_rpc_root] 
88
+		</para>
89
+		<para>
90
+		<emphasis>
91
+			Default value is "rpc".
92
+		</emphasis>
93
+		</para>
94
+		<example>
95
+		<title>Set <varname>xhttp_rpc_root</varname> parameter</title>
96
+		<programlisting format="linespecific">
97
+...
98
+modparam("xhttp_rpc", "xhttp_rpc_root", "http_rpc")
99
+...
100
+</programlisting>
101
+		</example>
102
+	</section>
103
+	<section>
104
+		<title><varname>xhttp_rpc_buf_size</varname> (str)</title>
105
+		<para>
106
+			It specifies the maximum length of the buffer used
107
+			to write in the RPC reply information in order to
108
+			build the html response.
109
+		</para>
110
+		<para>
111
+		<emphasis>
112
+			Default value is 0 (auto set to 1/3 of the size of the configured pkg mem).
113
+		</emphasis>
114
+		</para>
115
+		<example>
116
+		<title>Set <varname>xhttp_rpc_buf_size</varname> parameter</title>
117
+		<programlisting format="linespecific">
118
+...
119
+modparam("xhttp", "xhttp_rpc_buf_size", )
120
+...
121
+</programlisting>
122
+		</example>
123
+	</section>
124
+	</section>
125
+
126
+	<section>
127
+	<title>Functions</title>
128
+ 	<section>
129
+	    <title>
130
+		<function moreinfo="none">dispatch_xhttp_rpc()</function>
131
+	    </title>
132
+	    <para>
133
+		Handle the HTTP request and generate back a response.
134
+	    </para>
135
+		<example>
136
+		<title><function>dispatch_xhttp_rpc</function> usage</title>
137
+		<programlisting format="linespecific">
138
+...
139
+tcp_accept_no_cl=yes
140
+...
141
+loadmodule "sl.so"
142
+loadmodule "xhttp.so"
143
+loadmodule "xhttp_rpc.so"
144
+...
145
+modparam("xhttp_rpc", "xhttp_rpc_root", "http_rpc")
146
+...
147
+event_route[xhttp:request] {
148
+	$var(xhttp_rpc_root) = $(hu{s.substr,0,9});
149
+	if ($var(xhttp_rpc_root) == "/http_rpc")
150
+		dispatch_xhttp_rpc();
151
+	else
152
+		xhttp_reply("200", "OK", "text/html",
153
+        		"&lt;html&gt;&lt;body&gt;Wrong URL $hu&lt;/body&gt;&lt;/html&gt;");
154
+}
155
+...
156
+</programlisting>
157
+	    </example>
158
+	</section>
159
+	</section>
160
+</chapter>
161
+
0 162
new file mode 100644
... ...
@@ -0,0 +1,816 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2011 VoIP Embedded, Inc.
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * 2011-11-11  initial version (osas)
22
+ */
23
+
24
+#include <string.h>
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+#include <stdarg.h>
28
+
29
+#include "../../ver.h"
30
+#include "../../trim.h"
31
+#include "../../sr_module.h"
32
+#include "../../nonsip_hooks.h"
33
+#include "../../modules/xhttp/api.h"
34
+#include "xhttp_rpc.h"
35
+#include "xhttp_rpc_fnc.h"
36
+
37
+/** @addtogroup xhttp_rpc
38
+ * @ingroup modules
39
+ * @{
40
+ *
41
+ * <h1>Overview of Operation</h1>
42
+ * This module provides a web interface for RPC management interface.
43
+ * It is built on top of the xhttp API module.
44
+ */
45
+
46
+/** @file
47
+ *
48
+ * This is the main file of xhttp_rpc module which contains all the functions
49
+ * related to http processing, as well as the module interface.
50
+ */
51
+
52
+MODULE_VERSION
53
+
54
+str XHTTP_RPC_REASON_OK = str_init("OK");
55
+str XHTTP_RPC_CONTENT_TYPE_TEXT_HTML = str_init("text/html");
56
+
57
+
58
+xhttp_rpc_mod_cmds_t *xhttp_rpc_mod_cmds = NULL;
59
+int xhttp_rpc_mod_cmds_size = 0;
60
+
61
+/* FIXME: this should be initialized in ../../ver.c */
62
+int full_version_len;
63
+int ver_name_len;
64
+
65
+static int mod_init(void);
66
+static int child_init(int rank);
67
+static int xhttp_rpc_dispatch(sip_msg_t* msg, char* s1, char* s2);
68
+
69
+
70
+/** The context of the xhttp_rpc request being processed.
71
+ *
72
+ * This is a global variable that records the context of the xhttp_rpc request
73
+ * being currently processed.
74
+ * @sa rpc_ctx
75
+ */
76
+static rpc_ctx_t ctx;
77
+
78
+static xhttp_api_t xhttp_api;
79
+
80
+/** Pointers to the functions that implement the RPC interface
81
+ * of xhttp_rpc module
82
+ */
83
+static rpc_t func_param;
84
+
85
+str xhttp_rpc_root = str_init("rpc");
86
+int buf_size = 0;
87
+char error_buf[ERROR_REASON_BUF_LEN];
88
+
89
+static cmd_export_t cmds[] = {
90
+	{"dispatch_xhttp_rpc",(cmd_function)xhttp_rpc_dispatch,0,0,0,REQUEST_ROUTE},
91
+	{0, 0, 0, 0, 0, 0}
92
+};
93
+
94
+static param_export_t params[] = {
95
+	{"xhttp_rpc_root",	STR_PARAM,	&xhttp_rpc_root.s},
96
+	{"xhttp_rpc_buf_size",	INT_PARAM,	&buf_size},
97
+	{0, 0, 0}
98
+};
99
+
100
+/** module exports */
101
+struct module_exports exports= {
102
+	"xhttp_rpc",
103
+	DEFAULT_DLFLAGS, /* dlopen flags */
104
+	cmds,
105
+	params,
106
+	0,		/* exported statistics */
107
+	0,		/* exported MI functions */
108
+	0,		/* exported pseudo-variables */
109
+	0,		/* extra processes */
110
+	mod_init,	/* module initialization function */
111
+	0,
112
+	0,
113
+	child_init	/* per-child init function */
114
+};
115
+
116
+
117
+/** Implementation of rpc_fault function required by the management API.
118
+ *
119
+ * This function will be called whenever a management function
120
+ * indicates that an error ocurred while it was processing the request. The
121
+ * function takes the reply code and reason phrase as parameters, these will
122
+ * be put in the body of the reply.
123
+ *
124
+ * @param ctx A pointer to the context structure of the request being
125
+ *            processed.
126
+ * @param code Reason code.
127
+ * @param fmt Formatting string used to build the reason phrase.
128
+ */
129
+static void rpc_fault(rpc_ctx_t* ctx, int code, char* fmt, ...)
130
+{
131
+	va_list ap;
132
+	struct xhttp_rpc_reply *reply = &ctx->reply;
133
+
134
+	reply->code = code;
135
+	va_start(ap, fmt);
136
+	vsnprintf(error_buf, ERROR_REASON_BUF_LEN, fmt, ap);
137
+	va_end(ap);
138
+	reply->reason.len = strlen(error_buf);
139
+	reply->reason.s = error_buf;
140
+	/* reset body so we can print the error */
141
+	reply->body.len = 0;
142
+
143
+	return;
144
+}
145
+
146
+
147
+/**
148
+ */
149
+static void free_data_struct(struct rpc_data_struct *rpc_d)
150
+{
151
+	struct rpc_data_struct *ds;
152
+
153
+	if (!rpc_d) {
154
+		LM_ERR("Atempting to free NULL rpc_data_struct\n");
155
+		return;
156
+	}
157
+	while (rpc_d) {
158
+		ds = rpc_d->next;
159
+		pkg_free(rpc_d);
160
+		rpc_d = ds;
161
+	}
162
+	return;
163
+}
164
+
165
+
166
+/**
167
+ */
168
+static struct rpc_data_struct *new_data_struct(rpc_ctx_t* ctx)
169
+{
170
+	struct rpc_data_struct *ds;
171
+
172
+	if (!ctx) return NULL;
173
+	ds = (struct rpc_data_struct*)pkg_malloc(sizeof(struct rpc_data_struct));
174
+	if (!ds) {
175
+		rpc_fault(ctx, 500, "Internal Server Error (oom)");
176
+		return NULL;
177
+	}
178
+	memset(ds, 0, sizeof(struct rpc_data_struct));
179
+	ds->ctx = ctx;
180
+
181
+	return ds;
182
+}
183
+
184
+
185
+/** Initialize xhttp_rpc reply data structure.
186
+ *
187
+ * This function initializes the data structure that contains all data related
188
+ * to the xhttp_rpc reply being created. The function must be called before any
189
+ * other function that adds data to the reply.
190
+ * @param ctx rpc_ctx_t structure to be initialized.
191
+ * @return 0 on success, a negative number on error.
192
+ */
193
+static int init_xhttp_rpc_reply(rpc_ctx_t *ctx)
194
+{
195
+	struct xhttp_rpc_reply *reply = &ctx->reply;
196
+
197
+	reply->code = 200;
198
+	reply->reason = XHTTP_RPC_REASON_OK;
199
+	reply->buf.s = pkg_malloc(buf_size);
200
+	if (!reply->buf.s) {
201
+		LM_ERR("oom\n");
202
+		rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
203
+		return -1;
204
+	}
205
+	reply->buf.len = buf_size;
206
+	reply->body.s = reply->buf.s;
207
+	reply->body.len = 0;
208
+	return 0;
209
+}
210
+
211
+
212
+/** Implementation of rpc_send function required by the management API.
213
+ *
214
+ * This is the function that will be called whenever a management function
215
+ * asks the management interface to send the reply to the client.
216
+ * The SIP/HTTP reply sent to
217
+ * the client will be always 200 OK, if an error ocurred on the server then it
218
+ * will be indicated in the html document in body.
219
+ *
220
+ * @param ctx A pointer to the context structure of the xhttp_rpc request that
221
+ *            generated the reply.
222
+ * @return 1 if the reply was already sent, 0 on success, a negative number on
223
+ *            error
224
+ */
225
+static int rpc_send(rpc_ctx_t* ctx)
226
+{
227
+	struct xhttp_rpc_reply* reply;
228
+
229
+	if (ctx->reply_sent) return 1;
230
+
231
+	reply = &ctx->reply;
232
+
233
+	if (0!=xhttp_rpc_build_page(ctx)){
234
+		rpc_fault(ctx, 500, "Internal Server Error");
235
+	}
236
+
237
+	ctx->reply_sent = 1;
238
+	if (reply->body.len)
239
+		xhttp_api.reply(ctx->msg, reply->code, &reply->reason,
240
+			&XHTTP_RPC_CONTENT_TYPE_TEXT_HTML, &reply->body);
241
+	else
242
+		xhttp_api.reply(ctx->msg, reply->code, &reply->reason,
243
+			&XHTTP_RPC_CONTENT_TYPE_TEXT_HTML, &reply->reason);
244
+
245
+	if (reply->buf.s) {
246
+		pkg_free(reply->buf.s);
247
+		reply->buf.s = NULL;
248
+		reply->buf.len = 0;
249
+	}
250
+	if (ctx->arg.s) {
251
+		pkg_free(ctx->arg.s);
252
+		ctx->arg.s = NULL;
253
+		ctx->arg.len = 0;
254
+	}
255
+	if (ctx->data_structs) {
256
+		free_data_struct(ctx->data_structs);
257
+		ctx->data_structs = NULL;
258
+	}
259
+
260
+	return 0;
261
+}
262
+
263
+
264
+/** Converts the variables provided in parameter ap according to formatting
265
+ * string provided in parameter fmt into HTML format.
266
+ *
267
+ * This function takes the parameters provided in ap parameter and creates
268
+ * HTML formatted parameters that will be put in the html document.
269
+ * The format of input parameters is described in formatting string
270
+ * fmt which follows the syntax of the management API. In the case of
271
+ * an error the function will generate an error reply in err_reply parameter
272
+ * instead.
273
+ * @param ctx An error reply document will be generated here if the
274
+ *                  function encounters a problem while processing input
275
+ *                  parameters.
276
+ * @param fmt Formatting string of the management API.
277
+ * @param ap A pointer to the array of input parameters.
278
+ *
279
+ */
280
+static int print_value(rpc_ctx_t* ctx, char fmt, va_list* ap, str *id)
281
+
282
+{
283
+	str body;
284
+	str *sp;
285
+	char buf[PRINT_VALUE_BUF_LEN];
286
+	time_t dt;
287
+	struct tm* t;
288
+
289
+	switch(fmt) {
290
+	case 'd':
291
+		body.s = sint2str(va_arg(*ap, int), &body.len);
292
+		break;
293
+	case 'f':
294
+		body.s = buf;
295
+		body.len = snprintf(buf, PRINT_VALUE_BUF_LEN,
296
+				"%f", va_arg(*ap, double));
297
+		if (body.len < 0) {
298
+			LM_ERR("Error while converting double\n");
299
+			return -1;
300
+		}
301
+		break;
302
+	case 'b':
303
+		body.len = 1;
304
+		body.s = ((va_arg(*ap, int)==0)?"0":"1");
305
+		break;
306
+	case 't':
307
+		body.s = buf;
308
+		body.len = sizeof("19980717T14:08:55") - 1;
309
+		dt = va_arg(*ap, time_t);
310
+		t = gmtime(&dt);
311
+		if (strftime(buf, PRINT_VALUE_BUF_LEN,
312
+				"%Y%m%dT%H:%M:%S", t) == 0) {
313
+			LM_ERR("Error while converting time\n");
314
+			return -1;
315
+		}
316
+		break;
317
+	case 's':
318
+		body.s = va_arg(*ap, char*);
319
+		body.len = strlen(body.s);
320
+		break;
321
+	case 'S':
322
+		sp = va_arg(*ap, str*);
323
+		body = *sp;
324
+		break;
325
+	default:
326
+		body.len = 0;
327
+		body.s = NULL;
328
+		LM_ERR("Invalid formatting character [%c]\n", fmt);
329
+		return -1;
330
+	}
331
+	if (0!=xhttp_rpc_build_content(ctx, &body, id)) {
332
+		rpc_fault(ctx, 500, "Internal Server Error");
333
+		return -1;
334
+	}
335
+	return 0;
336
+}
337
+
338
+
339
+/** Implementation of rpc_add function required by the management API.
340
+ *
341
+ * This function will be called when an RPC management function calls
342
+ * rpc->add to add a parameter to the xhttp_rpc reply being generated.
343
+ */
344
+static int rpc_add(rpc_ctx_t* ctx, char* fmt, ...)
345
+{
346
+	void **void_ptr;
347
+	struct rpc_data_struct *ds;
348
+	va_list ap;
349
+
350
+	if (0!=xhttp_rpc_build_content(ctx, NULL, NULL)) {
351
+		rpc_fault(ctx, 500, "Internal Server Error");
352
+		return -1;
353
+	}
354
+	va_start(ap, fmt);
355
+	while(*fmt) {
356
+		if (*fmt == '{') {
357
+			void_ptr = va_arg(ap, void**);
358
+			ds = new_data_struct(ctx);
359
+			if (!ds) goto err;
360
+			if (ctx->data_structs) free_data_struct(ctx->data_structs);
361
+			ctx->data_structs = ds;
362
+			*void_ptr = ds;
363
+		} else {
364
+			if (print_value(ctx, *fmt, &ap, NULL) < 0) goto err;
365
+		}
366
+		fmt++;
367
+	}
368
+	va_end(ap);
369
+	return 0;
370
+err:
371
+	va_end(ap);
372
+	return -1;
373
+}
374
+
375
+
376
+/** Implementation of rpc->scan function required by the management API.
377
+ *
378
+ * This is the function that will be called whenever a management function
379
+ * calls rpc->scan to get the value of parameter from the xhttp_rpc
380
+ * request. This function will extract the current parameter from the xhttp_rpc
381
+ * URL and attempts to convert it to the type requested by the management
382
+ * function that called it.
383
+ */
384
+static int rpc_scan(rpc_ctx_t* ctx, char* fmt, ...)
385
+{
386
+	int *int_ptr;
387
+	char **char_ptr;
388
+	double *double_ptr;
389
+	str *str_ptr;
390
+
391
+	str arg;
392
+
393
+	int mandatory_param = 1;
394
+	int modifiers = 0;
395
+	char* orig_fmt;
396
+	va_list ap;
397
+
398
+	orig_fmt=fmt;
399
+	va_start(ap, fmt);
400
+	while(*fmt) {
401
+		switch(*fmt) {
402
+		case '*': /* start of optional parameters */
403
+			mandatory_param = 0;
404
+			modifiers++;
405
+			fmt++;
406
+			continue;
407
+			break;
408
+		case '.': /* autoconvert */
409
+			modifiers++;
410
+			fmt++;
411
+			continue;
412
+			break;
413
+		case 'b': /* Bool */
414
+		case 't': /* Date and time */
415
+		case 'd': /* Integer */
416
+			xhttp_rpc_get_next_arg(ctx, &arg);
417
+			if (arg.len==0)
418
+				goto read_error;
419
+			int_ptr = va_arg(ap, int*);
420
+			*int_ptr = strtol(arg.s, 0, 0);
421
+			break;
422
+		case 'f': /* double */
423
+			xhttp_rpc_get_next_arg(ctx, &arg);
424
+			if (arg.len==0)
425
+				goto read_error;
426
+			double_ptr = va_arg(ap, double*);
427
+			*double_ptr = strtod(arg.s, 0);
428
+			break;
429
+		case 's': /* zero terminated string */
430
+			xhttp_rpc_get_next_arg(ctx, &arg);
431
+			if (arg.len==0)
432
+				goto read_error;
433
+			char_ptr = va_arg(ap, char**);
434
+			*char_ptr = arg.s;
435
+			break;
436
+		case 'S': /* str structure */
437
+			xhttp_rpc_get_next_arg(ctx, &arg);
438
+			if (arg.len==0)
439
+				goto read_error;
440
+			str_ptr = va_arg(ap, str*);
441
+			*str_ptr = arg;
442
+			break;
443
+		case '{':
444
+			xhttp_rpc_get_next_arg(ctx, &arg);
445
+			if (arg.len==0)
446
+				goto read_error;
447
+			LM_ERR("Unsupported param type [{]\n");
448
+			rpc_fault(ctx, 500, "Unsupported param type [{]");
449
+			goto error;
450
+			break;
451
+		default:
452
+			LM_ERR("Invalid param type in formatting string: [%c]\n", *fmt);
453
+			rpc_fault(ctx, 500,
454
+				"Internal Server Error (inval formatting str)");
455
+			goto error;
456
+		}
457
+		fmt++;
458
+	}
459
+	va_end(ap);
460
+	return (int)(fmt-orig_fmt)-modifiers;
461
+read_error:
462
+	if (mandatory_param) rpc_fault(ctx, 400, "Invalid parameter value");
463
+error:
464
+	va_end(ap);
465
+	return -((int)(fmt-orig_fmt)-modifiers);
466
+}
467
+
468
+
469
+/** Implementation of rpc_printf function required by the management API.
470
+ *
471
+ * This function will be called whenever an RPC management function calls
472
+ * rpc-printf to add a parameter to the xhttp_rpc reply being constructed.
473
+ */
474
+static int rpc_printf(rpc_ctx_t* ctx, char* fmt, ...)
475
+{
476
+	int n, size;
477
+	char *p;
478
+	va_list ap;
479
+
480
+	if (0!=xhttp_rpc_build_content(ctx, NULL, NULL)) {
481
+		rpc_fault(ctx, 500, "Internal Server Error");
482
+		return -1;
483
+	}
484
+
485
+	p = ctx->reply.body.s + ctx->reply.body.len;
486
+	size = ctx->reply.buf.len - ctx->reply.body.len;
487
+	va_start(ap, fmt);
488
+	n = vsnprintf(p, size, fmt, ap);
489
+	va_end(ap);
490
+	if (n > -1 && n < size) {
491
+		ctx->reply.body.len += n;
492
+		p += n;
493
+	} else {
494
+		LM_ERR("oom\n");
495
+		rpc_fault(ctx, 500, "Internal Server Error (oom)");
496
+		return -1;
497
+	}
498
+	if (0!=xhttp_rpc_insert_break(ctx)) {
499
+		LM_ERR("oom\n");
500
+		rpc_fault(ctx, 500, "Internal Server Error (oom)");
501
+		return -1;
502
+	}
503
+
504
+	return 0;
505
+}
506
+
507
+
508
+/** Adds a new member to structure.
509
+ */
510
+static int rpc_struct_add(struct rpc_data_struct* rpc_s, char* fmt, ...)
511
+{
512
+	va_list ap;
513
+	void **void_ptr;
514
+	str member_name;
515
+	rpc_ctx_t *ctx = rpc_s->ctx;
516
+	struct rpc_data_struct *ds, *s;
517
+
518
+	if (!ctx) {
519
+		LM_ERR("Invalid context\n");
520
+		return -1;
521
+	}
522
+	if (!ctx->data_structs) {
523
+		LM_ERR("Invalid structs\n");
524
+		return -1;
525
+	}
526
+	s = ds = ctx->data_structs;
527
+	ctx->struc_depth = 0;
528
+	while (s) {
529
+		if (s == rpc_s) {
530
+			if (s->next) {
531
+				free_data_struct(s->next);
532
+				s->next = NULL;
533
+			}
534
+			break;
535
+		}
536
+		ctx->struc_depth++;
537
+		ds = s;
538
+		s = s->next;
539
+	}
540
+	if (!s)
541
+		s = ds;
542
+	va_start(ap, fmt);
543
+	while(*fmt) {
544
+		member_name.s = va_arg(ap, char*);
545
+		member_name.len = (member_name.s?strlen(member_name.s):0);
546
+		if (*fmt == '{') {
547
+			void_ptr = va_arg(ap, void**);
548
+			ds = new_data_struct(ctx);
549
+			if (!ds) goto err;
550
+			s->next = ds;
551
+			*void_ptr = ds;
552
+			if (0!=xhttp_rpc_build_content(ctx, NULL, &member_name))
553
+				goto err;
554
+		} else {
555
+			if (print_value(ctx, *fmt, &ap, &member_name) < 0) goto err;
556
+		}
557
+		fmt++;
558
+	}
559
+	va_end(ap);
560
+	return 0;
561
+err:
562
+	va_end(ap);
563
+	return -1;
564
+}
565
+
566
+
567
+static int rpc_struct_scan(void* s, char* fmt, ...)
568
+{
569
+	LM_ERR("Not implemented\n");
570
+	return -1;
571
+}
572
+
573
+
574
+/** Create a new member from formatting string and add it to a structure.
575
+ */
576
+static int rpc_struct_printf(void* s, char* member_name, char* fmt, ...)
577
+{
578
+	LM_ERR("Not implemented\n");
579
+	return -1;
580
+}
581
+
582
+
583
+/** Returns the RPC capabilities supported by the xmlrpc driver.
584
+ */
585
+static rpc_capabilities_t rpc_capabilities(rpc_ctx_t* ctx)
586
+{
587
+	/* No support for async commands.
588
+	 */
589
+	return 0;
590
+}
591
+
592
+
593
+/** Returns a new "delayed reply" context.
594
+ * Creates a new delayed reply context in shm and returns it.
595
+ * @return 0 - not supported, already replied, or no more memory;
596
+ *         !=0 pointer to the special delayed ctx.
597
+ * Note1: one should use the returned ctx reply context to build a reply and
598
+ *  when finished call rpc_delayed_ctx_close().
599
+ * Note2: adding pieces to the reply in different processes is not supported.
600
+ */
601
+static struct rpc_delayed_ctx* rpc_delayed_ctx_new(rpc_ctx_t* ctx)
602
+{
603
+	return NULL;
604
+}
605
+
606
+
607
+/** Closes a "delayed reply" context and sends the reply.
608
+ * If no reply has been sent the reply will be built and sent automatically.
609
+ * See the notes from rpc_new_delayed_ctx()
610
+ */
611
+static void rpc_delayed_ctx_close(struct rpc_delayed_ctx* dctx)
612
+{
613
+	return;
614
+}
615
+
616
+
617
+static int mod_init(void)
618
+{
619
+	int i;
620
+
621
+	/* bind the XHTTP API */
622
+	if (xhttp_load_api(&xhttp_api) < 0) {
623
+		LM_ERR("cannot bind to XHTTP API\n");
624
+		return -1;
625
+	}
626
+
627
+	/* Check xhttp_rpc_buf_size param */
628
+	if (buf_size == 0)
629
+		buf_size = pkg_mem_size/3;
630
+
631
+	/* Check xhttp_rpc_root param */
632
+	xhttp_rpc_root.len = strlen(xhttp_rpc_root.s);
633
+	for(i=0;i<xhttp_rpc_root.len;i++){
634
+		if ( !isalnum(xhttp_rpc_root.s[i]) && xhttp_rpc_root.s[i]!='_') {
635
+			LM_ERR("bad xhttp_rpc_root param [%.*s], char [%c] "
636
+				"- use only alphanumerical chars\n",
637
+				xhttp_rpc_root.len, xhttp_rpc_root.s,
638
+				xhttp_rpc_root.s[i]);
639
+			return -1;
640
+		}
641
+	}
642
+
643
+	func_param.send = (rpc_send_f)rpc_send;
644
+	func_param.fault = (rpc_fault_f)rpc_fault;
645
+	func_param.add = (rpc_add_f)rpc_add;
646
+	func_param.scan = (rpc_scan_f)rpc_scan;
647
+	func_param.printf = (rpc_printf_f)rpc_printf;
648
+	func_param.struct_add = (rpc_struct_add_f)rpc_struct_add;
649
+	func_param.struct_scan = (rpc_struct_scan_f)rpc_struct_scan;
650
+	func_param.struct_printf = (rpc_struct_printf_f)rpc_struct_printf;
651
+	func_param.capabilities = (rpc_capabilities_f)rpc_capabilities;
652
+	func_param.delayed_ctx_new = (rpc_delayed_ctx_new_f)rpc_delayed_ctx_new;
653
+	func_param.delayed_ctx_close =
654
+		(rpc_delayed_ctx_close_f)rpc_delayed_ctx_close;
655
+
656
+	return 0;
657
+}
658
+
659
+static int child_init(int rank)
660
+{
661
+	int i, j;
662
+	int len;
663
+	xhttp_rpc_mod_cmds_t *cmds;
664
+	/* rpc_export_t *rpc_e; */
665
+
666
+	if(rank==PROC_MAIN || rank==PROC_TCP_MAIN)
667
+		return 0; /* do nothing for the main process */
668
+
669
+	if (rank==PROC_INIT)
670
+	{
671
+		/* building a cache of rpc module commands */
672
+		xhttp_rpc_mod_cmds =
673
+			(xhttp_rpc_mod_cmds_t*)pkg_malloc(sizeof(xhttp_rpc_mod_cmds_t));
674
+		if (xhttp_rpc_mod_cmds==NULL){
675
+			LM_ERR("oom\n");
676
+			return -1;
677
+		}
678
+		xhttp_rpc_mod_cmds->rpc_e_index = 0;
679
+		xhttp_rpc_mod_cmds->mod.s = NULL;
680
+		xhttp_rpc_mod_cmds->mod.len = 0;
681
+		xhttp_rpc_mod_cmds->size = 0;
682
+		xhttp_rpc_mod_cmds_size = 1;
683
+		cmds = xhttp_rpc_mod_cmds;
684
+		for(i=0; i<rpc_sarray_crt_size; i++){
685
+			len = strlen(rpc_sarray[i]->name);
686
+			j = 0;
687
+			while (j<len && rpc_sarray[i]->name[j]!='.')
688
+				j++;
689
+			if (j==len) {
690
+				LM_DBG("dropping invalid command format [%.*s]\n",
691
+						len, rpc_sarray[i]->name);
692
+			} else {
693
+				if (cmds->mod.len==0) {
694
+					/* this is the first module */
695
+					cmds->rpc_e_index = i;
696
+					cmds->mod.s = (char*)&rpc_sarray[i]->name[0];
697
+					cmds->mod.len = j;
698
+					cmds->size++;
699
+				} else if (cmds->mod.len==j &&
700
+					strncmp(cmds->mod.s,
701
+						(char*)&rpc_sarray[i]->name[0],
702
+						j)==0){
703
+					cmds->size++;
704
+				} else {
705
+					cmds = (xhttp_rpc_mod_cmds_t*)
706
+						pkg_realloc(xhttp_rpc_mod_cmds,
707
+							(xhttp_rpc_mod_cmds_size+1)*
708
+							sizeof(xhttp_rpc_mod_cmds_t));
709
+					if (cmds==NULL){
710
+						LM_ERR("oom\n");
711
+						return -1;
712
+					}
713
+					xhttp_rpc_mod_cmds = cmds;
714
+					cmds = &xhttp_rpc_mod_cmds[xhttp_rpc_mod_cmds_size];
715
+					cmds->rpc_e_index = i;
716
+					cmds->mod.s = (char*)&rpc_sarray[i]->name[0];
717
+					cmds->mod.len = j;
718
+					xhttp_rpc_mod_cmds_size++;
719
+					cmds->size = 1;
720
+				}
721
+			}
722
+		}
723
+		/*
724
+		for(i=0; i<xhttp_rpc_mod_cmds_size; i++){
725
+			for (j=0; j<xhttp_rpc_mod_cmds[i].size; j++){
726
+				rpc_e = rpc_sarray[xhttp_rpc_mod_cmds[i].rpc_e_index+j];
727
+				LM_DBG("[%p] => [%p]->[%.*s] [%p]->[%s]\n",
728
+					rpc_e,
729
+					xhttp_rpc_mod_cmds[i].mod.s,
730
+					xhttp_rpc_mod_cmds[i].mod.len,
731
+					xhttp_rpc_mod_cmds[i].mod.s,
732
+					rpc_e->name,
733
+					rpc_e->name);
734
+			}
735
+		}
736
+		*/
737
+	}
738
+
739
+	full_version_len = strlen(full_version);
740
+	ver_name_len = strlen(ver_name);
741
+	return 0;
742
+}
743
+
744
+
745
+static int xhttp_rpc_dispatch(sip_msg_t* msg, char* s1, char* s2)
746
+{
747
+	rpc_export_t* rpc_e;
748
+	str arg = {NULL, 0};
749
+	int ret = 0;
750
+	int i;
751
+
752
+	if(!IS_HTTP(msg)) {
753
+		LM_DBG("Got non HTTP msg\n");
754
+		return NONSIP_MSG_PASS;
755
+	}
756
+
757
+	/* Init xhttp_rpc context */
758
+	if (ctx.reply.buf.s) LM_ERR("Unexpected buf value [%p][%d]\n",
759
+				ctx.reply.buf.s, ctx.reply.buf.len);
760
+	memset(&ctx, 0, sizeof(rpc_ctx_t));
761
+	ctx.msg = msg;
762
+	ctx.mod = ctx.cmd = -1;
763
+	if (init_xhttp_rpc_reply(&ctx) < 0) goto send_reply;
764
+
765
+	/* Extract arguments from url */
766
+	if (0!=xhttp_rpc_parse_url(&msg->first_line.u.request.uri,
767
+				&ctx.mod, &ctx.cmd, &arg)){
768
+		rpc_fault(&ctx, 500, "Bad URL");
769
+		goto send_reply;
770
+	}
771
+
772
+	if (arg.s) {
773
+		if (arg.len) {
774
+			/* Unescape args */
775
+			ctx.arg.s = pkg_malloc((arg.len+1)*sizeof(char));
776
+			if (ctx.arg.s==NULL){
777
+				LM_ERR("oom\n");
778
+				rpc_fault(&ctx, 500, "Internal Server Error (oom)");
779
+				goto send_reply;
780
+			}
781
+			for(i=0;i<arg.len;i++) if (arg.s[i]=='+') arg.s[i]=' ';
782
+			if (0>un_escape(&arg, &ctx.arg)) {
783
+				LM_ERR("unable to escape [%.*s]\n", arg.len, arg.s);
784
+				rpc_fault(&ctx, 500, "Bad arg in URL");
785
+				goto send_reply;
786
+			}
787
+			ctx.arg.s[ctx.arg.len] = '\0';
788
+			ctx.arg.len++;
789
+			ctx.arg2scan = ctx.arg;
790
+		}
791
+		ctx.arg_received = 1;
792
+	} else {
793
+		goto send_reply;
794
+	}
795
+	
796
+	/*
797
+	rpc_e=find_rpc_export((char*)rpc_sarray[xhttp_rpc_mod_cmds[ctx.mod].rpc_e_index+ctx.cmd]->name, 0);
798
+	if ((rpc_e==NULL) || (rpc_e->function==NULL)){
799
+		LM_ERR("Unable to find rpc command [%s]\n",
800
+		rpc_sarray[xhttp_rpc_mod_cmds[ctx.mod].rpc_e_index+ctx.cmd]->name);
801
+		rpc_fault(&ctx, 500, "Method not found");
802
+		goto send_reply;
803
+	}
804
+	*/
805
+	rpc_e=rpc_sarray[xhttp_rpc_mod_cmds[ctx.mod].rpc_e_index+ctx.cmd];
806
+	rpc_e->function(&func_param, &ctx);
807
+
808
+send_reply:
809
+	if (!ctx.reply_sent) {
810
+		ret = rpc_send(&ctx);
811
+	}
812
+	if (ret < 0) return -1;
813
+	return 0;
814
+}
815
+
0 816
new file mode 100644
... ...
@@ -0,0 +1,94 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2011 VoIP Embedded, Inc.
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * 2011-11-11  initial version (osas)
22
+ */
23
+
24
+
25
+#ifndef _XHTTP_RPC_H
26
+#define _XHTTP_RPC_H
27
+
28
+#include "../../str.h"
29
+#include "../../rpc_lookup.h"
30
+#include "../../parser/msg_parser.h"
31
+
32
+
33
+#define ERROR_REASON_BUF_LEN 1024
34
+#define PRINT_VALUE_BUF_LEN 256
35
+
36
+
37
+
38
+struct rpc_data_struct {
39
+	struct rpc_ctx* ctx;
40
+	struct rpc_data_struct* next;
41
+};
42
+
43
+
44
+/** Representation of the xhttp_rpc reply being constructed.
45
+ *
46
+ * This data structure describes the xhttp_rpc reply that is being constructed
47
+ * and will be sent to the client.
48
+ */
49
+struct xhttp_rpc_reply {
50
+	int code;	/**< Reply code which indicates the type of the reply */
51
+	str reason;	/**< Reason phrase text which provides human-readable
52
+			 * description that augments the reply code */
53
+	str body;	/**< The xhttp_rpc http body built so far */
54
+	str buf;	/**< The memory buffer allocated for the reply, this is
55
+			 * where the body attribute of the structure points to */
56
+};
57
+
58
+
59
+/** The context of the xhttp_rpc request being processed.
60
+ *
61
+ * This is the data structure that contains all data related to the xhttp_rpc
62
+ * request being processed, such as the reply code and reason, data to be sent
63
+ * to the client in the reply, and so on.
64
+ *
65
+ * There is always one context per xhttp_rpc request.
66
+ */
67
+typedef struct rpc_ctx {
68
+	sip_msg_t* msg;			/**< The SIP/HTTP received message. */
69
+	struct xhttp_rpc_reply reply;	/**< xhttp_rpc reply to be sent to the client */
70
+	int reply_sent;
71
+	int mod;			/**< Module being processed */
72
+	int cmd;			/**< RPC command being processed */
73
+	int arg_received;		/**< RPC argument flag */
74
+	str arg;			/**< RPC command argument */
75
+	str arg2scan;			/**< RPC command args to be parsed */
76
+	struct rpc_struct *structs;
77
+	struct rpc_data_struct *data_structs;
78
+	unsigned int struc_depth;
79
+} rpc_ctx_t;
80
+
81
+
82
+/* An RPC module representation.
83
+ *
84
+ * The module is the first substring of the RPC commands (delimited by '.'.
85
+ */
86
+typedef struct xhttp_rpc_mod_cmds_ {
87
+	int rpc_e_index;	/**< Index to the first module RPC rec in rpc_sarray */
88
+	str mod;		/**< Module name */
89
+	int size;		/**< Number of commands provided by the above module */
90
+} xhttp_rpc_mod_cmds_t;
91
+
92
+#endif
93
+
0 94
new file mode 100644
... ...
@@ -0,0 +1,621 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2011 VoIP Embedded, Inc.
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * Kamailio is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * Kamailio is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU General Public License
18
+ * along with this program; if not, write to the Free Software
19
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
+ *
21
+ * 2011-11-11  initial version (osas)
22
+ */
23
+
24
+#include <string.h>
25
+#include <stdlib.h>
26
+#include <stdio.h>
27
+#include <stdarg.h>
28
+
29
+#include "../../trim.h"
30
+#include "../../ver.h"
31
+#include "../../rpc_lookup.h"
32
+#include "xhttp_rpc.h"
33
+
34
+extern str xhttp_rpc_root;
35
+extern int xhttp_rpc_mod_cmds_size;
36
+extern xhttp_rpc_mod_cmds_t *xhttp_rpc_mod_cmds;
37
+
38
+extern int ver_name_len;
39
+extern int full_version_len;
40
+
41
+#define XHTTP_RPC_COPY(p,str)	\
42
+do{	\
43
+	if ((int)((p)-buf)+(str).len>max_page_len) {	\
44
+		goto error;	\
45
+	}	\
46
+	memcpy((p), (str).s, (str).len); (p) += (str).len;	\
47
+}while(0)
48
+
49
+#define XHTTP_RPC_COPY_2(p,str1,str2)	\
50
+do{	\
51
+	if ((int)((p)-buf)+(str1).len+(str2).len>max_page_len) {	\
52
+		goto error;	\
53
+	}	\
54
+	memcpy((p), (str1).s, (str1).len); (p) += (str1).len;	\
55
+	memcpy((p), (str2).s, (str2).len); (p) += (str2).len;	\
56
+}while(0)
57
+
58
+#define XHTTP_RPC_COPY_3(p,str1,str2,str3)	\
59
+do{	\
60
+	if ((int)((p)-buf)+(str1).len+(str2).len+(str3).len>max_page_len) {	\
61
+		goto error;	\
62
+	}	\
63
+	memcpy((p), (str1).s, (str1).len); (p) += (str1).len;	\
64
+	memcpy((p), (str2).s, (str2).len); (p) += (str2).len;	\
65
+	memcpy((p), (str3).s, (str3).len); (p) += (str3).len;	\
66
+}while(0)
67
+
68
+#define XHTTP_RPC_COPY_4(p,str1,str2,str3,str4)	\
69
+do{	\
70
+	if ((int)((p)-buf)+(str1).len+(str2).len+(str3).len+(str4).len>max_page_len) {	\
71
+		goto error;	\
72
+	}	\
73
+	memcpy((p), (str1).s, (str1).len); (p) += (str1).len;	\
74
+	memcpy((p), (str2).s, (str2).len); (p) += (str2).len;	\
75
+	memcpy((p), (str3).s, (str3).len); (p) += (str3).len;	\
76
+	memcpy((p), (str4).s, (str4).len); (p) += (str4).len;	\
77
+}while(0)
78
+
79
+#define XHTTP_RPC_COPY_5(p,s1,s2,s3,s4,s5)	\
80
+do{	\
81
+	if ((int)((p)-buf)+(s1).len+(s2).len+(s3).len+(s4).len+(s5).len>max_page_len) {	\
82
+		goto error;	\
83
+	}	\
84
+	memcpy((p), (s1).s, (s1).len); (p) += (s1).len;	\
85
+	memcpy((p), (s2).s, (s2).len); (p) += (s2).len;	\
86
+	memcpy((p), (s3).s, (s3).len); (p) += (s3).len;	\
87
+	memcpy((p), (s4).s, (s4).len); (p) += (s4).len;	\
88
+	memcpy((p), (s5).s, (s5).len); (p) += (s5).len;	\
89
+}while(0)
90
+
91
+#define XHTTP_RPC_COPY_6(p,s1,s2,s3,s4,s5,s6)	\
92
+do{	\
93
+	if ((int)((p)-buf)+(s1).len+(s2).len+(s3).len+(s4).len+(s5).len+(s6).len>max_page_len) {	\
94
+		goto error;	\
95
+	}	\
96
+	memcpy((p), (s1).s, (s1).len); (p) += (s1).len;	\
97
+	memcpy((p), (s2).s, (s2).len); (p) += (s2).len;	\
98
+	memcpy((p), (s3).s, (s3).len); (p) += (s3).len;	\
99
+	memcpy((p), (s4).s, (s4).len); (p) += (s4).len;	\
100
+	memcpy((p), (s5).s, (s5).len); (p) += (s5).len;	\
101
+	memcpy((p), (s6).s, (s6).len); (p) += (s6).len;	\
102
+}while(0)
103
+
104
+#define XHTTP_RPC_COPY_10(p,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10)	\
105
+do{	\
106
+	if ((int)((p)-buf)+(s1).len+(s2).len+(s3).len+(s4).len+(s5).len+(s6).len+(s7).len+(s8).len+(s9).len+(s10).len>max_page_len) {	\
107
+		goto error;	\
108
+	}	\
109
+	memcpy((p), (s1).s, (s1).len); (p) += (s1).len;	\