Browse code

ruxc: new module with utility functions from libruxc

- first target is to provide http get/post functions that do not depend
on libcurl+libssl

Daniel-Constantin Mierla authored on 19/07/2021 06:32:48
Showing 6 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+#
2
+# secsipid module makefile
3
+#
4
+# WARNING: do not run this directly, it should be run by the main Makefile
5
+
6
+include ../../Makefile.defs
7
+auto_gen=
8
+NAME=ruxc.so
9
+
10
+ifeq ($(CROSS_COMPILE),)
11
+	BUILDER = $(shell which pkg-config)
12
+ifneq ($(BUILDER),)
13
+	PKGLIBRUXC = $(shell $(BUILDER) --exists libruxc > /dev/null 2>&1 ; echo $$? )
14
+ifneq ($(PKGLIBRUXC),0)
15
+	BUILDER =
16
+endif
17
+endif
18
+endif
19
+
20
+ifeq ($(BUILDER),)
21
+	DEFS+= -I.
22
+	LIBS = -L. -lruxc
23
+else
24
+	DEFS+= $(shell pkg-config --cflags libruxc)
25
+	LIBS = $(shell pkg-config --libs libruxc)
26
+endif
27
+
28
+ifeq ($(OS), darwin)
29
+LIBS+= -framework CoreFoundation -framework Security
30
+endif
31
+
32
+include ../../Makefile.modules
0 33
new file mode 100644
... ...
@@ -0,0 +1,188 @@
1
+RUXC Module
2
+
3
+Daniel-Constantin Mierla
4
+
5
+   asipto.com
6
+   <miconda@gmail.com>
7
+
8
+Edited by
9
+
10
+Daniel-Constantin Mierla
11
+
12
+   <miconda@gmail.com>
13
+
14
+   Copyright � 2021 http://www.asipto.com
15
+     __________________________________________________________________
16
+
17
+   Table of Contents
18
+
19
+   1. Admin Guide
20
+
21
+        1. Overview
22
+        2. Dependencies
23
+
24
+              2.1. Kamailio Modules
25
+              2.2. External Libraries or Applications
26
+
27
+        3. Parameters
28
+
29
+              3.1. http_timeout (int)
30
+
31
+        4. Functions
32
+
33
+              4.1. ruxc_http_get(url, hdrs, respv)
34
+              4.2. ruxc_http_post(url, body, hdrs, respv)
35
+
36
+        5. Installation
37
+
38
+   List of Examples
39
+
40
+   1.1. Set http_timeout parameter
41
+   1.2. ruxc_http_get() usage
42
+   1.3. ruxc_http_post() usage
43
+   1.4. Libruxc Usage
44
+
45
+Chapter 1. Admin Guide
46
+
47
+   Table of Contents
48
+
49
+   1. Overview
50
+   2. Dependencies
51
+
52
+        2.1. Kamailio Modules
53
+        2.2. External Libraries or Applications
54
+
55
+   3. Parameters
56
+
57
+        3.1. http_timeout (int)
58
+
59
+   4. Functions
60
+
61
+        4.1. ruxc_http_get(url, hdrs, respv)
62
+        4.2. ruxc_http_post(url, body, hdrs, respv)
63
+
64
+   5. Installation
65
+
66
+1. Overview
67
+
68
+   The module exports utility functions based on libruxc.
69
+
70
+   Among them are function to perform HTTP GET and POST queries.
71
+
72
+   The ruxc project is available at: https://github.com/miconda/ruxc.
73
+
74
+2. Dependencies
75
+
76
+   2.1. Kamailio Modules
77
+   2.2. External Libraries or Applications
78
+
79
+2.1. Kamailio Modules
80
+
81
+   The following modules must be installed (but not loaded) to use this
82
+   module:
83
+     * none.
84
+
85
+2.2. External Libraries or Applications
86
+
87
+   The following libraries or applications must be installed before
88
+   running Kamailio with this module loaded:
89
+     * libruxc.
90
+
91
+3. Parameters
92
+
93
+   3.1. http_timeout (int)
94
+
95
+3.1. http_timeout (int)
96
+
97
+   The interval in miliseconds after which the HTTP GET or POST query
98
+   times out.
99
+
100
+   Default value is 5000 (5 secs).
101
+
102
+   Example 1.1. Set http_timeout parameter
103
+...
104
+modparam("ruxc", "http_timeout", 2000)
105
+...
106
+
107
+4. Functions
108
+
109
+   4.1. ruxc_http_get(url, hdrs, respv)
110
+   4.2. ruxc_http_post(url, body, hdrs, respv)
111
+
112
+4.1. ruxc_http_get(url, hdrs, respv)
113
+
114
+   Perform a HTTP GET request to "url", storing the response body in the
115
+   "respv" variable. The "hdrs" can be empty string to skip setting them.
116
+   The first two parameters can contain variables that are evaluated at
117
+   runtime. The "respv" has to be the name of a writable variable.
118
+
119
+   The function returns response code of HTTP reply or negative value if
120
+   something went wrong.
121
+
122
+   This function can be used from ANY_ROUTE.
123
+
124
+   Example 1.2. ruxc_http_get() usage
125
+...
126
+http_client_get("http://api.com/index.php?r_uri=$(ru{s.escape.param})&f_uri=$(fu
127
+{s.escape.param})",
128
+           "", "X-Token: abc", "$var(result)");
129
+switch ($rc) {
130
+    ...
131
+}
132
+...
133
+
134
+4.2. ruxc_http_post(url, body, hdrs, respv)
135
+
136
+   Perform a HTTP POST request to "url", storing the response body in the
137
+   "respv" variable. The "body" and "hdrs" can be empty strings to skip
138
+   setting them. The first three parameters can contain variables that are
139
+   evaluated at runtime. The "respv" has to be the name of a writable
140
+   variable.
141
+
142
+   The function returns response code of HTTP reply or negative value if
143
+   something went wrong.
144
+
145
+   This function can be used from ANY_ROUTE.
146
+
147
+   Example 1.3. ruxc_http_post() usage
148
+...
149
+ruxc_http_post("http://api.com/index.php?r_uri=$(ru{s.escape.param})&f_uri=$(fu{
150
+s.escape.param})",
151
+           "", "X-Token: abc", "$var(result)");
152
+switch ($rc) {
153
+    ...
154
+}
155
+...
156
+
157
+5. Installation
158
+
159
+   The module needs "libruxc" library, which is provided by "ruxc" project
160
+   from https://github.com/miconda/ruxc/. The library is implemented in
161
+   Rust language, with generated C API and library. Until the libruxc is
162
+   going to be packaged in OS distributions, the ruxc module can be
163
+   compiled by copying ruxc.h and libruxc.a files in the folder of the
164
+   module.
165
+
166
+   To generate the libruxc.a file, it requires to have Rust language
167
+   installed and its environment configured, then run the following
168
+   commands:
169
+
170
+   Example 1.4. Libruxc Usage
171
+...
172
+git clone https://github.com/miconda/ruxc
173
+cd ruxc
174
+cargo build --release
175
+cp include/ruxc.h target/release/libruxc.a \
176
+    /path/to/kamailio/src/modules/ruxc/
177
+
178
+cd /path/to/kamailio/
179
+make include_modules="ruxc ..." cfg
180
+make all
181
+make install
182
+
183
+## or compiling individual module for use inside source tree
184
+# make modules modules=src/modules/ruxc
185
+...
186
+
187
+   For more details about compilation and installation of libruxc, see:
188
+   https://github.com/miconda/ruxc.
0 189
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+docs = ruxc.xml
2
+
3
+docbook_dir = ../../../../doc/docbook
4
+include $(docbook_dir)/Makefile.module
0 5
new file mode 100644
... ...
@@ -0,0 +1,42 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+
11
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
12
+    <bookinfo>
13
+	<title>RUXC Module</title>
14
+	<productname class="trade">&kamailioname;</productname>
15
+	<authorgroup>
16
+	    <author>
17
+		<firstname>Daniel-Constantin</firstname>
18
+		<surname>Mierla</surname>
19
+		<affiliation><orgname>asipto.com</orgname></affiliation>
20
+		<email>miconda@gmail.com</email>
21
+		<address>
22
+		<otheraddr>
23
+		<ulink url="http://www.asipto.com">http://www.asipto.com</ulink>
24
+		</otheraddr>
25
+		</address>
26
+	    </author>
27
+	    <editor>
28
+		<firstname>Daniel-Constantin</firstname>
29
+		<surname>Mierla</surname>
30
+		<email>miconda@gmail.com</email>
31
+	    </editor>
32
+	</authorgroup>
33
+	<copyright>
34
+	    <year>2021</year>
35
+	    <holder>http://www.asipto.com</holder>
36
+	</copyright>
37
+    </bookinfo>
38
+    <toc></toc>
39
+
40
+    <xi:include href="ruxc_admin.xml"/>
41
+
42
+</book>
0 43
new file mode 100644
... ...
@@ -0,0 +1,189 @@
1
+<?xml version="1.0" encoding='ISO-8859-1'?>
2
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
4
+
5
+<!-- Include general documentation entities -->
6
+<!ENTITY % docentities SYSTEM "../../../../doc/docbook/entities.xml">
7
+%docentities;
8
+
9
+]>
10
+<!-- Module User's Guide -->
11
+
12
+<chapter>
13
+
14
+	<title>&adminguide;</title>
15
+
16
+	<section>
17
+	<title>Overview</title>
18
+	<para>
19
+		The module exports utility functions based on libruxc.
20
+	</para>
21
+	<para>
22
+		Among them are function to perform HTTP GET and POST queries.
23
+	</para>
24
+	<para>
25
+		The ruxc project is available at:
26
+		<ulink url="https://github.com/miconda/ruxc">https://github.com/miconda/ruxc</ulink>.
27
+	</para>
28
+	</section>
29
+	<section>
30
+	<title>Dependencies</title>
31
+	<section>
32
+		<title>&kamailio; Modules</title>
33
+		<para>
34
+		The following modules must be installed (but not loaded) to use this module:
35
+			<itemizedlist>
36
+			<listitem>
37
+			<para>
38
+				<emphasis>none</emphasis>.
39
+			</para>
40
+			</listitem>
41
+			</itemizedlist>
42
+		</para>
43
+	</section>
44
+	<section>
45
+		<title>External Libraries or Applications</title>
46
+		<para>
47
+		The following libraries or applications must be installed before running
48
+		&kamailio; with this module loaded:
49
+			<itemizedlist>
50
+			<listitem>
51
+			<para>
52
+				<emphasis>libruxc</emphasis>.
53
+			</para>
54
+			</listitem>
55
+			</itemizedlist>
56
+		</para>
57
+	</section>
58
+	</section>
59
+	<section>
60
+	<title>Parameters</title>
61
+	<section id="ruxc.p.http_timeout">
62
+		<title><varname>http_timeout</varname> (int)</title>
63
+		<para>
64
+		The interval in miliseconds after which the HTTP GET or POST query
65
+		times out.
66
+		</para>
67
+		<para>
68
+		<emphasis>
69
+			Default value is 5000 (5 secs).
70
+		</emphasis>
71
+		</para>
72
+		<example>
73
+		<title>Set <varname>http_timeout</varname> parameter</title>
74
+		<programlisting format="linespecific">
75
+...
76
+modparam("ruxc", "http_timeout", 2000)
77
+...
78
+</programlisting>
79
+		</example>
80
+	</section>
81
+	</section>
82
+
83
+	<section>
84
+	<title>Functions</title>
85
+		<section id="ruxc.f.ruxc_http_get">
86
+			<title>
87
+				<function moreinfo="none">ruxc_http_get(url, hdrs, respv)</function>
88
+			</title>
89
+			<para>
90
+				Perform a HTTP GET request to "url", storing the response body
91
+				in the "respv" variable. The "hdrs" can be empty string
92
+				to skip setting them. The first two parameters can contain
93
+				variables that are evaluated at runtime. The "respv" has to be
94
+				the name of a writable variable.
95
+			</para>
96
+			<para>
97
+			The function returns response code of HTTP reply or negative value
98
+			if something went wrong.
99
+			</para>
100
+			<para>
101
+			This function can be used from ANY_ROUTE.
102
+			</para>
103
+			<example>
104
+				<title><function>ruxc_http_get()</function> usage</title>
105
+				<programlisting format="linespecific">
106
+...
107
+http_client_get("http://api.com/index.php?r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
108
+	   "", "X-Token: abc", "$var(result)");
109
+switch ($rc) {
110
+    ...
111
+}
112
+...
113
+				</programlisting>
114
+			</example>
115
+		</section>
116
+		<section id="ruxc.f.ruxc_http_post">
117
+			<title>
118
+				<function moreinfo="none">ruxc_http_post(url, body, hdrs, respv)</function>
119
+			</title>
120
+			<para>
121
+				Perform a HTTP POST request to "url", storing the response body
122
+				in the "respv" variable. The "body" and "hdrs" can be empty strings
123
+				to skip setting them. The first three parameters can contain
124
+				variables that are evaluated at runtime. The "respv" has to be
125
+				the name of a writable variable.
126
+			</para>
127
+			<para>
128
+			The function returns response code of HTTP reply or negative value
129
+			if something went wrong.
130
+			</para>
131
+			<para>
132
+			This function can be used from ANY_ROUTE.
133
+			</para>
134
+			<example>
135
+				<title><function>ruxc_http_post()</function> usage</title>
136
+				<programlisting format="linespecific">
137
+...
138
+ruxc_http_post("http://api.com/index.php?r_uri=$(ru{s.escape.param})&amp;f_uri=$(fu{s.escape.param})",
139
+	   "", "X-Token: abc", "$var(result)");
140
+switch ($rc) {
141
+    ...
142
+}
143
+...
144
+				</programlisting>
145
+			</example>
146
+		</section>
147
+	</section>
148
+	<section id="ruxc.s.installation">
149
+	<title>Installation</title>
150
+	<para>
151
+		The module needs "libruxc" library, which is provided by "ruxc" project
152
+		from https://github.com/miconda/ruxc/. The library is
153
+		implemented in Rust language, with generated C API and library. Until the
154
+		libruxc is going to be packaged in OS distributions, the ruxc
155
+		module can be compiled by copying ruxc.h and libruxc.a
156
+		files in the folder of the module.
157
+	</para>
158
+	<para>
159
+		To generate the libruxc.a file, it requires to have Rust language
160
+		installed and its environment configured, then run the following commands:
161
+	</para>
162
+		<example>
163
+		<title>Libruxc Usage</title>
164
+		<programlisting format="linespecific">
165
+...
166
+git clone https://github.com/miconda/ruxc
167
+cd ruxc
168
+cargo build --release
169
+cp include/ruxc.h target/release/libruxc.a \
170
+    /path/to/kamailio/src/modules/ruxc/
171
+
172
+cd /path/to/kamailio/
173
+make include_modules="ruxc ..." cfg
174
+make all
175
+make install
176
+
177
+## or compiling individual module for use inside source tree
178
+# make modules modules=src/modules/ruxc
179
+...
180
+</programlisting>
181
+		</example>
182
+	<para>
183
+		For more details about compilation and installation of libruxc, see:
184
+		<ulink url="https://github.com/miconda/ruxc">https://github.com/miconda/ruxc</ulink>.
185
+	</para>
186
+	</section>
187
+
188
+</chapter>
189
+
0 190
new file mode 100644
... ...
@@ -0,0 +1,416 @@
1
+/**
2
+ * Copyright (C) 2021 Daniel-Constantin Mierla (asipto.com)
3
+ *
4
+ * This file is part of Kamailio, a free SIP server.
5
+ *
6
+ * This file is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ *
12
+ * This file 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
+ *
21
+ */
22
+
23
+#include <stdio.h>
24
+#include <unistd.h>
25
+#include <stdlib.h>
26
+#include <string.h>
27
+
28
+#include <ruxc.h>
29
+
30
+#include "../../core/sr_module.h"
31
+#include "../../core/dprint.h"
32
+#include "../../core/mod_fix.h"
33
+#include "../../core/data_lump.h"
34
+#include "../../core/str_list.h"
35
+#include "../../core/lvalue.h"
36
+#include "../../core/kemi.h"
37
+
38
+
39
+MODULE_VERSION
40
+
41
+static int _ruxc_http_timeout = 5000;
42
+
43
+static int mod_init(void);
44
+static int child_init(int);
45
+static void mod_destroy(void);
46
+
47
+static int fixup_ruxc_http_get(void **param, int param_no);
48
+static int fixup_free_ruxc_http_get(void **param, int param_no);
49
+static int w_ruxc_http_get(struct sip_msg *_msg, char *_url,
50
+		char *_hdrs, char *_result);
51
+
52
+static int fixup_ruxc_http_post(void **param, int param_no);
53
+static int fixup_free_ruxc_http_post(void **param, int param_no);
54
+static int w_ruxc_http_post(struct sip_msg *_msg, char *_url,
55
+		char *_body, char *_hdrs, char *_result);
56
+
57
+typedef struct ruxc_data {
58
+	str value;
59
+	int ret;
60
+} ruxc_data_t;
61
+
62
+/* clang-format off */
63
+static cmd_export_t cmds[]={
64
+	{"ruxc_http_get", (cmd_function)w_ruxc_http_get, 3, fixup_ruxc_http_get,
65
+		fixup_free_ruxc_http_get, ANY_ROUTE},
66
+	{"ruxc_http_post", (cmd_function)w_ruxc_http_post, 4, fixup_ruxc_http_post,
67
+		fixup_free_ruxc_http_post, ANY_ROUTE},
68
+
69
+	{0, 0, 0, 0, 0, 0}
70
+};
71
+
72
+static param_export_t params[]={
73
+	{"http_timeout",       PARAM_INT,   &_ruxc_http_timeout},
74
+
75
+	{0, 0, 0}
76
+};
77
+
78
+struct module_exports exports = {
79
+	"ruxc",
80
+	DEFAULT_DLFLAGS, /* dlopen flags */
81
+	cmds,
82
+	params,
83
+	0,              /* exported RPC methods */
84
+	0,              /* exported pseudo-variables */
85
+	0,              /* response function */
86
+	mod_init,       /* module initialization function */
87
+	child_init,     /* per child init function */
88
+	mod_destroy    	/* destroy function */
89
+};
90
+/* clang-format on */
91
+
92
+
93
+/**
94
+ * init module function
95
+ */
96
+static int mod_init(void)
97
+{
98
+	return 0;
99
+}
100
+
101
+/**
102
+ * @brief Initialize async module children
103
+ */
104
+static int child_init(int rank)
105
+{
106
+	return 0;
107
+}
108
+
109
+/**
110
+ * destroy module function
111
+ */
112
+static void mod_destroy(void)
113
+{
114
+	return;
115
+}
116
+
117
+/**
118
+ *
119
+ */
120
+static int ki_ruxc_http_get_helper(sip_msg_t *_msg, str *url, str *hdrs,
121
+		pv_spec_t *dst)
122
+{
123
+	RuxcHTTPRequest v_http_request = {0};
124
+	RuxcHTTPResponse v_http_response = {0};
125
+	int ret;
126
+
127
+    v_http_request.timeout = _ruxc_http_timeout;
128
+    v_http_request.timeout_connect = _ruxc_http_timeout;
129
+    v_http_request.timeout_read = _ruxc_http_timeout;
130
+    v_http_request.timeout_write = _ruxc_http_timeout;
131
+
132
+	v_http_request.url = url->s;
133
+	v_http_request.url_len = url->len;
134
+
135
+	if(hdrs!=NULL && hdrs->s!=NULL && hdrs->len>0) {
136
+		v_http_request.headers = hdrs->s;
137
+		v_http_request.headers_len = hdrs->len;
138
+	}
139
+
140
+	ruxc_http_get(&v_http_request, &v_http_response);
141
+
142
+	if(v_http_response.retcode < 0) {
143
+		LM_ERR("failed to perform http get - retcode: %d\n", v_http_response.retcode);
144
+		ret = v_http_response.retcode;
145
+	} else {
146
+		if(v_http_response.resdata != NULL &&  v_http_response.resdata_len>0) {
147
+			LM_DBG("response code: %d - data len: %d - data: [%.*s]\n",
148
+					v_http_response.rescode, v_http_response.resdata_len,
149
+					v_http_response.resdata_len, v_http_response.resdata);
150
+		}
151
+		ret = v_http_response.rescode;
152
+	}
153
+	ruxc_http_response_release(&v_http_response);
154
+
155
+	return (ret!=0)?ret:-2;
156
+}
157
+
158
+/**
159
+ *
160
+ */
161
+static int ki_ruxc_http_get(sip_msg_t *_msg, str *url, str *hdrs, str *dpv)
162
+{
163
+	pv_spec_t *dst;
164
+
165
+	dst = pv_cache_get(dpv);
166
+	if(dst==NULL) {
167
+		LM_ERR("failed to get pv spec for: %.*s\n", dpv->len, dpv->s);
168
+		return -1;
169
+	}
170
+	if(dst->setf==NULL) {
171
+		LM_ERR("target pv is not writable: %.*s\n", dpv->len, dpv->s);
172
+		return -1;
173
+	}
174
+	return ki_ruxc_http_get_helper(_msg, url, hdrs, dst);
175
+}
176
+
177
+/**
178
+ *
179
+ */
180
+static int w_ruxc_http_get(struct sip_msg *_msg, char *_url,
181
+		char *_hdrs, char *_result)
182
+{
183
+	str url = {NULL, 0};
184
+	str hdrs = {NULL, 0};
185
+	pv_spec_t *dst;
186
+
187
+	if(get_str_fparam(&url, _msg, (gparam_p)_url) != 0 || url.len <= 0) {
188
+		LM_ERR("URL has no value\n");
189
+		return -1;
190
+	}
191
+	if(_hdrs && get_str_fparam(&hdrs, _msg, (gparam_p)_hdrs) != 0) {
192
+		LM_ERR("HDRS has no value\n");
193
+		return -1;
194
+	} else {
195
+		if(hdrs.len == 0) {
196
+			hdrs.s = NULL;
197
+		}
198
+	}
199
+	dst = (pv_spec_t *)_result;
200
+
201
+	return ki_ruxc_http_get_helper(_msg, &url, &hdrs, dst);
202
+}
203
+
204
+/**
205
+ *
206
+ */
207
+static int ki_ruxc_http_post_helper(sip_msg_t *_msg, str *url, str *body, str *hdrs,
208
+		pv_spec_t *dst)
209
+{
210
+	RuxcHTTPRequest v_http_request = {0};
211
+	RuxcHTTPResponse v_http_response = {0};
212
+	int ret;
213
+
214
+    v_http_request.timeout = _ruxc_http_timeout;
215
+    v_http_request.timeout_connect = _ruxc_http_timeout;
216
+    v_http_request.timeout_read = _ruxc_http_timeout;
217
+    v_http_request.timeout_write = _ruxc_http_timeout;
218
+
219
+	v_http_request.url = url->s;
220
+	v_http_request.url_len = url->len;
221
+
222
+	if(body!=NULL && body->s!=NULL && body->len>0) {
223
+		v_http_request.data = body->s;
224
+		v_http_request.data_len = body->len;
225
+	}
226
+
227
+	if(hdrs!=NULL && hdrs->s!=NULL && hdrs->len>0) {
228
+		v_http_request.headers = hdrs->s;
229
+		v_http_request.headers_len = hdrs->len;
230
+	}
231
+
232
+	ruxc_http_post(&v_http_request, &v_http_response);
233
+
234
+	if(v_http_response.retcode < 0) {
235
+		LM_ERR("failed to perform http get - retcode: %d\n", v_http_response.retcode);
236
+		ret = v_http_response.retcode;
237
+	} else {
238
+		if(v_http_response.resdata != NULL &&  v_http_response.resdata_len>0) {
239
+			LM_DBG("response code: %d - data len: %d - data: [%.*s]\n",
240
+					v_http_response.rescode, v_http_response.resdata_len,
241
+					v_http_response.resdata_len, v_http_response.resdata);
242
+		}
243
+		ret = v_http_response.rescode;
244
+	}
245
+	ruxc_http_response_release(&v_http_response);
246
+
247
+	return (ret!=0)?ret:-2;
248
+}
249
+
250
+/**
251
+ *
252
+ */
253
+static int ki_ruxc_http_post(sip_msg_t *_msg, str *url, str *body, str *hdrs, str *dpv)
254
+{
255
+	pv_spec_t *dst;
256
+
257
+	dst = pv_cache_get(dpv);
258
+	if(dst==NULL) {
259
+		LM_ERR("failed to get pv spec for: %.*s\n", dpv->len, dpv->s);
260
+		return -1;
261
+	}
262
+	if(dst->setf==NULL) {
263
+		LM_ERR("target pv is not writable: %.*s\n", dpv->len, dpv->s);
264
+		return -1;
265
+	}
266
+	return ki_ruxc_http_post_helper(_msg, url, body, hdrs, dst);
267
+}
268
+
269
+/**
270
+ *
271
+ */
272
+static int w_ruxc_http_post(struct sip_msg *_msg, char *_url,
273
+		char *_body, char *_hdrs, char *_result)
274
+{
275
+	str url = {NULL, 0};
276
+	str body = {NULL, 0};
277
+	str hdrs = {NULL, 0};
278
+	pv_spec_t *dst;
279
+
280
+	if(get_str_fparam(&url, _msg, (gparam_p)_url) != 0 || url.len <= 0) {
281
+		LM_ERR("URL has no value\n");
282
+		return -1;
283
+	}
284
+	if(_body && get_str_fparam(&body, _msg, (gparam_p)_body) != 0) {
285
+		LM_ERR("DATA body has no value\n");
286
+		return -1;
287
+	} else {
288
+		if(body.len == 0) {
289
+			body.s = NULL;
290
+		}
291
+	}
292
+	if(_hdrs && get_str_fparam(&hdrs, _msg, (gparam_p)_hdrs) != 0) {
293
+		LM_ERR("HDRS has no value\n");
294
+		return -1;
295
+	} else {
296
+		if(hdrs.len == 0) {
297
+			hdrs.s = NULL;
298
+		}
299
+	}
300
+	dst = (pv_spec_t *)_result;
301
+
302
+	return ki_ruxc_http_post_helper(_msg, &url, &body, &hdrs, dst);
303
+}
304
+
305
+/**
306
+ *
307
+ */
308
+static int fixup_ruxc_http_get(void **param, int param_no)
309
+{
310
+	if((param_no >= 1) && (param_no <= 2)) {
311
+		return fixup_spve_null(param, 1);
312
+	}
313
+
314
+	if(param_no == 3) {
315
+		if(fixup_pvar_null(param, 1) != 0) {
316
+			LM_ERR("failed to fixup result pvar\n");
317
+			return -1;
318
+		}
319
+		if(((pv_spec_t *)(*param))->setf == NULL) {
320
+			LM_ERR("result pvar is not writeble\n");
321
+			return -1;
322
+		}
323
+		return 0;
324
+	}
325
+
326
+	LM_ERR("invalid parameter number <%d>\n", param_no);
327
+	return -1;
328
+}
329
+
330
+/**
331
+ *
332
+ */
333
+static int fixup_free_ruxc_http_get(void **param, int param_no)
334
+{
335
+	if((param_no >= 1) && (param_no <= 2)) {
336
+		return fixup_free_spve_null(param, 1);
337
+	}
338
+
339
+	if(param_no == 3) {
340
+		return fixup_free_pvar_null(param, 1);
341
+	}
342
+
343
+	LM_ERR("invalid parameter number <%d>\n", param_no);
344
+	return -1;
345
+}
346
+
347
+/**
348
+ *
349
+ */
350
+static int fixup_ruxc_http_post(void **param, int param_no)
351
+{
352
+	if((param_no >= 1) && (param_no <= 3)) {
353
+		return fixup_spve_null(param, 1);
354
+	}
355
+
356
+	if(param_no == 4) {
357
+		if(fixup_pvar_null(param, 1) != 0) {
358
+			LM_ERR("failed to fixup result pvar\n");
359
+			return -1;
360
+		}
361
+		if(((pv_spec_t *)(*param))->setf == NULL) {
362
+			LM_ERR("result pvar is not writeble\n");
363
+			return -1;
364
+		}
365
+		return 0;
366
+	}
367
+
368
+	LM_ERR("invalid parameter number <%d>\n", param_no);
369
+	return -1;
370
+}
371
+
372
+/**
373
+ *
374
+ */
375
+static int fixup_free_ruxc_http_post(void **param, int param_no)
376
+{
377
+	if((param_no >= 1) && (param_no <= 3)) {
378
+		return fixup_free_spve_null(param, 1);
379
+	}
380
+
381
+	if(param_no == 4) {
382
+		return fixup_free_pvar_null(param, 1);
383
+	}
384
+
385
+	LM_ERR("invalid parameter number <%d>\n", param_no);
386
+	return -1;
387
+}
388
+
389
+/**
390
+ *
391
+ */
392
+/* clang-format off */
393
+static sr_kemi_t sr_kemi_ruxc_exports[] = {
394
+	{ str_init("ruxc"), str_init("http_get"),
395
+		SR_KEMIP_INT, ki_ruxc_http_get,
396
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
397
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
398
+	},
399
+	{ str_init("ruxc"), str_init("http_post"),
400
+		SR_KEMIP_INT, ki_ruxc_http_post,
401
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
402
+			SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE }
403
+	},
404
+
405
+	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
406
+};
407
+/* clang-format on */
408
+
409
+/**
410
+ *
411
+ */
412
+int mod_register(char *path, int *dlflags, void *p1, void *p2)
413
+{
414
+	sr_kemi_modules_add(sr_kemi_ruxc_exports);
415
+	return 0;
416
+}