diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-07-05 12:33:25 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-07-05 12:33:25 +0000 |
commit | 3f1bdbec8a40c36da13fd2488e67b8daba49025c (patch) | |
tree | c8ae0f8c4a533d6d7afbab3c26fa987b019d99c9 /src/vpn | |
parent | b97332aac1d2c14ba8985e82fad90077673027c0 (diff) | |
download | gnunet-3f1bdbec8a40c36da13fd2488e67b8daba49025c.tar.gz gnunet-3f1bdbec8a40c36da13fd2488e67b8daba49025c.zip |
transitioning VPN API to MQ
Diffstat (limited to 'src/vpn')
-rw-r--r-- | src/vpn/vpn_api.c | 269 |
1 files changed, 112 insertions, 157 deletions
diff --git a/src/vpn/vpn_api.c b/src/vpn/vpn_api.c index da597d801..adba0a666 100644 --- a/src/vpn/vpn_api.c +++ b/src/vpn/vpn_api.c | |||
@@ -41,12 +41,7 @@ struct GNUNET_VPN_Handle | |||
41 | /** | 41 | /** |
42 | * Connection to VPN service. | 42 | * Connection to VPN service. |
43 | */ | 43 | */ |
44 | struct GNUNET_CLIENT_Connection *client; | 44 | struct GNUNET_MQ_Handle *mq; |
45 | |||
46 | /** | ||
47 | * Active transmission request. | ||
48 | */ | ||
49 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
50 | 45 | ||
51 | /** | 46 | /** |
52 | * Head of list of active redirection requests. | 47 | * Head of list of active redirection requests. |
@@ -61,7 +56,7 @@ struct GNUNET_VPN_Handle | |||
61 | /** | 56 | /** |
62 | * Identifier of a reconnect task. | 57 | * Identifier of a reconnect task. |
63 | */ | 58 | */ |
64 | struct GNUNET_SCHEDULER_Task * rt; | 59 | struct GNUNET_SCHEDULER_Task *rt; |
65 | 60 | ||
66 | /** | 61 | /** |
67 | * How long do we wait until we try to reconnect? | 62 | * How long do we wait until we try to reconnect? |
@@ -160,35 +155,20 @@ reconnect (struct GNUNET_VPN_Handle *vh); | |||
160 | 155 | ||
161 | 156 | ||
162 | /** | 157 | /** |
163 | * Function called when we receive a message from the VPN service. | 158 | * Check a #GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP message from the |
159 | * VPN service. | ||
164 | * | 160 | * |
165 | * @param cls the `struct GNUNET_VPN_Handle` | 161 | * @param cls the `struct GNUNET_VPN_Handle` |
166 | * @param msg message received, NULL on timeout or fatal error | 162 | * @param rm message received |
163 | * @return #GNUNET_OK if @a rm is well-formed | ||
167 | */ | 164 | */ |
168 | static void | 165 | static int |
169 | receive_response (void *cls, | 166 | check_use_ip (void *cls, |
170 | const struct GNUNET_MessageHeader* msg) | 167 | const struct RedirectToIpResponseMessage *rm) |
171 | { | 168 | { |
172 | struct GNUNET_VPN_Handle *vh = cls; | ||
173 | const struct RedirectToIpResponseMessage *rm; | ||
174 | struct GNUNET_VPN_RedirectionRequest *rr; | ||
175 | size_t msize; | ||
176 | size_t alen; | 169 | size_t alen; |
177 | int af; | 170 | int af; |
178 | 171 | ||
179 | if (NULL == msg) | ||
180 | { | ||
181 | reconnect (vh); | ||
182 | return; | ||
183 | } | ||
184 | if ( (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP) || | ||
185 | (sizeof (struct RedirectToIpResponseMessage) > (msize = ntohs (msg->size))) ) | ||
186 | { | ||
187 | GNUNET_break (0); | ||
188 | reconnect (vh); | ||
189 | return; | ||
190 | } | ||
191 | rm = (const struct RedirectToIpResponseMessage *) msg; | ||
192 | af = (int) ntohl (rm->result_af); | 172 | af = (int) ntohl (rm->result_af); |
193 | switch (af) | 173 | switch (af) |
194 | { | 174 | { |
@@ -203,19 +183,34 @@ receive_response (void *cls, | |||
203 | break; | 183 | break; |
204 | default: | 184 | default: |
205 | GNUNET_break (0); | 185 | GNUNET_break (0); |
206 | reconnect (vh); | 186 | return GNUNET_SYSERR; |
207 | return; | ||
208 | } | 187 | } |
209 | if ( (msize != alen + sizeof (struct RedirectToIpResponseMessage)) || | 188 | if ( (ntohs (rm->header.size) != alen + sizeof (*rm)) || |
210 | (0 == rm->request_id) ) | 189 | (0 == rm->request_id) ) |
211 | { | 190 | { |
212 | GNUNET_break (0); | 191 | GNUNET_break (0); |
213 | reconnect (vh); | 192 | return GNUNET_SYSERR; |
214 | return; | ||
215 | } | 193 | } |
216 | GNUNET_CLIENT_receive (vh->client, | 194 | return GNUNET_OK; |
217 | &receive_response, vh, | 195 | } |
218 | GNUNET_TIME_UNIT_FOREVER_REL); | 196 | |
197 | |||
198 | /** | ||
199 | * Handle a #GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP message from the | ||
200 | * VPN service. | ||
201 | * | ||
202 | * @param cls the `struct GNUNET_VPN_Handle` | ||
203 | * @param rm message received | ||
204 | */ | ||
205 | static void | ||
206 | handle_use_ip (void *cls, | ||
207 | const struct RedirectToIpResponseMessage *rm) | ||
208 | { | ||
209 | struct GNUNET_VPN_Handle *vh = cls; | ||
210 | struct GNUNET_VPN_RedirectionRequest *rr; | ||
211 | int af; | ||
212 | |||
213 | af = (int) ntohl (rm->result_af); | ||
219 | for (rr = vh->rr_head; NULL != rr; rr = rr->next) | 214 | for (rr = vh->rr_head; NULL != rr; rr = rr->next) |
220 | { | 215 | { |
221 | if (rr->request_id == rm->request_id) | 216 | if (rr->request_id == rm->request_id) |
@@ -234,59 +229,32 @@ receive_response (void *cls, | |||
234 | 229 | ||
235 | 230 | ||
236 | /** | 231 | /** |
237 | * We're ready to transmit a request to the VPN service. Do it. | 232 | * Add a request to our request queue and transmit it. |
238 | * | 233 | * |
239 | * @param cls the `struct GNUNET_VPN_Handle*` | 234 | * @param rr request to queue and transmit. |
240 | * @param size number of bytes available in buf | ||
241 | * @param buf where to copy the request | ||
242 | * @return number of bytes copied to 'buf' | ||
243 | */ | 235 | */ |
244 | static size_t | 236 | static void |
245 | transmit_request (void *cls, | 237 | send_request (struct GNUNET_VPN_RedirectionRequest *rr) |
246 | size_t size, | ||
247 | void *buf) | ||
248 | { | 238 | { |
249 | struct GNUNET_VPN_Handle *vh = cls; | 239 | struct GNUNET_VPN_Handle *vh = rr->vh; |
250 | struct GNUNET_VPN_RedirectionRequest *rr; | 240 | struct RedirectToIpRequestMessage *rip; |
251 | struct RedirectToIpRequestMessage rip; | 241 | struct RedirectToServiceRequestMessage *rs; |
252 | struct RedirectToServiceRequestMessage rs; | 242 | struct GNUNET_MQ_Envelope *env; |
253 | char *cbuf; | ||
254 | size_t alen; | 243 | size_t alen; |
255 | size_t ret; | ||
256 | |||
257 | vh->th = NULL; | ||
258 | /* find a pending request */ | ||
259 | rr = vh->rr_head; | ||
260 | while ( (NULL != rr) && | ||
261 | (0 != rr->request_id) ) | ||
262 | rr = rr->next; | ||
263 | if (NULL == rr) | ||
264 | return 0; | ||
265 | if (0 == size) | ||
266 | { | ||
267 | reconnect (vh); | ||
268 | return 0; | ||
269 | } | ||
270 | 244 | ||
271 | /* if first request, start receive loop */ | 245 | if (NULL == vh->mq) |
272 | if (0 == vh->request_id_gen) | 246 | return; |
273 | GNUNET_CLIENT_receive (vh->client, | ||
274 | &receive_response, vh, | ||
275 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
276 | if (NULL == rr->addr) | 247 | if (NULL == rr->addr) |
277 | { | 248 | { |
278 | ret = sizeof (struct RedirectToServiceRequestMessage); | 249 | env = GNUNET_MQ_msg (rs, |
279 | GNUNET_assert (ret <= size); | 250 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE); |
280 | rs.header.size = htons ((uint16_t) ret); | 251 | rs->reserved = htonl (0); |
281 | rs.header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_SERVICE); | 252 | rs->expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time); |
282 | rs.reserved = htonl (0); | 253 | rs->protocol = htonl (rr->protocol); |
283 | rs.expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time); | 254 | rs->result_af = htonl (rr->result_af); |
284 | rs.protocol = htonl (rr->protocol); | 255 | rs->target = rr->peer; |
285 | rs.result_af = htonl (rr->result_af); | 256 | rs->service_descriptor = rr->serv; |
286 | rs.target = rr->peer; | 257 | rs->request_id = rr->request_id = ++vh->request_id_gen; |
287 | rs.service_descriptor = rr->serv; | ||
288 | rs.request_id = rr->request_id = ++vh->request_id_gen; | ||
289 | memcpy (buf, &rs, sizeof (struct RedirectToServiceRequestMessage)); | ||
290 | } | 258 | } |
291 | else | 259 | else |
292 | { | 260 | { |
@@ -300,58 +268,40 @@ transmit_request (void *cls, | |||
300 | break; | 268 | break; |
301 | default: | 269 | default: |
302 | GNUNET_assert (0); | 270 | GNUNET_assert (0); |
303 | return 0; | 271 | return; |
304 | } | 272 | } |
305 | ret = alen + sizeof (struct RedirectToIpRequestMessage); | 273 | env = GNUNET_MQ_msg_extra (rip, |
306 | GNUNET_assert (ret <= size); | 274 | alen, |
307 | rip.header.size = htons ((uint16_t) ret); | 275 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP); |
308 | rip.header.type = htons (GNUNET_MESSAGE_TYPE_VPN_CLIENT_REDIRECT_TO_IP); | 276 | rip->reserved = htonl (0); |
309 | rip.reserved = htonl (0); | 277 | rip->expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time); |
310 | rip.expiration_time = GNUNET_TIME_absolute_hton (rr->expiration_time); | 278 | rip->result_af = htonl (rr->result_af); |
311 | rip.result_af = htonl (rr->result_af); | 279 | rip->addr_af = htonl (rr->addr_af); |
312 | rip.addr_af = htonl (rr->addr_af); | 280 | rip->request_id = rr->request_id = ++vh->request_id_gen; |
313 | rip.request_id = rr->request_id = ++vh->request_id_gen; | 281 | memcpy (&rip[1], |
314 | cbuf = buf; | 282 | rr->addr, |
315 | memcpy (cbuf, &rip, sizeof (struct RedirectToIpRequestMessage)); | 283 | alen); |
316 | memcpy (&cbuf[sizeof (struct RedirectToIpRequestMessage)], rr->addr, alen); | ||
317 | } | 284 | } |
318 | /* test if there are more pending requests */ | 285 | GNUNET_MQ_send (vh->mq, |
319 | while ( (NULL != rr) && | 286 | env); |
320 | (0 != rr->request_id) ) | ||
321 | rr = rr->next; | ||
322 | if (NULL != rr) | ||
323 | vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client, | ||
324 | sizeof (struct RedirectToServiceRequestMessage), | ||
325 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
326 | GNUNET_NO, | ||
327 | &transmit_request, | ||
328 | vh); | ||
329 | return ret; | ||
330 | } | 287 | } |
331 | 288 | ||
332 | 289 | ||
333 | /** | 290 | /** |
334 | * Add a request to our request queue and transmit it. | 291 | * Generic error handler, called with the appropriate error code and |
292 | * the same closure specified at the creation of the message queue. | ||
293 | * Not every message queue implementation supports an error handler. | ||
335 | * | 294 | * |
336 | * @param rr request to queue and transmit. | 295 | * @param cls closure with the `struct GNUNET_VPN_Handle *` |
296 | * @param error error code | ||
337 | */ | 297 | */ |
338 | static void | 298 | static void |
339 | queue_request (struct GNUNET_VPN_RedirectionRequest *rr) | 299 | mq_error_handler (void *cls, |
300 | enum GNUNET_MQ_Error error) | ||
340 | { | 301 | { |
341 | struct GNUNET_VPN_Handle *vh; | 302 | struct GNUNET_VPN_Handle *vh = cls; |
342 | 303 | ||
343 | vh = rr->vh; | 304 | reconnect (vh); |
344 | GNUNET_CONTAINER_DLL_insert_tail (vh->rr_head, | ||
345 | vh->rr_tail, | ||
346 | rr); | ||
347 | if ( (NULL == vh->th) && | ||
348 | (NULL != vh->client) ) | ||
349 | vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client, | ||
350 | sizeof (struct RedirectToServiceRequestMessage), | ||
351 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
352 | GNUNET_NO, | ||
353 | &transmit_request, | ||
354 | vh); | ||
355 | } | 305 | } |
356 | 306 | ||
357 | 307 | ||
@@ -364,18 +314,25 @@ static void | |||
364 | connect_task (void *cls) | 314 | connect_task (void *cls) |
365 | { | 315 | { |
366 | struct GNUNET_VPN_Handle *vh = cls; | 316 | struct GNUNET_VPN_Handle *vh = cls; |
317 | GNUNET_MQ_hd_var_size (use_ip, | ||
318 | GNUNET_MESSAGE_TYPE_VPN_CLIENT_USE_IP, | ||
319 | struct RedirectToIpResponseMessage); | ||
320 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
321 | make_use_ip_handler (cls), | ||
322 | GNUNET_MQ_handler_end () | ||
323 | }; | ||
324 | struct GNUNET_VPN_RedirectionRequest *rr; | ||
367 | 325 | ||
368 | vh->rt = NULL; | 326 | vh->rt = NULL; |
369 | vh->client = GNUNET_CLIENT_connect ("vpn", vh->cfg); | 327 | vh->mq = GNUNET_CLIENT_connecT (vh->cfg, |
370 | GNUNET_assert (NULL != vh->client); | 328 | "vpn", |
371 | GNUNET_assert (NULL == vh->th); | 329 | handlers, |
372 | if (NULL != vh->rr_head) | 330 | &mq_error_handler, |
373 | vh->th = GNUNET_CLIENT_notify_transmit_ready (vh->client, | 331 | vh); |
374 | sizeof (struct RedirectToServiceRequestMessage), | 332 | if (NULL == vh->mq) |
375 | GNUNET_TIME_UNIT_FOREVER_REL, | 333 | return; |
376 | GNUNET_NO, | 334 | for (rr = vh->rr_head; NULL != rr; rr = rr->next) |
377 | &transmit_request, | 335 | send_request (rr); |
378 | vh); | ||
379 | } | 336 | } |
380 | 337 | ||
381 | 338 | ||
@@ -389,13 +346,8 @@ reconnect (struct GNUNET_VPN_Handle *vh) | |||
389 | { | 346 | { |
390 | struct GNUNET_VPN_RedirectionRequest *rr; | 347 | struct GNUNET_VPN_RedirectionRequest *rr; |
391 | 348 | ||
392 | if (NULL != vh->th) | 349 | GNUNET_MQ_destroy (vh->mq); |
393 | { | 350 | vh->mq = NULL; |
394 | GNUNET_CLIENT_notify_transmit_ready_cancel (vh->th); | ||
395 | vh->th = NULL; | ||
396 | } | ||
397 | GNUNET_CLIENT_disconnect (vh->client); | ||
398 | vh->client = NULL; | ||
399 | vh->request_id_gen = 0; | 351 | vh->request_id_gen = 0; |
400 | for (rr = vh->rr_head; NULL != rr; rr = rr->next) | 352 | for (rr = vh->rr_head; NULL != rr; rr = rr->next) |
401 | rr->request_id = 0; | 353 | rr->request_id = 0; |
@@ -469,7 +421,10 @@ GNUNET_VPN_redirect_to_peer (struct GNUNET_VPN_Handle *vh, | |||
469 | rr->expiration_time = expiration_time; | 421 | rr->expiration_time = expiration_time; |
470 | rr->result_af = result_af; | 422 | rr->result_af = result_af; |
471 | rr->protocol = protocol; | 423 | rr->protocol = protocol; |
472 | queue_request (rr); | 424 | GNUNET_CONTAINER_DLL_insert_tail (vh->rr_head, |
425 | vh->rr_tail, | ||
426 | rr); | ||
427 | send_request (rr); | ||
473 | return rr; | 428 | return rr; |
474 | } | 429 | } |
475 | 430 | ||
@@ -485,7 +440,7 @@ GNUNET_VPN_redirect_to_peer (struct GNUNET_VPN_Handle *vh, | |||
485 | * | 440 | * |
486 | * @param vh VPN handle | 441 | * @param vh VPN handle |
487 | * @param result_af desired address family for the returned allocation | 442 | * @param result_af desired address family for the returned allocation |
488 | * @param addr_af address family for 'addr', AF_INET or AF_INET6 | 443 | * @param addr_af address family for @a addr, AF_INET or AF_INET6 |
489 | * @param addr destination IP address on the Internet; destination | 444 | * @param addr destination IP address on the Internet; destination |
490 | * port is to be taken from the VPN packet itself | 445 | * port is to be taken from the VPN packet itself |
491 | * @param expiration_time at what time should the redirection expire? | 446 | * @param expiration_time at what time should the redirection expire? |
@@ -528,8 +483,13 @@ GNUNET_VPN_redirect_to_ip (struct GNUNET_VPN_Handle *vh, | |||
528 | rr->expiration_time = expiration_time; | 483 | rr->expiration_time = expiration_time; |
529 | rr->result_af = result_af; | 484 | rr->result_af = result_af; |
530 | rr->addr_af = addr_af; | 485 | rr->addr_af = addr_af; |
531 | memcpy (&rr[1], addr, alen); | 486 | memcpy (&rr[1], |
532 | queue_request (rr); | 487 | addr, |
488 | alen); | ||
489 | GNUNET_CONTAINER_DLL_insert_tail (vh->rr_head, | ||
490 | vh->rr_tail, | ||
491 | rr); | ||
492 | send_request (rr); | ||
533 | return rr; | 493 | return rr; |
534 | } | 494 | } |
535 | 495 | ||
@@ -543,12 +503,12 @@ GNUNET_VPN_redirect_to_ip (struct GNUNET_VPN_Handle *vh, | |||
543 | struct GNUNET_VPN_Handle * | 503 | struct GNUNET_VPN_Handle * |
544 | GNUNET_VPN_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) | 504 | GNUNET_VPN_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) |
545 | { | 505 | { |
546 | struct GNUNET_VPN_Handle *vh; | 506 | struct GNUNET_VPN_Handle *vh |
507 | = GNUNET_new (struct GNUNET_VPN_Handle); | ||
547 | 508 | ||
548 | vh = GNUNET_new (struct GNUNET_VPN_Handle); | ||
549 | vh->cfg = cfg; | 509 | vh->cfg = cfg; |
550 | vh->client = GNUNET_CLIENT_connect ("vpn", cfg); | 510 | connect_task (vh); |
551 | if (NULL == vh->client) | 511 | if (NULL == vh->mq) |
552 | { | 512 | { |
553 | GNUNET_free (vh); | 513 | GNUNET_free (vh); |
554 | return NULL; | 514 | return NULL; |
@@ -566,15 +526,10 @@ void | |||
566 | GNUNET_VPN_disconnect (struct GNUNET_VPN_Handle *vh) | 526 | GNUNET_VPN_disconnect (struct GNUNET_VPN_Handle *vh) |
567 | { | 527 | { |
568 | GNUNET_assert (NULL == vh->rr_head); | 528 | GNUNET_assert (NULL == vh->rr_head); |
569 | if (NULL != vh->th) | 529 | if (NULL != vh->mq) |
570 | { | ||
571 | GNUNET_CLIENT_notify_transmit_ready_cancel (vh->th); | ||
572 | vh->th = NULL; | ||
573 | } | ||
574 | if (NULL != vh->client) | ||
575 | { | 530 | { |
576 | GNUNET_CLIENT_disconnect (vh->client); | 531 | GNUNET_MQ_destroy (vh->mq); |
577 | vh->client = NULL; | 532 | vh->mq = NULL; |
578 | } | 533 | } |
579 | if (NULL != vh->rt) | 534 | if (NULL != vh->rt) |
580 | { | 535 | { |