"Fossies" - the Fresh Open Source Software Archive 
Member "zorp-7.0.4/modules/apr/apr.cc" (28 Oct 2019, 10414 Bytes) of package /linux/privat/zorp-7.0.4.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "apr.cc" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
7.0.1_vs_7.0.2.
1 /***************************************************************************
2 *
3 * Copyright (c) 2000-2015 BalaBit IT Ltd, Budapest, Hungary
4 * Copyright (c) 2015-2018 BalaSys IT Ltd, Budapest, Hungary
5 *
6 * This program 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 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 *
21 ***************************************************************************/
22
23 #include <zorp/proxy.h>
24 #include <zorpll/registry.h>
25 #include <zorpll/streambuf.h>
26
27 #define APR_DUMP "apr.dump"
28 #define APR_DEBUG "apr.debug"
29 #define APR_ERROR "apr.error"
30
31 static const guint stream_buf_size = 65536;
32
33 typedef struct
34 {
35 ZProxy super;
36 ZPoll *poll;
37 gint timeout;
38 gboolean need_server_connect;
39 gint copy_client_data;
40 gboolean quit;
41 ZPktBuf *data_buffer[EP_MAX];
42 /**
43 * Will pass stream to instance of this proxy class when set.
44 */
45 ZPolicyObj *service;
46 gsize buffer_written_to_client;
47 } APRProxy;
48
49 static ZStream *
50 get_stream(APRProxy *self, gint side)
51 {
52 return self->super.endpoints[side];
53 }
54
55 extern ZClass APRProxy__class;
56 static gboolean apr_read_callback(ZStream *stream, GIOCondition /* cond */, gpointer user_data);
57
58 static void
59 apr_setup_stream(APRProxy *self, gint ep)
60 {
61 self->super.endpoints[ep] = z_stream_push(self->super.endpoints[ep], z_stream_buf_new(NULL, stream_buf_size, Z_SBF_IMMED_FLUSH));
62 z_poll_add_stream(self->poll, self->super.endpoints[ep]);
63 z_stream_set_callback(get_stream(self, ep), G_IO_IN, apr_read_callback, self, NULL);
64 z_stream_set_cond(get_stream(self, ep), G_IO_IN, TRUE);
65 }
66
67 static gboolean
68 apr_config_set_defaults(APRProxy *self)
69 {
70 int i;
71 for (i = 0; i < EP_MAX; ++i)
72 self->data_buffer[i] = z_pktbuf_new();
73
74 self->poll = z_poll_new();
75 self->timeout = 600000;
76 self->buffer_written_to_client = 0;
77
78 return TRUE;
79 }
80
81 static gboolean
82 apr_continue_with_proxy(APRProxy *self)
83 {
84 gint i;
85 gboolean called;
86 ZPolicyObj *pyres;
87
88 for (i = EP_CLIENT; i < EP_MAX; i++)
89 {
90 if (self->super.endpoints[i])
91 {
92 /* NOTE: we flush out streams as some packets might be stucked */
93 if (!z_stream_broken(self->super.endpoints[i]))
94 {
95 z_stream_buf_flush(self->super.endpoints[i]);
96 z_stream_set_nonblock(self->super.endpoints[i], FALSE);
97 }
98
99 /* Prepare stream for passing to other proxy */
100 z_stream_set_cond(self->super.endpoints[i], G_IO_IN, FALSE);
101 z_poll_remove_stream(self->poll, self->super.endpoints[i]);
102
103 self->super.endpoints[i] = z_stream_pop(self->super.endpoints[i]);
104
105 gssize len = self->data_buffer[i]->length;
106 if (i == EP_CLIENT && self->buffer_written_to_client)
107 len = self->buffer_written_to_client;
108
109 z_stream_unget(self->super.endpoints[i], self->data_buffer[i]->data, len, NULL);
110 }
111 }
112
113 z_policy_lock(self->super.thread);
114 pyres = z_policy_call(self->super.handler, "startService", z_policy_var_build("(O)", self->service), &called, self->super.session_id);
115 z_policy_var_unref(pyres);
116 z_policy_unlock(self->super.thread);
117
118 /* release, but don't close fds on success */
119 for (i = EP_CLIENT; i < EP_MAX; i++)
120 {
121 if (self->super.endpoints[i])
122 {
123 if (TRUE)
124 z_stream_unref(self->super.endpoints[i]);
125 else
126 z_stream_close(self->super.endpoints[i], NULL);
127 self->super.endpoints[i] = NULL;
128 }
129 }
130
131 return TRUE;
132 }
133
134 static void
135 apr_register_vars(APRProxy *self)
136 {
137 z_proxy_var_new(&self->super, "timeout",
138 Z_VAR_GET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
139 Z_VAR_TYPE_INT, &self->timeout);
140
141 z_proxy_var_new(&self->super, "copy_client_data",
142 Z_VAR_GET | Z_VAR_SET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
143 Z_VAR_TYPE_INT, &self->copy_client_data);
144
145 z_proxy_var_new(&self->super, "need_server_connect",
146 Z_VAR_GET | Z_VAR_SET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
147 Z_VAR_TYPE_INT, &self->need_server_connect);
148
149 z_proxy_var_new(&self->super, "quit",
150 Z_VAR_GET | Z_VAR_SET | Z_VAR_GET_CONFIG | Z_VAR_SET_CONFIG |
151 Z_VAR_TYPE_INT, &self->quit);
152 }
153
154 static gboolean
155 apr_config(ZProxy *s)
156 {
157 APRProxy *self = (APRProxy *) s;
158
159 z_proxy_enter (self);
160 apr_config_set_defaults(self);
161 apr_register_vars(self);
162 z_proxy_return(self, Z_SUPER(s, ZProxy)->config(s));
163 }
164
165 /**
166 * Reads data into packet from stream.
167 *
168 * @internal
169 */
170 static inline gboolean
171 apr_read(ZStream *stream, ZPktBuf *packet, gsize length)
172 {
173 GIOStatus status;
174 gsize br;
175
176 if (packet->allocated < packet->length + length)
177 z_pktbuf_resize(packet, packet->length + length);
178
179 status = z_stream_read(stream, (gchar*) (z_pktbuf_end(packet)), length, &br, NULL);
180
181 if (status == G_IO_STATUS_ERROR || status == G_IO_STATUS_EOF)
182 {
183 /* error already logged */
184 return FALSE;
185 }
186 else if (status == G_IO_STATUS_NORMAL)
187 {
188 packet->length += br;
189 }
190
191 return TRUE;
192 }
193
194 static void
195 apr_detect(APRProxy *self, gint side)
196 {
197 ZPktBuf *buf = self->data_buffer[side];
198
199 z_proxy_log_data_dump(self, APR_DUMP, 8, (gchar*) buf->data, buf->length);
200 z_policy_lock(self->super.thread);
201 PyObject *data = PyString_FromStringAndSize(reinterpret_cast<char *>(buf->data), buf->length);
202 if (data)
203 {
204 ZPolicyObj *pyres = z_policy_call(self->super.handler, "detect", z_policy_var_build("(iO)", side, data),
205 nullptr, self->super.session_id);
206 Py_XDECREF(data);
207 if (pyres)
208 {
209 if (pyres != z_policy_none)
210 {
211 self->quit = TRUE;
212 self->service = pyres;
213 }
214 else
215 {
216 z_policy_var_unref(pyres);
217 }
218 }
219 }
220 z_policy_unlock(self->super.thread);
221 }
222
223 static void
224 connect_server(APRProxy *self)
225 {
226 if (get_stream(self, EP_SERVER))
227 return;
228 z_proxy_log(self, "APR.debug", 6, "connect server");
229 if (z_proxy_connect_server(&self->super, NULL, 0))
230 apr_setup_stream(self, EP_SERVER);
231 }
232
233 static gboolean
234 apr_read_callback(ZStream *stream, GIOCondition /* cond */, gpointer user_data)
235 {
236 APRProxy *self = static_cast<APRProxy *>(user_data);
237 gint side = (stream == get_stream(self, EP_CLIENT)) ? EP_CLIENT : EP_SERVER;
238 ZPktBuf *incoming_packet = self->data_buffer[side];
239
240 if (!apr_read(stream, incoming_packet, stream_buf_size))
241 goto error;
242
243 z_proxy_log(self, "APR.debug", 6, "Received data");
244 apr_detect(self, side);
245 if (self->need_server_connect)
246 connect_server(self);
247 if (self->copy_client_data && get_stream(self, EP_SERVER))
248 {
249 gsize written;
250 gsize length = static_cast<guint>(self->copy_client_data) >
251 self->data_buffer[EP_CLIENT]->length ? self->data_buffer[EP_CLIENT]->length : self->copy_client_data;
252 self->copy_client_data = 0;
253 z_stream_write(get_stream(self, EP_SERVER), self->data_buffer[EP_CLIENT]->data, length, &written, NULL);
254 self->buffer_written_to_client = written;
255 }
256 return TRUE;
257
258 error:
259 self->quit = TRUE;
260 incoming_packet->length = 0;
261 return FALSE;
262 }
263
264 static void
265 apr_wakeup(ZProxy *s)
266 {
267 APRProxy *self = (APRProxy *) s;
268
269 z_poll_wakeup(self->poll);
270 }
271
272 /*
273 * Main proxy loop.
274 *
275 * @param[in] s APRProxy instance.
276 */
277 static void
278 apr_main(ZProxy *s)
279 {
280 APRProxy *self = Z_CAST(s, APRProxy);
281 guint ep;
282
283 /* construct and initialize */
284
285 /* start */
286 apr_setup_stream(self, EP_CLIENT);
287
288 if (self->need_server_connect)
289 connect_server(self);
290
291 /* process packets */
292 z_proxy_log(self, APR_DEBUG, 6, "Entering main-loop;");
293 while (!self->quit && z_poll_iter_timeout(self->poll, self->timeout))
294 {
295 if (!z_proxy_loop_iteration(s))
296 self->quit = TRUE;
297 }
298
299 /* pass streams as neccessary */
300 if (self->service && !apr_continue_with_proxy(self))
301 {
302 //z_proxy_log(self, SOCKS_DEBUG, 6, "Unable to pass streams to stacked proxy;");
303 }
304
305
306 //z_proxy_log(self, SOCKS_DEBUG, 6, "Leaving main-loop;");
307
308 for (ep = EP_CLIENT; ep < EP_MAX; ep++)
309 {
310 if (self->super.endpoints[ep])
311 {
312 /* NOTE: we flush out streams as some packets might be stucked */
313 if (!z_stream_broken(self->super.endpoints[ep]))
314 {
315 z_stream_buf_flush(self->super.endpoints[ep]);
316 z_stream_set_nonblock(self->super.endpoints[ep], FALSE);
317 }
318
319 z_poll_remove_stream(self->poll, self->super.endpoints[ep]);
320 }
321 }
322 }
323
324 /**
325 * APRProxy constructor. Allocates and initializes a proxy instance,
326 * starts proxy thread.
327 */
328 static ZProxy *
329 apr_proxy_new(ZProxyParams *params)
330 {
331 APRProxy *self;
332
333 z_enter ();
334 self = Z_CAST(z_proxy_new(Z_CLASS(APRProxy), params), APRProxy);
335 z_return((ZProxy *) self);
336 }
337
338 /*
339 * APRProxy free method.
340 *
341 * @param[in] s APRProxy instance.
342 */
343 void
344 apr_proxy_free(ZObject *s)
345 {
346 APRProxy *self = Z_CAST(s, APRProxy);
347
348 z_enter();
349
350 for (int i = 0; i < EP_MAX; ++i)
351 z_pktbuf_unref(self->data_buffer[i]);
352
353 z_poll_unref(self->poll);
354 if (self->service)
355 z_policy_var_unref(self->service);
356 z_proxy_free_method(s);
357 z_return();
358 }
359
360 ZProxyFuncs apr_proxy_funcs =
361 {
362 {
363 Z_FUNCS_COUNT (ZProxy),
364 apr_proxy_free,
365 },
366 apr_config,
367 NULL,
368 apr_main,
369 NULL,
370 NULL,
371 NULL,
372 NULL,
373 apr_wakeup,
374 };
375
376 Z_CLASS_DEF(APRProxy, ZProxy, apr_proxy_funcs);
377
378 static ZProxyModuleFuncs apr_module_funcs =
379 {
380 apr_proxy_new,
381 NULL
382 };
383
384 /**
385 * Module initialization function. Registers the APR proxy type.
386 *
387 * @return TRUE if module usage is permitted by the licence.
388 */
389 gint
390 zorp_module_init(void)
391 {
392 z_registry_add("apr", ZR_PROXY, &apr_module_funcs);
393 return TRUE;
394 }