diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-12-06 20:20:46 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-12-06 20:20:46 +0000 |
commit | 03b7f628dabad307fb8f81ff90d356f05e75d9ff (patch) | |
tree | 85f4b89d48ef014b3911bdd60bedbe500d073253 /src/arm | |
parent | d473cdc8138214fe65e5b74221584fec8df5785a (diff) | |
download | gnunet-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.c | 790 |
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 | |||
59 | struct 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 | */ | ||
110 | struct 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 | */ | ||
289 | static void | ||
290 | closeClientAndServiceSockets (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 | */ | ||
359 | static void | ||
360 | receiveFromClient (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 | */ | ||
369 | static void | ||
370 | receiveFromService (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
371 | |||
372 | |||
373 | /** | ||
374 | * | ||
375 | */ | ||
376 | static void | ||
377 | start_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 | */ | ||
387 | static void | ||
388 | forwardToClient (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 | */ | ||
444 | static void | ||
445 | receiveFromService (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 | */ | ||
538 | static void | ||
539 | forwardToService (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 | */ | ||
633 | static void | ||
634 | receiveFromClient (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 | |||
689 | static void | ||
690 | fc_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 | |||
749 | static struct ServiceListeningInfo * | ||
750 | service_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 | */ | ||
788 | static void | ||
789 | start_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 | */ |
879 | int | 167 | int |
@@ -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 | */ | ||
914 | static void | ||
915 | acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
916 | |||
917 | |||
918 | static void | ||
919 | accept_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; |