aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-07-05 12:33:25 +0000
committerChristian Grothoff <christian@grothoff.org>2016-07-05 12:33:25 +0000
commit3f1bdbec8a40c36da13fd2488e67b8daba49025c (patch)
treec8ae0f8c4a533d6d7afbab3c26fa987b019d99c9 /src/vpn
parentb97332aac1d2c14ba8985e82fad90077673027c0 (diff)
downloadgnunet-3f1bdbec8a40c36da13fd2488e67b8daba49025c.tar.gz
gnunet-3f1bdbec8a40c36da13fd2488e67b8daba49025c.zip
transitioning VPN API to MQ
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/vpn_api.c269
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 */
168static void 165static int
169receive_response (void *cls, 166check_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 */
205static void
206handle_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 */
244static size_t 236static void
245transmit_request (void *cls, 237send_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 */
338static void 298static void
339queue_request (struct GNUNET_VPN_RedirectionRequest *rr) 299mq_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
364connect_task (void *cls) 314connect_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,
543struct GNUNET_VPN_Handle * 503struct GNUNET_VPN_Handle *
544GNUNET_VPN_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) 504GNUNET_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
566GNUNET_VPN_disconnect (struct GNUNET_VPN_Handle *vh) 526GNUNET_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 {