Browse code

sworker: added parameter to be able to pass extra data to worker

Daniel-Constantin Mierla authored on 24/09/2021 08:31:12
Showing 2 changed files
... ...
@@ -65,6 +65,34 @@
65 65
 	</section>
66 66
 	</section>
67 67
 
68
+	<section>
69
+	<title>Parameters</title>
70
+	<section id="sworker.p.xdata">
71
+		<title>
72
+		<function moreinfo="none">xdata (str)</function>
73
+		</title>
74
+		<para>
75
+			Name of a script variable from where to take additional data to be
76
+			passed to special worker along with the SIP message. Same variable
77
+			will be set by the special worker, therefore it has to be a writable
78
+			variable. Moreover, it must be a variable that can be set without
79
+			the SIP message structure, like $var(name), otherwise it can lead to
80
+			a crash.
81
+		</para>
82
+		<para>
83
+		Default value: not set.
84
+		</para>
85
+		<example>
86
+		<title><function>xdata</function> usage</title>
87
+		<programlisting format="linespecific">
88
+...
89
+modparam("sworker", "xdata", "$var(xdata)")
90
+...
91
+</programlisting>
92
+		</example>
93
+	</section>
94
+	</section>
95
+
68 96
 	<section>
69 97
 	<title>Functions</title>
70 98
 	<section id="sworker.f.sworker_active">
... ...
@@ -44,12 +44,15 @@ static int w_sworker_task(sip_msg_t *msg, char *pgname, char *p2);
44 44
 static int w_sworker_active(sip_msg_t *msg, char *p1, char *p2);
45 45
 
46 46
 static int _sworker_active = 0;
47
+static str _sworker_xdata = STR_NULL;
48
+static pv_spec_t *_sworker_xdata_spec = NULL;
47 49
 
48 50
 /* clang-format off */
49 51
 typedef struct sworker_task_param {
50 52
 	char *buf;
51 53
 	int len;
52 54
 	receive_info_t rcv;
55
+	str xdata;
53 56
 } sworker_task_param_t;
54 57
 
55 58
 static cmd_export_t cmds[]={
... ...
@@ -60,17 +63,22 @@ static cmd_export_t cmds[]={
60 63
 	{0, 0, 0, 0, 0, 0}
61 64
 };
62 65
 
66
+static param_export_t params[]={
67
+	{"xdata",    PARAM_STR,   &_sworker_xdata},
68
+	{0, 0, 0}
69
+};
70
+
63 71
 struct module_exports exports = {
64
-	"sworker",
72
+	"sworker",       /* module name */
65 73
 	DEFAULT_DLFLAGS, /* dlopen flags */
66
-	cmds,
67
-	0,
68
-	0,              /* exported RPC methods */
69
-	0,              /* exported pseudo-variables */
70
-	0,              /* response function */
71
-	mod_init,       /* module initialization function */
72
-	child_init,     /* per child init function */
73
-	mod_destroy    	/* destroy function */
74
+	cmds,            /* exported functions */
75
+	params,          /* exported parameters */
76
+	0,               /* exported RPC methods */
77
+	0,               /* exported pseudo-variables */
78
+	0,               /* response function */
79
+	mod_init,        /* module initialization function */
80
+	child_init,      /* per child init function */
81
+	mod_destroy      /* destroy function */
74 82
 };
75 83
 /* clang-format on */
76 84
 
... ...
@@ -80,6 +88,19 @@ struct module_exports exports = {
80 88
  */
81 89
 static int mod_init(void)
82 90
 {
91
+	if(_sworker_xdata.s!=NULL && _sworker_xdata.len>0) {
92
+		_sworker_xdata_spec = pv_cache_get(&_sworker_xdata);
93
+		if(_sworker_xdata_spec==NULL) {
94
+			LM_ERR("cannot get pv spec for [%.*s]\n",
95
+					_sworker_xdata.len, _sworker_xdata.s);
96
+			return -1;
97
+		}
98
+		if(_sworker_xdata_spec->setf==NULL) {
99
+			LM_ERR("read only output variable [%.*s]\n",
100
+					_sworker_xdata.len, _sworker_xdata.s);
101
+			return -1;
102
+		}
103
+	}
83 104
 	return 0;
84 105
 }
85 106
 
... ...
@@ -110,6 +131,7 @@ void sworker_exec_task(void *param)
110 131
 	static char buf[BUF_SIZE+1];
111 132
 	receive_info_t rcvi;
112 133
 	int len;
134
+	pv_value_t val;
113 135
 
114 136
 	stp = (sworker_task_param_t *)param;
115 137
 
... ...
@@ -124,6 +146,23 @@ void sworker_exec_task(void *param)
124 146
 	memcpy(&rcvi, &stp->rcv, sizeof(receive_info_t));
125 147
 	rcvi.rflags |= RECV_F_INTERNAL;
126 148
 
149
+	if(_sworker_xdata_spec!=NULL) {
150
+		if(stp->xdata.len>0) {
151
+			memset(&val, 0, sizeof(pv_value_t));
152
+			val.flags |= PV_VAL_STR;
153
+			val.rs = stp->xdata;
154
+			if(pv_set_spec_value(NULL, _sworker_xdata_spec, 0, &val)!=0) {
155
+				LM_ERR("failed to set the xdata variable\n");
156
+				return;
157
+			}
158
+		} else {
159
+			if(pv_set_spec_value(NULL, _sworker_xdata_spec, 0, NULL)!=0) {
160
+				LM_ERR("failed to reset the xdata variable\n");
161
+				return;
162
+			}
163
+		}
164
+	}
165
+
127 166
 	_sworker_active = 1;
128 167
 	receive_msg(buf, len, &rcvi);
129 168
 	_sworker_active = 0;
... ...
@@ -137,9 +176,23 @@ int sworker_send_task(sip_msg_t *msg, str *gname)
137 176
 	async_task_t *at = NULL;
138 177
 	sworker_task_param_t *stp = NULL;
139 178
 	int dsize;
179
+	pv_value_t val;
140 180
 
181
+	memset(&val, 0, sizeof(pv_value_t));
141 182
 	dsize = sizeof(async_task_t) + sizeof(sworker_task_param_t)
142 183
 		+ (msg->len+1)*sizeof(char);
184
+	if(_sworker_xdata_spec!=NULL) {
185
+		if(pv_get_spec_value(msg, _sworker_xdata_spec, &val)!=0) {
186
+			LM_ERR("failed to get xdata value\n");
187
+			return -1;
188
+		}
189
+		if((val.flags & PV_VAL_STR) && (val.rs.len>0)) {
190
+			dsize += val.rs.len + 1;
191
+		} else {
192
+			LM_DBG("xdata does not have a string value - skipping\n");
193
+			val.rs.len = 0;
194
+		}
195
+	}
143 196
 	at = (async_task_t *)shm_malloc(dsize);
144 197
 	if(at == NULL) {
145 198
 		LM_ERR("no more shm memory\n");
... ...
@@ -153,6 +206,12 @@ int sworker_send_task(sip_msg_t *msg, str *gname)
153 206
 	memcpy(stp->buf, msg->buf, msg->len);
154 207
 	stp->len = msg->len;
155 208
 	memcpy(&stp->rcv, &msg->rcv, sizeof(receive_info_t));
209
+	if(val.rs.len>0) {
210
+		stp->xdata.s = (char*)stp+sizeof(sworker_task_param_t)+msg->len+1;
211
+		memcpy(stp->xdata.s, val.rs.s, val.rs.len);
212
+		stp->xdata.len = val.rs.len;
213
+		pv_value_destroy(&val);
214
+	}
156 215
 
157 216
 	return async_task_group_push(gname, at);
158 217
 }