aboutsummaryrefslogtreecommitdiff
path: root/src/arm
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-12-06 20:20:46 +0000
committerChristian Grothoff <christian@grothoff.org>2011-12-06 20:20:46 +0000
commit03b7f628dabad307fb8f81ff90d356f05e75d9ff (patch)
tree85f4b89d48ef014b3911bdd60bedbe500d073253 /src/arm
parentd473cdc8138214fe65e5b74221584fec8df5785a (diff)
downloadgnunet-03b7f628dabad307fb8f81ff90d356f05e75d9ff.tar.gz
gnunet-03b7f628dabad307fb8f81ff90d356f05e75d9ff.zip
removing ARM interceptor connection forwarding post-accept code, now using lsocks everywhere
Diffstat (limited to 'src/arm')
-rw-r--r--src/arm/gnunet-service-arm_interceptor.c790
1 files changed, 1 insertions, 789 deletions
diff --git a/src/arm/gnunet-service-arm_interceptor.c b/src/arm/gnunet-service-arm_interceptor.c
index c2c275ba3..8d312e28c 100644
--- a/src/arm/gnunet-service-arm_interceptor.c
+++ b/src/arm/gnunet-service-arm_interceptor.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors) 3 (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -39,25 +39,6 @@
39 39
40#define DEBUG_SERVICE_MANAGER GNUNET_EXTRA_LOGGING 40#define DEBUG_SERVICE_MANAGER GNUNET_EXTRA_LOGGING
41 41
42#define BUFFER_SIZE (64 * 1024)
43
44/**
45 * Problem forwarding from client to service.
46 */
47#define REASON_CLIENT_TO_SERVICE 1
48
49/**
50 * Problem forwarding from service to client.
51 */
52#define REASON_SERVICE_TO_CLIENT 2
53
54/**
55 * Problem in both directions.
56 */
57#define REASON_ERROR 3
58
59struct ForwardedConnection;
60
61/** 42/**
62 * 43 *
63 */ 44 */
@@ -94,111 +75,11 @@ struct ServiceListeningInfo
94 struct GNUNET_NETWORK_Handle *listeningSocket; 75 struct GNUNET_NETWORK_Handle *listeningSocket;
95 76
96 /** 77 /**
97 *
98 */
99 struct ForwardedConnection *fc;
100
101 /**
102 * Task doing the accepting. 78 * Task doing the accepting.
103 */ 79 */
104 GNUNET_SCHEDULER_TaskIdentifier acceptTask; 80 GNUNET_SCHEDULER_TaskIdentifier acceptTask;
105}; 81};
106 82
107/**
108 * Information of the connection: client-arm-service
109 */
110struct ForwardedConnection
111{
112 /**
113 *
114 */
115 struct GNUNET_NETWORK_Handle *armClientSocket;
116
117 /**
118 *
119 */
120 struct GNUNET_NETWORK_Handle *armServiceSocket;
121
122 /**
123 *
124 */
125 struct ServiceListeningInfo *listen_info;
126
127 /**
128 *
129 */
130 char service_to_client_buffer[BUFFER_SIZE];
131
132 /**
133 *
134 */
135 char client_to_service_buffer[BUFFER_SIZE];
136
137 /**
138 *
139 */
140 char client_addr[32];
141
142 /**
143 *
144 */
145 const char *client_to_service_bufferPos;
146
147 /**
148 *
149 */
150 const char *service_to_client_bufferPos;
151
152 /**
153 * Timeout for forwarding.
154 */
155 struct GNUNET_TIME_Absolute timeout;
156
157 /**
158 * Current back-off value.
159 */
160 struct GNUNET_TIME_Relative back_off;
161
162 /**
163 * Task that tries to initiate forwarding.
164 */
165 GNUNET_SCHEDULER_TaskIdentifier start_task;
166
167 /**
168 *
169 */
170 GNUNET_SCHEDULER_TaskIdentifier client_to_service_task;
171
172 /**
173 *
174 */
175 GNUNET_SCHEDULER_TaskIdentifier service_to_client_task;
176
177 /**
178 *
179 */
180 ssize_t client_to_service_bufferDataLength;
181
182 /**
183 *
184 */
185 ssize_t service_to_client_bufferDataLength;
186
187 /**
188 *
189 */
190 socklen_t client_addr_len;
191
192 /**
193 * Have we ever successfully written data to the service?
194 */
195 int first_write_done;
196
197 /**
198 * Reference count (the structure is freed when it reaches zero)
199 */
200 int reference_count;
201};
202 83
203/** 84/**
204 * Array with the names of the services started by default. 85 * Array with the names of the services started by default.
@@ -281,599 +162,6 @@ isInDefaultList (const char *serviceName)
281 162
282 163
283/** 164/**
284 * Close forwarded connection (partial or full).
285 *
286 * @param fc connection to close
287 * @param reason which direction to close
288 */
289static void
290closeClientAndServiceSockets (struct ForwardedConnection *fc, int reason)
291{
292 if (0 != (REASON_SERVICE_TO_CLIENT & reason))
293 {
294#if DEBUG_SERVICE_MANAGER
295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
296 "Stopping forwarding from service to client\n");
297#endif
298 if (fc->armClientSocket != NULL)
299 GNUNET_NETWORK_socket_shutdown (fc->armClientSocket, SHUT_WR);
300 if (fc->armServiceSocket != NULL)
301 GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket, SHUT_RD);
302 }
303 if (0 != (REASON_CLIENT_TO_SERVICE & reason))
304 {
305#if DEBUG_SERVICE_MANAGER
306 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
307 "Stopping forwarding from client to service\n");
308#endif
309 if (fc->armClientSocket != NULL)
310 GNUNET_NETWORK_socket_shutdown (fc->armClientSocket, SHUT_RD);
311 if (fc->armServiceSocket != NULL)
312 GNUNET_NETWORK_socket_shutdown (fc->armServiceSocket, SHUT_WR);
313 }
314#if DEBUG_SERVICE_MANAGER
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "Closing forwarding connection (done with both directions)\n");
317#endif
318 fc->reference_count -= 1;
319 if (fc->reference_count <= 0)
320 {
321 if ((NULL != fc->armClientSocket) &&
322 (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (fc->armClientSocket)))
323 {
324 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
325 fc->armClientSocket = NULL;
326 }
327 if ((NULL != fc->armServiceSocket) &&
328 (GNUNET_SYSERR == GNUNET_NETWORK_socket_close (fc->armServiceSocket)))
329 {
330 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "close");
331 fc->armServiceSocket = NULL;
332 }
333 if (fc->listen_info != NULL)
334 {
335 if (fc->listen_info->serviceName != NULL)
336 {
337 GNUNET_free (fc->listen_info->serviceName);
338 fc->listen_info->serviceName = NULL;
339 }
340 if (fc->listen_info->service_addr != NULL)
341 {
342 GNUNET_free (fc->listen_info->service_addr);
343 fc->listen_info->service_addr = NULL;
344 }
345 GNUNET_free (fc->listen_info);
346 fc->listen_info = NULL;
347 }
348 GNUNET_free (fc);
349 }
350}
351
352
353/**
354 * Read data from the client and then forward it to the service.
355 *
356 * @param cls callback data, struct ForwardedConnection for the communication between client and service
357 * @param tc context
358 */
359static void
360receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
361
362
363/**
364 * Receive service messages sent by the service and forward it to client
365 *
366 * @param cls callback data, struct ForwardedConnection for the communication between client and service
367 * @param tc scheduler context
368 */
369static void
370receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
371
372
373/**
374 *
375 */
376static void
377start_forwarding (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
378
379
380
381/**
382 * Forward messages sent from service to client
383 *
384 * @param cls callback data, struct ForwardedConnection for the communication between client and service
385 * @param tc context
386 */
387static void
388forwardToClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
389{
390 struct ForwardedConnection *fc = cls;
391 ssize_t numberOfBytesSent;
392
393 fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
394 if (GNUNET_YES !=
395 GNUNET_NETWORK_fdset_isset (tc->write_ready, fc->armClientSocket))
396 {
397 fc->service_to_client_task =
398 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
399 fc->armClientSocket, &forwardToClient,
400 fc);
401 return;
402 }
403 /* Forwarding service response to client */
404 numberOfBytesSent =
405 GNUNET_NETWORK_socket_send (fc->armClientSocket,
406 fc->service_to_client_bufferPos,
407 fc->service_to_client_bufferDataLength);
408 if (numberOfBytesSent <= 0)
409 {
410 if ((errno != EPIPE) && (errno != ECONNRESET))
411 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
412 "Failed to forward %u bytes of data to client: %s\n",
413 fc->service_to_client_bufferDataLength, STRERROR (errno));
414 closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
415 return;
416 }
417#if DEBUG_SERVICE_MANAGER
418 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarded %d bytes to client\n",
419 numberOfBytesSent);
420#endif
421 if (numberOfBytesSent < fc->service_to_client_bufferDataLength)
422 {
423 fc->service_to_client_bufferPos += numberOfBytesSent;
424 fc->service_to_client_bufferDataLength -= numberOfBytesSent;
425 fc->service_to_client_task =
426 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
427 fc->armClientSocket, &forwardToClient,
428 fc);
429 return;
430 }
431 fc->service_to_client_task =
432 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
433 fc->armServiceSocket, &receiveFromService,
434 fc);
435}
436
437
438/**
439 * Receive service messages sent by the service and forward it to client
440 *
441 * @param cls callback data, struct ForwardedConnection for the communication between client and service
442 * @param tc scheduler context
443 */
444static void
445receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
446{
447 struct ForwardedConnection *fc = cls;
448 struct GNUNET_TIME_Relative rem;
449
450 fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
451 if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
452 (fc->first_write_done != GNUNET_YES))
453 {
454 closeClientAndServiceSockets (fc, REASON_ERROR);
455 return;
456 }
457 if (GNUNET_YES !=
458 GNUNET_NETWORK_fdset_isset (tc->read_ready, fc->armServiceSocket))
459 {
460 fc->service_to_client_task =
461 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
462 fc->armServiceSocket,
463 &receiveFromService, fc);
464 return;
465 }
466 fc->service_to_client_bufferPos = fc->service_to_client_buffer;
467 fc->service_to_client_bufferDataLength =
468 GNUNET_NETWORK_socket_recv (fc->armServiceSocket,
469 fc->service_to_client_buffer, BUFFER_SIZE);
470 if (fc->service_to_client_bufferDataLength <= 0)
471 {
472#if DEBUG_SERVICE_MANAGER
473 if (fc->service_to_client_bufferDataLength == 0)
474 {
475 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476 "Service `%s' stopped sending data.\n",
477 fc->listen_info->serviceName);
478 }
479#endif
480 if (fc->first_write_done != GNUNET_YES)
481 {
482 fc->service_to_client_bufferDataLength = 0;
483 GNUNET_break (GNUNET_OK ==
484 GNUNET_NETWORK_socket_close (fc->armServiceSocket));
485 fc->armServiceSocket = NULL;
486 if ((fc->client_to_service_bufferDataLength > 0) &&
487 (fc->client_to_service_task != GNUNET_SCHEDULER_NO_TASK))
488 {
489 GNUNET_SCHEDULER_cancel (fc->client_to_service_task);
490 fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
491 }
492 fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
493#if DEBUG_SERVICE_MANAGER
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "Failed to connected to service `%s' at `%s', will try again in %llu ms\n",
496 fc->listen_info->serviceName,
497 GNUNET_a2s (fc->listen_info->service_addr,
498 fc->listen_info->service_addr_len),
499 (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
500 rem).rel_value);
501#endif
502 rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
503 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
504 fc->start_task =
505 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_min
506 (fc->back_off, rem), &start_forwarding,
507 fc);
508 }
509 else
510 {
511#if DEBUG_SERVICE_MANAGER
512 if (fc->service_to_client_bufferDataLength != 0)
513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
514 "Error receiving from service: %s\n", STRERROR (errno));
515#endif
516 closeClientAndServiceSockets (fc, REASON_SERVICE_TO_CLIENT);
517 }
518 return;
519 }
520 fc->first_write_done = GNUNET_YES;
521#if DEBUG_SERVICE_MANAGER
522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes for client\n",
523 fc->service_to_client_bufferDataLength);
524#endif
525 fc->service_to_client_task =
526 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
527 fc->armClientSocket, &forwardToClient,
528 fc);
529}
530
531
532/**
533 * Forward client message to service
534 *
535 * @param cls callback data, struct ForwardedConnection for the communication between client and service
536 * @param tc scheduler context
537 */
538static void
539forwardToService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
540{
541 struct ForwardedConnection *fc = cls;
542 ssize_t numberOfBytesSent;
543 struct GNUNET_TIME_Relative rem;
544
545 fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
546 if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) &&
547 (fc->first_write_done != GNUNET_YES))
548 {
549 closeClientAndServiceSockets (fc, REASON_ERROR);
550 return;
551 }
552 if (GNUNET_YES !=
553 GNUNET_NETWORK_fdset_isset (tc->write_ready, fc->armServiceSocket))
554 {
555 fc->client_to_service_task =
556 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
557 fc->armServiceSocket, &forwardToService,
558 fc);
559 return;
560 }
561 numberOfBytesSent =
562 GNUNET_NETWORK_socket_send (fc->armServiceSocket,
563 fc->client_to_service_bufferPos,
564 fc->client_to_service_bufferDataLength);
565 if (numberOfBytesSent <= 0)
566 {
567 if (GNUNET_YES != fc->first_write_done)
568 {
569 GNUNET_break (GNUNET_OK ==
570 GNUNET_NETWORK_socket_close (fc->armServiceSocket));
571 fc->armServiceSocket = NULL;
572 if ((fc->service_to_client_bufferDataLength == 0) &&
573 (fc->service_to_client_task != GNUNET_SCHEDULER_NO_TASK))
574 {
575 GNUNET_SCHEDULER_cancel (fc->service_to_client_task);
576 fc->service_to_client_task = GNUNET_SCHEDULER_NO_TASK;
577 }
578 fc->back_off = GNUNET_TIME_relative_multiply (fc->back_off, 2);
579#if DEBUG_SERVICE_MANAGER
580 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
581 "Failed to connect to service `%s' at `%s', will try again in %llu ms\n",
582 fc->listen_info->serviceName,
583 GNUNET_a2s (fc->listen_info->service_addr,
584 fc->listen_info->service_addr_len),
585 (unsigned long long) GNUNET_TIME_relative_min (fc->back_off,
586 rem).rel_value);
587#endif
588 rem = GNUNET_TIME_absolute_get_remaining (fc->timeout);
589 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
590 fc->start_task =
591 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_min
592 (fc->back_off, rem), &start_forwarding,
593 fc);
594 }
595 else
596 {
597 if ((errno != EPIPE) && (errno != ECONNRESET))
598 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
599 "Failed to forward data to service: %s\n",
600 STRERROR (errno));
601 closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
602 }
603 return;
604 }
605#if DEBUG_SERVICE_MANAGER
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarded %d bytes to service\n",
607 numberOfBytesSent);
608#endif
609 fc->first_write_done = GNUNET_YES;
610 if (numberOfBytesSent < fc->client_to_service_bufferDataLength)
611 {
612 fc->client_to_service_bufferPos += numberOfBytesSent;
613 fc->client_to_service_bufferDataLength -= numberOfBytesSent;
614 fc->client_to_service_task =
615 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
616 fc->armServiceSocket, &forwardToService,
617 fc);
618 return;
619 }
620 fc->client_to_service_task =
621 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
622 fc->armClientSocket, &receiveFromClient,
623 fc);
624}
625
626
627/**
628 * Read data from the client and then forward it to the service.
629 *
630 * @param cls callback data, struct ForwardedConnection for the communication between client and service
631 * @param tc context
632 */
633static void
634receiveFromClient (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
635{
636 struct ForwardedConnection *fc = cls;
637
638 fc->client_to_service_task = GNUNET_SCHEDULER_NO_TASK;
639 if (GNUNET_YES !=
640 GNUNET_NETWORK_fdset_isset (tc->read_ready, fc->armClientSocket))
641 {
642 fc->client_to_service_task =
643 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
644 fc->armClientSocket, &receiveFromClient,
645 fc);
646 return;
647 }
648 fc->client_to_service_bufferPos = fc->client_to_service_buffer;
649 fc->client_to_service_bufferDataLength =
650 GNUNET_NETWORK_socket_recv (fc->armClientSocket,
651 fc->client_to_service_buffer, BUFFER_SIZE);
652 if (fc->client_to_service_bufferDataLength <= 0)
653 {
654 if (fc->client_to_service_bufferDataLength == 0)
655 {
656#if DEBUG_SERVICE_MANAGER
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Client closed connection with service `%s'\n",
659 fc->listen_info->serviceName);
660#endif
661 }
662 else
663 {
664#if DEBUG_SERVICE_MANAGER
665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error receiving from client: %s\n",
666 STRERROR (errno));
667#endif
668 }
669 closeClientAndServiceSockets (fc, REASON_CLIENT_TO_SERVICE);
670 return;
671 }
672#if DEBUG_SERVICE_MANAGER
673 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received %d bytes for service\n",
674 fc->client_to_service_bufferDataLength);
675#endif
676 if (fc->armServiceSocket != NULL)
677 fc->client_to_service_task =
678 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
679 fc->armServiceSocket, &forwardToService,
680 fc);
681 else
682 /* We have not added any task with fc as a closure, so we're
683 * dropping our reference to fc
684 */
685 fc->reference_count -= 1;
686}
687
688
689static void
690fc_acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
691{
692 struct ServiceListeningInfo *sli = cls;
693 struct ForwardedConnection *fc = sli->fc;
694
695 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY))
696 {
697 GNUNET_assert (GNUNET_OK ==
698 GNUNET_NETWORK_socket_close (sli->listeningSocket));
699 closeClientAndServiceSockets (fc, REASON_ERROR);
700 GNUNET_free (sli);
701 return;
702 }
703#if DEBUG_SERVICE_MANAGER
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "Connected to service, now starting forwarding\n");
706#endif
707 fc->armServiceSocket = sli->listeningSocket;
708 GNUNET_free (fc->listen_info->service_addr);
709 fc->listen_info->service_addr = sli->service_addr;
710 fc->listen_info->service_addr_len = sli->service_addr_len;
711 /* Drop fc reference count prematurely, it'll be incremented
712 * once or twice in the following conditional branches.
713 * This is, apparently, the place where reference count increases
714 * past 1.
715 */
716 fc->reference_count -= 1;
717 if (fc->client_to_service_task == GNUNET_SCHEDULER_NO_TASK)
718 {
719 if (fc->client_to_service_bufferDataLength == 0)
720 fc->client_to_service_task =
721 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
722 fc->armClientSocket,
723 &receiveFromClient, fc);
724 else
725 fc->client_to_service_task =
726 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
727 fc->armServiceSocket,
728 &forwardToService, fc);
729 fc->reference_count += 1;
730 }
731 if (fc->service_to_client_task == GNUNET_SCHEDULER_NO_TASK)
732 {
733 if (fc->service_to_client_bufferDataLength == 0)
734 fc->service_to_client_task =
735 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
736 fc->armServiceSocket,
737 &receiveFromService, fc);
738 else
739 fc->service_to_client_task =
740 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
741 fc->armClientSocket, &forwardToClient,
742 fc);
743 fc->reference_count += 1;
744 }
745 GNUNET_free (sli);
746}
747
748
749static struct ServiceListeningInfo *
750service_try_to_connect (const struct sockaddr *addr, int pf, socklen_t addrlen,
751 struct ForwardedConnection *fc)
752{
753 struct GNUNET_NETWORK_Handle *sock;
754 struct ServiceListeningInfo *serviceListeningInfo;
755
756 sock = GNUNET_NETWORK_socket_create (pf, SOCK_STREAM, 0);
757 if (sock == NULL)
758 {
759 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
760 return NULL;
761 }
762 if ((GNUNET_SYSERR == GNUNET_NETWORK_socket_connect (sock, addr, addrlen)) &&
763 (errno != EINPROGRESS))
764 {
765 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
766 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
767 return NULL;
768 }
769 serviceListeningInfo = GNUNET_malloc (sizeof (struct ServiceListeningInfo));
770 serviceListeningInfo->serviceName = NULL;
771 serviceListeningInfo->service_addr = GNUNET_malloc (addrlen);
772 memcpy (serviceListeningInfo->service_addr, addr, addrlen);
773 serviceListeningInfo->service_addr_len = addrlen;
774 serviceListeningInfo->listeningSocket = sock;
775 serviceListeningInfo->fc = fc;
776 serviceListeningInfo->acceptTask =
777 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
778 serviceListeningInfo->listeningSocket,
779 &fc_acceptConnection,
780 serviceListeningInfo);
781 return serviceListeningInfo;
782}
783
784
785/**
786 *
787 */
788static void
789start_forwarding (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
790{
791 struct ForwardedConnection *fc = cls;
792 struct ServiceListeningInfo *sc;
793 struct sockaddr_in target_ipv4;
794 struct sockaddr_in6 target_ipv6;
795 const struct sockaddr_in *v4;
796 const struct sockaddr_in6 *v6;
797 char listen_address[INET6_ADDRSTRLEN];
798
799 fc->start_task = GNUNET_SCHEDULER_NO_TASK;
800 if ((NULL != tc) && (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
801 {
802 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
803 _("Unable to forward to service `%s': shutdown\n"),
804 fc->listen_info->serviceName);
805 closeClientAndServiceSockets (fc, REASON_ERROR);
806 return;
807 }
808 if (0 == GNUNET_TIME_absolute_get_remaining (fc->timeout).rel_value)
809 {
810 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
811 _
812 ("Unable to forward to service `%s': timeout before connect\n"),
813 fc->listen_info->serviceName);
814 closeClientAndServiceSockets (fc, REASON_ERROR);
815 return;
816 }
817 switch (fc->listen_info->service_addr->sa_family)
818 {
819 case AF_UNSPEC:
820 GNUNET_break (0);
821 closeClientAndServiceSockets (fc, REASON_ERROR);
822 return;
823 case AF_INET:
824 v4 = (const struct sockaddr_in *) fc->listen_info->service_addr;
825 inet_ntop (fc->listen_info->service_addr->sa_family,
826 (const void *) &v4->sin_addr, listen_address, INET_ADDRSTRLEN);
827 if (0 == strncmp (listen_address, "0.0.0.0", 7))
828 {
829 /* connect to [::1] and 127.0.0.1 instead of [::] and 0.0.0.0 */
830 memset (&target_ipv4, 0, sizeof (target_ipv4));
831 GNUNET_assert (1 ==
832 inet_pton (AF_INET, "127.0.0.1", &target_ipv4.sin_addr));
833 target_ipv4.sin_family = AF_INET;
834 target_ipv4.sin_port = v4->sin_port;
835 v4 = &target_ipv4;
836 }
837 sc = service_try_to_connect ((const struct sockaddr *) v4, PF_INET,
838 sizeof (struct sockaddr_in), fc);
839 break;
840 case AF_INET6:
841 v6 = (struct sockaddr_in6 *) fc->listen_info->service_addr;
842 inet_ntop (fc->listen_info->service_addr->sa_family,
843 (const void *) &v6->sin6_addr, listen_address, INET6_ADDRSTRLEN);
844 if ((strncmp (listen_address, "[::]:", 5) == 0) ||
845 (strncmp (listen_address, "::", 2) == 0))
846 {
847 memset (&target_ipv6, 0, sizeof (target_ipv6));
848 target_ipv6.sin6_addr = in6addr_loopback;
849 target_ipv6.sin6_family = AF_INET6;
850 target_ipv6.sin6_port = v6->sin6_port;
851 v6 = &target_ipv6;
852 }
853 sc = service_try_to_connect ((const struct sockaddr *) v6, PF_INET6,
854 sizeof (struct sockaddr_in6), fc);
855 break;
856 case AF_UNIX:
857 sc = service_try_to_connect (fc->listen_info->service_addr, PF_UNIX,
858 fc->listen_info->service_addr_len, fc);
859 break;
860 default:
861 GNUNET_break (0);
862 closeClientAndServiceSockets (fc, REASON_ERROR);
863 return;
864 }
865 if (NULL == sc)
866 {
867 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
868 _("Unable to start service `%s': %s\n"),
869 fc->listen_info->serviceName, STRERROR (errno));
870 closeClientAndServiceSockets (fc, REASON_ERROR);
871 return;
872 }
873}
874
875
876/**
877 * 165 *
878 */ 166 */
879int 167int
@@ -904,68 +192,6 @@ stop_listening (const char *serviceName)
904 return ret; 192 return ret;
905} 193}
906 194
907/**
908 * First connection has come to the listening socket associated with the service,
909 * create the service in order to relay the incoming connection to it
910 *
911 * @param cls callback data, struct ServiceListeningInfo describing a listen socket
912 * @param tc context
913 */
914static void
915acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
916
917
918static void
919accept_and_forward (struct ServiceListeningInfo *serviceListeningInfo)
920{
921 struct ForwardedConnection *fc;
922
923 fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
924 fc->reference_count = 1;
925 fc->listen_info = serviceListeningInfo;
926 fc->service_to_client_bufferPos = fc->service_to_client_buffer;
927 fc->client_to_service_bufferPos = fc->client_to_service_buffer;
928 fc->client_addr_len = sizeof (fc->client_addr);
929 fc->armClientSocket =
930 GNUNET_NETWORK_socket_accept (serviceListeningInfo->listeningSocket,
931 (struct sockaddr *) fc->client_addr,
932 &fc->client_addr_len);
933 if (NULL == fc->armClientSocket)
934 {
935 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
936 _("Unable to accept connection for service `%s': %s\n"),
937 serviceListeningInfo->serviceName, STRERROR (errno));
938 GNUNET_free (fc);
939 GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head,
940 serviceListeningInfoList_tail,
941 serviceListeningInfo);
942 serviceListeningInfo->acceptTask =
943 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
944 serviceListeningInfo->listeningSocket,
945 &acceptConnection, serviceListeningInfo);
946 return;
947 }
948 GNUNET_break (GNUNET_OK ==
949 GNUNET_NETWORK_socket_close
950 (serviceListeningInfo->listeningSocket));
951 start_service (NULL, serviceListeningInfo->serviceName, NULL);
952 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Service `%s' started\n"),
953 fc->listen_info->serviceName);
954 fc->timeout =
955 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_SERVICE_TIMEOUT);
956 fc->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
957 fc->client_to_service_task =
958 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
959 fc->armClientSocket, &receiveFromClient,
960 fc);
961 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == fc->start_task);
962 /* We're creating another chain of tasks for this fc that
963 * will have its own reference to it.
964 */
965 fc->reference_count += 1;
966 fc->start_task = GNUNET_SCHEDULER_add_now (&start_forwarding, fc);
967}
968
969 195
970/** 196/**
971 * First connection has come to the listening socket associated with the service, 197 * First connection has come to the listening socket associated with the service,
@@ -982,26 +208,12 @@ acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
982 struct ServiceListeningInfo *next; 208 struct ServiceListeningInfo *next;
983 SOCKTYPE *lsocks; 209 SOCKTYPE *lsocks;
984 unsigned int ls; 210 unsigned int ls;
985 int use_lsocks;
986 211
987 sli->acceptTask = GNUNET_SCHEDULER_NO_TASK; 212 sli->acceptTask = GNUNET_SCHEDULER_NO_TASK;
988 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) 213 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
989 return; 214 return;
990 GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head, 215 GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
991 serviceListeningInfoList_tail, sli); 216 serviceListeningInfoList_tail, sli);
992 use_lsocks = GNUNET_YES;
993 if ((GNUNET_YES ==
994 GNUNET_CONFIGURATION_have_value (cfg, "arm",
995 "ENABLE_INTERCEPTOR")) &&
996 (GNUNET_YES ==
997 GNUNET_CONFIGURATION_get_value_yesno (cfg, "arm",
998 "ENABLE_INTERCEPTOR")) )
999 use_lsocks = GNUNET_NO;
1000 if (GNUNET_YES != use_lsocks)
1001 {
1002 accept_and_forward (sli);
1003 return;
1004 }
1005 lsocks = NULL; 217 lsocks = NULL;
1006 ls = 0; 218 ls = 0;
1007 next = serviceListeningInfoList_head; 219 next = serviceListeningInfoList_head;