aboutsummaryrefslogtreecommitdiff
path: root/src/transport/tcp_connection_legacy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/tcp_connection_legacy.c')
-rw-r--r--src/transport/tcp_connection_legacy.c1647
1 files changed, 1647 insertions, 0 deletions
diff --git a/src/transport/tcp_connection_legacy.c b/src/transport/tcp_connection_legacy.c
new file mode 100644
index 000000000..f5253445d
--- /dev/null
+++ b/src/transport/tcp_connection_legacy.c
@@ -0,0 +1,1647 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
4
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
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file util/connection.c
23 * @brief TCP connection management
24 * @author Christian Grothoff
25 *
26 * This code is rather complex. Only modify it if you
27 * 1) Have a NEW testcase showing that the new code
28 * is needed and correct
29 * 2) All EXISTING testcases pass with the new code
30 * These rules should apply in general, but for this
31 * module they are VERY, VERY important.
32 */
33#include "platform.h"
34#include "gnunet_util_lib.h"
35#include "gnunet_resolver_service.h"
36
37
38
39#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-connection", syscall)
40
41
42/**
43 * Transmission handle. There can only be one for each connection.
44 */
45struct GNUNET_CONNECTION_TransmitHandle
46{
47
48 /**
49 * Function to call if the send buffer has notify_size
50 * bytes available.
51 */
52 GNUNET_CONNECTION_TransmitReadyNotify notify_ready;
53
54 /**
55 * Closure for notify_ready.
56 */
57 void *notify_ready_cls;
58
59 /**
60 * Our connection handle.
61 */
62 struct GNUNET_CONNECTION_Handle *connection;
63
64 /**
65 * Timeout for receiving (in absolute time).
66 */
67 struct GNUNET_TIME_Absolute transmit_timeout;
68
69 /**
70 * Task called on timeout.
71 */
72 struct GNUNET_SCHEDULER_Task * timeout_task;
73
74 /**
75 * At what number of bytes available in the
76 * write buffer should the notify method be called?
77 */
78 size_t notify_size;
79
80};
81
82
83/**
84 * During connect, we try multiple possible IP addresses
85 * to find out which one might work.
86 */
87struct AddressProbe
88{
89
90 /**
91 * This is a linked list.
92 */
93 struct AddressProbe *next;
94
95 /**
96 * This is a doubly-linked list.
97 */
98 struct AddressProbe *prev;
99
100 /**
101 * The address; do not free (allocated at the end of this struct).
102 */
103 const struct sockaddr *addr;
104
105 /**
106 * Underlying OS's socket.
107 */
108 struct GNUNET_NETWORK_Handle *sock;
109
110 /**
111 * Connection for which we are probing.
112 */
113 struct GNUNET_CONNECTION_Handle *connection;
114
115 /**
116 * Lenth of addr.
117 */
118 socklen_t addrlen;
119
120 /**
121 * Task waiting for the connection to finish connecting.
122 */
123 struct GNUNET_SCHEDULER_Task * task;
124};
125
126
127/**
128 * @brief handle for a network connection
129 */
130struct GNUNET_CONNECTION_Handle
131{
132
133 /**
134 * Configuration to use.
135 */
136 const struct GNUNET_CONFIGURATION_Handle *cfg;
137
138 /**
139 * Linked list of sockets we are currently trying out
140 * (during connect).
141 */
142 struct AddressProbe *ap_head;
143
144 /**
145 * Linked list of sockets we are currently trying out
146 * (during connect).
147 */
148 struct AddressProbe *ap_tail;
149
150 /**
151 * Network address of the other end-point, may be NULL.
152 */
153 struct sockaddr *addr;
154
155 /**
156 * Pointer to the hostname if connection was
157 * created using DNS lookup, otherwise NULL.
158 */
159 char *hostname;
160
161 /**
162 * Underlying OS's socket, set to NULL after fatal errors.
163 */
164 struct GNUNET_NETWORK_Handle *sock;
165
166 /**
167 * Function to call on data received, NULL if no receive is pending.
168 */
169 GNUNET_CONNECTION_Receiver receiver;
170
171 /**
172 * Closure for @e receiver.
173 */
174 void *receiver_cls;
175
176 /**
177 * Pointer to our write buffer.
178 */
179 char *write_buffer;
180
181 /**
182 * Current size of our @e write_buffer.
183 */
184 size_t write_buffer_size;
185
186 /**
187 * Current write-offset in @e write_buffer (where
188 * would we write next).
189 */
190 size_t write_buffer_off;
191
192 /**
193 * Current read-offset in @e write_buffer (how many
194 * bytes have already been sent).
195 */
196 size_t write_buffer_pos;
197
198 /**
199 * Length of @e addr.
200 */
201 socklen_t addrlen;
202
203 /**
204 * Read task that we may need to wait for.
205 */
206 struct GNUNET_SCHEDULER_Task *read_task;
207
208 /**
209 * Write task that we may need to wait for.
210 */
211 struct GNUNET_SCHEDULER_Task *write_task;
212
213 /**
214 * Handle to a pending DNS lookup request.
215 */
216 struct GNUNET_RESOLVER_RequestHandle *dns_active;
217
218 /**
219 * The handle we return for #GNUNET_CONNECTION_notify_transmit_ready().
220 */
221 struct GNUNET_CONNECTION_TransmitHandle nth;
222
223 /**
224 * Timeout for receiving (in absolute time).
225 */
226 struct GNUNET_TIME_Absolute receive_timeout;
227
228 /**
229 * Maximum number of bytes to read (for receiving).
230 */
231 size_t max;
232
233 /**
234 * Port to connect to.
235 */
236 uint16_t port;
237
238 /**
239 * When shutdown, do not ever actually close the socket, but
240 * free resources. Only should ever be set if using program
241 * termination as a signal (because only then will the leaked
242 * socket be freed!)
243 */
244 int8_t persist;
245
246 /**
247 * Usually 0. Set to 1 if this handle is in use, and should
248 * #GNUNET_CONNECTION_destroy() be called right now, the action needs
249 * to be deferred by setting it to -1.
250 */
251 int8_t destroy_later;
252
253 /**
254 * Handle to subsequent connection after proxy handshake completes,
255 */
256 struct GNUNET_CONNECTION_Handle *proxy_handshake;
257
258};
259
260
261/**
262 * Set the persist option on this connection handle. Indicates
263 * that the underlying socket or fd should never really be closed.
264 * Used for indicating process death.
265 *
266 * @param connection the connection to set persistent
267 */
268void
269GNUNET_CONNECTION_persist_ (struct GNUNET_CONNECTION_Handle *connection)
270{
271 connection->persist = GNUNET_YES;
272}
273
274
275/**
276 * Disable the "CORK" feature for communication with the given connection,
277 * forcing the OS to immediately flush the buffer on transmission
278 * instead of potentially buffering multiple messages. Essentially
279 * reduces the OS send buffers to zero.
280 * Used to make sure that the last messages sent through the connection
281 * reach the other side before the process is terminated.
282 *
283 * @param connection the connection to make flushing and blocking
284 * @return #GNUNET_OK on success
285 */
286int
287GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle *connection)
288{
289 return GNUNET_NETWORK_socket_disable_corking (connection->sock);
290}
291
292
293/**
294 * Create a connection handle by boxing an existing OS socket. The OS
295 * socket should henceforth be no longer used directly.
296 * #GNUNET_connection_destroy() will close it.
297 *
298 * @param osSocket existing socket to box
299 * @return the boxed connection handle
300 */
301struct GNUNET_CONNECTION_Handle *
302GNUNET_CONNECTION_create_from_existing (struct GNUNET_NETWORK_Handle *osSocket)
303{
304 struct GNUNET_CONNECTION_Handle *connection;
305
306 connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
307 connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
308 connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
309 connection->sock = osSocket;
310 return connection;
311}
312
313
314/**
315 * Create a connection handle by accepting on a listen socket. This
316 * function may block if the listen socket has no connection ready.
317 *
318 * @param access_cb function to use to check if access is allowed
319 * @param access_cb_cls closure for @a access_cb
320 * @param lsock listen socket
321 * @return the connection handle, NULL on error
322 */
323struct GNUNET_CONNECTION_Handle *
324GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access_cb,
325 void *access_cb_cls,
326 struct GNUNET_NETWORK_Handle *lsock)
327{
328 struct GNUNET_CONNECTION_Handle *connection;
329 char addr[128];
330 socklen_t addrlen;
331 struct GNUNET_NETWORK_Handle *sock;
332 int aret;
333 struct sockaddr_in *v4;
334 struct sockaddr_in6 *v6;
335 struct sockaddr *sa;
336 void *uaddr;
337#ifdef SO_PEERCRED
338 struct ucred uc;
339 socklen_t olen;
340#endif
341 struct GNUNET_CONNECTION_Credentials *gcp;
342#if HAVE_GETPEEREID || defined(SO_PEERCRED) || HAVE_GETPEERUCRED
343 struct GNUNET_CONNECTION_Credentials gc;
344
345 gc.uid = 0;
346 gc.gid = 0;
347#endif
348
349 addrlen = sizeof (addr);
350 sock =
351 GNUNET_NETWORK_socket_accept (lsock,
352 (struct sockaddr *) &addr,
353 &addrlen);
354 if (NULL == sock)
355 {
356 if (EAGAIN != errno)
357 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
358 return NULL;
359 }
360 if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
361 {
362 GNUNET_break (0);
363 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
364 return NULL;
365 }
366
367 sa = (struct sockaddr *) addr;
368 v6 = (struct sockaddr_in6 *) addr;
369 if ( (AF_INET6 == sa->sa_family) &&
370 (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)) )
371 {
372 /* convert to V4 address */
373 v4 = GNUNET_new (struct sockaddr_in);
374 memset (v4, 0, sizeof (struct sockaddr_in));
375 v4->sin_family = AF_INET;
376#if HAVE_SOCKADDR_IN_SIN_LEN
377 v4->sin_len = (u_char) sizeof (struct sockaddr_in);
378#endif
379 GNUNET_memcpy (&v4->sin_addr,
380 &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
381 sizeof (struct in_addr)],
382 sizeof (struct in_addr));
383 v4->sin_port = v6->sin6_port;
384 uaddr = v4;
385 addrlen = sizeof (struct sockaddr_in);
386 }
387 else
388 {
389 uaddr = GNUNET_malloc (addrlen);
390 GNUNET_memcpy (uaddr, addr, addrlen);
391 }
392 gcp = NULL;
393 if (AF_UNIX == sa->sa_family)
394 {
395#if HAVE_GETPEEREID
396 /* most BSDs */
397 if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock),
398 &gc.uid,
399 &gc.gid))
400 gcp = &gc;
401#else
402#ifdef SO_PEERCRED
403 /* largely traditional GNU/Linux */
404 olen = sizeof (uc);
405 if ( (0 ==
406 getsockopt (GNUNET_NETWORK_get_fd (sock),
407 SOL_SOCKET,
408 SO_PEERCRED,
409 &uc,
410 &olen)) &&
411 (olen == sizeof (uc)) )
412 {
413 gc.uid = uc.uid;
414 gc.gid = uc.gid;
415 gcp = &gc;
416 }
417#else
418#if HAVE_GETPEERUCRED
419 /* this is for Solaris 10 */
420 ucred_t *uc;
421
422 uc = NULL;
423 if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc))
424 {
425 gc.uid = ucred_geteuid (uc);
426 gc.gid = ucred_getegid (uc);
427 gcp = &gc;
428 }
429 ucred_free (uc);
430#endif
431#endif
432#endif
433 }
434
435 if ( (NULL != access_cb) &&
436 (GNUNET_YES != (aret = access_cb (access_cb_cls,
437 gcp,
438 uaddr,
439 addrlen))) )
440 {
441 if (GNUNET_NO == aret)
442 LOG (GNUNET_ERROR_TYPE_INFO,
443 _("Access denied to `%s'\n"),
444 GNUNET_a2s (uaddr,
445 addrlen));
446 GNUNET_break (GNUNET_OK ==
447 GNUNET_NETWORK_socket_shutdown (sock,
448 SHUT_RDWR));
449 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
450 GNUNET_free (uaddr);
451 return NULL;
452 }
453 connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
454 connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
455 connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
456 connection->addr = uaddr;
457 connection->addrlen = addrlen;
458 connection->sock = sock;
459 LOG (GNUNET_ERROR_TYPE_INFO,
460 _("Accepting connection from `%s': %p\n"),
461 GNUNET_a2s (uaddr,
462 addrlen),
463 connection);
464 return connection;
465}
466
467
468/**
469 * Obtain the network address of the other party.
470 *
471 * @param connection the client to get the address for
472 * @param addr where to store the address
473 * @param addrlen where to store the length of the @a addr
474 * @return #GNUNET_OK on success
475 */
476int
477GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection,
478 void **addr,
479 size_t *addrlen)
480{
481 if ((NULL == connection->addr) || (0 == connection->addrlen))
482 return GNUNET_NO;
483 *addr = GNUNET_malloc (connection->addrlen);
484 GNUNET_memcpy (*addr, connection->addr, connection->addrlen);
485 *addrlen = connection->addrlen;
486 return GNUNET_OK;
487}
488
489
490/**
491 * Tell the receiver callback that we had an IO error.
492 *
493 * @param connection connection to signal error
494 * @param errcode error code to send
495 */
496static void
497signal_receive_error (struct GNUNET_CONNECTION_Handle *connection,
498 int errcode)
499{
500 GNUNET_CONNECTION_Receiver receiver;
501
502 LOG (GNUNET_ERROR_TYPE_DEBUG,
503 "Receive encounters error (%s), connection closed (%p)\n",
504 STRERROR (errcode),
505 connection);
506 GNUNET_assert (NULL != (receiver = connection->receiver));
507 connection->receiver = NULL;
508 receiver (connection->receiver_cls,
509 NULL,
510 0,
511 connection->addr,
512 connection->addrlen,
513 errcode);
514}
515
516
517/**
518 * Tell the receiver callback that a timeout was reached.
519 *
520 * @param connection connection to signal for
521 */
522static void
523signal_receive_timeout (struct GNUNET_CONNECTION_Handle *connection)
524{
525 GNUNET_CONNECTION_Receiver receiver;
526
527 LOG (GNUNET_ERROR_TYPE_DEBUG,
528 "Connection signals timeout to receiver (%p)!\n",
529 connection);
530 GNUNET_assert (NULL != (receiver = connection->receiver));
531 connection->receiver = NULL;
532 receiver (connection->receiver_cls, NULL, 0, NULL, 0, 0);
533}
534
535
536/**
537 * We failed to transmit data to the service, signal the error.
538 *
539 * @param connection handle that had trouble
540 * @param ecode error code (errno)
541 */
542static void
543signal_transmit_error (struct GNUNET_CONNECTION_Handle *connection,
544 int ecode)
545{
546 GNUNET_CONNECTION_TransmitReadyNotify notify;
547
548 LOG (GNUNET_ERROR_TYPE_DEBUG,
549 "Transmission encounterd error (%s), connection closed (%p)\n",
550 STRERROR (ecode),
551 connection);
552 if (NULL != connection->sock)
553 {
554 (void) GNUNET_NETWORK_socket_shutdown (connection->sock,
555 SHUT_RDWR);
556 GNUNET_break (GNUNET_OK ==
557 GNUNET_NETWORK_socket_close (connection->sock));
558 connection->sock = NULL;
559 GNUNET_assert (NULL == connection->write_task);
560 }
561 if (NULL != connection->read_task)
562 {
563 /* send errors trigger read errors... */
564 GNUNET_SCHEDULER_cancel (connection->read_task);
565 connection->read_task = NULL;
566 signal_receive_timeout (connection);
567 return;
568 }
569 if (NULL == connection->nth.notify_ready)
570 return; /* nobody to tell about it */
571 notify = connection->nth.notify_ready;
572 connection->nth.notify_ready = NULL;
573 notify (connection->nth.notify_ready_cls,
574 0,
575 NULL);
576}
577
578
579/**
580 * We've failed for good to establish a connection (timeout or
581 * no more addresses to try).
582 *
583 * @param connection the connection we tried to establish
584 */
585static void
586connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection)
587{
588 LOG (GNUNET_ERROR_TYPE_INFO,
589 "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n",
590 connection->hostname,
591 connection->port);
592 GNUNET_break (NULL == connection->ap_head);
593 GNUNET_break (NULL == connection->ap_tail);
594 GNUNET_break (GNUNET_NO == connection->dns_active);
595 GNUNET_break (NULL == connection->sock);
596 GNUNET_assert (NULL == connection->write_task);
597 GNUNET_assert (NULL == connection->proxy_handshake);
598
599 /* signal errors for jobs that used to wait on the connection */
600 connection->destroy_later = 1;
601 if (NULL != connection->receiver)
602 signal_receive_error (connection,
603 ECONNREFUSED);
604 if (NULL != connection->nth.notify_ready)
605 {
606 GNUNET_assert (NULL != connection->nth.timeout_task);
607 GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
608 connection->nth.timeout_task = NULL;
609 signal_transmit_error (connection,
610 ECONNREFUSED);
611 }
612 if (-1 == connection->destroy_later)
613 {
614 /* do it now */
615 connection->destroy_later = 0;
616 GNUNET_CONNECTION_destroy (connection);
617 return;
618 }
619 connection->destroy_later = 0;
620}
621
622
623/**
624 * We are ready to transmit (or got a timeout).
625 *
626 * @param cls our connection handle
627 */
628static void
629transmit_ready (void *cls);
630
631
632/**
633 * This function is called once we either timeout or have data ready
634 * to read.
635 *
636 * @param cls connection to read from
637 */
638static void
639receive_ready (void *cls);
640
641
642/**
643 * We've succeeded in establishing a connection.
644 *
645 * @param connection the connection we tried to establish
646 */
647static void
648connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
649{
650 LOG (GNUNET_ERROR_TYPE_DEBUG,
651 "Connection to `%s' succeeded! (%p)\n",
652 GNUNET_a2s (connection->addr,
653 connection->addrlen),
654 connection);
655 /* trigger jobs that waited for the connection */
656 if (NULL != connection->receiver)
657 {
658 LOG (GNUNET_ERROR_TYPE_DEBUG,
659 "Connection succeeded, starting with receiving data (%p)\n",
660 connection);
661 GNUNET_assert (NULL == connection->read_task);
662 connection->read_task =
663 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
664 (connection->receive_timeout),
665 connection->sock,
666 &receive_ready, connection);
667 }
668 if (NULL != connection->nth.notify_ready)
669 {
670 LOG (GNUNET_ERROR_TYPE_DEBUG,
671 "Connection succeeded, starting with sending data (%p)\n",
672 connection);
673 GNUNET_assert (connection->nth.timeout_task != NULL);
674 GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
675 connection->nth.timeout_task = NULL;
676 GNUNET_assert (connection->write_task == NULL);
677 connection->write_task =
678 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
679 (connection->nth.transmit_timeout), connection->sock,
680 &transmit_ready, connection);
681 }
682}
683
684
685/**
686 * Scheduler let us know that we're either ready to write on the
687 * socket OR connect timed out. Do the right thing.
688 *
689 * @param cls the `struct AddressProbe *` with the address that we are probing
690 */
691static void
692connect_probe_continuation (void *cls)
693{
694 struct AddressProbe *ap = cls;
695 struct GNUNET_CONNECTION_Handle *connection = ap->connection;
696 const struct GNUNET_SCHEDULER_TaskContext *tc;
697 struct AddressProbe *pos;
698 int error;
699 socklen_t len;
700
701 GNUNET_assert (NULL != ap->sock);
702 GNUNET_CONTAINER_DLL_remove (connection->ap_head,
703 connection->ap_tail,
704 ap);
705 len = sizeof (error);
706 errno = 0;
707 error = 0;
708 tc = GNUNET_SCHEDULER_get_task_context ();
709 if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
710 (GNUNET_OK !=
711 GNUNET_NETWORK_socket_getsockopt (ap->sock,
712 SOL_SOCKET,
713 SO_ERROR,
714 &error,
715 &len)) ||
716 (0 != error) )
717 {
718 GNUNET_break (GNUNET_OK ==
719 GNUNET_NETWORK_socket_close (ap->sock));
720 GNUNET_free (ap);
721 if ( (NULL == connection->ap_head) &&
722 (GNUNET_NO == connection->dns_active) &&
723 (NULL == connection->proxy_handshake) )
724 connect_fail_continuation (connection);
725 return;
726 }
727 GNUNET_assert (NULL == connection->sock);
728 connection->sock = ap->sock;
729 GNUNET_assert (NULL == connection->addr);
730 connection->addr = GNUNET_malloc (ap->addrlen);
731 GNUNET_memcpy (connection->addr, ap->addr, ap->addrlen);
732 connection->addrlen = ap->addrlen;
733 GNUNET_free (ap);
734 /* cancel all other attempts */
735 while (NULL != (pos = connection->ap_head))
736 {
737 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
738 GNUNET_SCHEDULER_cancel (pos->task);
739 GNUNET_CONTAINER_DLL_remove (connection->ap_head,
740 connection->ap_tail,
741 pos);
742 GNUNET_free (pos);
743 }
744 connect_success_continuation (connection);
745}
746
747
748/**
749 * Try to establish a connection given the specified address.
750 * This function is called by the resolver once we have a DNS reply.
751 *
752 * @param cls our `struct GNUNET_CONNECTION_Handle *`
753 * @param addr address to try, NULL for "last call"
754 * @param addrlen length of @a addr
755 */
756static void
757try_connect_using_address (void *cls,
758 const struct sockaddr *addr,
759 socklen_t addrlen)
760{
761 struct GNUNET_CONNECTION_Handle *connection = cls;
762 struct AddressProbe *ap;
763 struct GNUNET_TIME_Relative delay;
764
765 if (NULL == addr)
766 {
767 connection->dns_active = NULL;
768 if ((NULL == connection->ap_head) &&
769 (NULL == connection->sock) &&
770 (NULL == connection->proxy_handshake))
771 connect_fail_continuation (connection);
772 return;
773 }
774 if (NULL != connection->sock)
775 return; /* already connected */
776 GNUNET_assert (NULL == connection->addr);
777 /* try to connect */
778 LOG (GNUNET_ERROR_TYPE_DEBUG,
779 "Trying to connect using address `%s:%u/%s:%u'\n",
780 connection->hostname,
781 connection->port,
782 GNUNET_a2s (addr, addrlen),
783 connection->port);
784 ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
785 ap->addr = (const struct sockaddr *) &ap[1];
786 GNUNET_memcpy (&ap[1], addr, addrlen);
787 ap->addrlen = addrlen;
788 ap->connection = connection;
789
790 switch (ap->addr->sa_family)
791 {
792 case AF_INET:
793 ((struct sockaddr_in *) ap->addr)->sin_port = htons (connection->port);
794 break;
795 case AF_INET6:
796 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (connection->port);
797 break;
798 default:
799 GNUNET_break (0);
800 GNUNET_free (ap);
801 return; /* not supported by us */
802 }
803 ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
804 SOCK_STREAM, 0);
805 if (NULL == ap->sock)
806 {
807 GNUNET_free (ap);
808 return; /* not supported by OS */
809 }
810 LOG (GNUNET_ERROR_TYPE_INFO,
811 "Trying to connect to `%s' (%p)\n",
812 GNUNET_a2s (ap->addr, ap->addrlen),
813 connection);
814 if ((GNUNET_OK !=
815 GNUNET_NETWORK_socket_connect (ap->sock,
816 ap->addr,
817 ap->addrlen)) &&
818 (EINPROGRESS != errno))
819 {
820 /* maybe refused / unsupported address, try next */
821 LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
822 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
823 GNUNET_free (ap);
824 return;
825 }
826 GNUNET_CONTAINER_DLL_insert (connection->ap_head, connection->ap_tail, ap);
827 delay = GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT;
828 if (NULL != connection->nth.notify_ready)
829 delay = GNUNET_TIME_relative_min (delay,
830 GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout));
831 if (NULL != connection->receiver)
832 delay = GNUNET_TIME_relative_min (delay,
833 GNUNET_TIME_absolute_get_remaining (connection->receive_timeout));
834 ap->task = GNUNET_SCHEDULER_add_write_net (delay,
835 ap->sock,
836 &connect_probe_continuation,
837 ap);
838}
839
840
841/**
842 * Create a connection handle by (asynchronously) connecting to a host.
843 * This function returns immediately, even if the connection has not
844 * yet been established. This function only creates TCP connections.
845 *
846 * @param cfg configuration to use
847 * @param hostname name of the host to connect to
848 * @param port port to connect to
849 * @return the connection handle
850 */
851struct GNUNET_CONNECTION_Handle *
852GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
853 const char *hostname,
854 uint16_t port)
855{
856 struct GNUNET_CONNECTION_Handle *connection;
857
858 GNUNET_assert (0 < strlen (hostname)); /* sanity check */
859 connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
860 connection->cfg = cfg;
861 connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
862 connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
863 connection->port = port;
864 connection->hostname = GNUNET_strdup (hostname);
865 connection->dns_active =
866 GNUNET_RESOLVER_ip_get (connection->hostname,
867 AF_UNSPEC,
868 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
869 &try_connect_using_address,
870 connection);
871 return connection;
872}
873
874
875/**
876 * Create a connection handle by connecting to a UNIX domain service.
877 * This function returns immediately, even if the connection has not
878 * yet been established. This function only creates UNIX connections.
879 *
880 * @param cfg configuration to use
881 * @param unixpath path to connect to
882 * @return the connection handle, NULL on systems without UNIX support
883 */
884struct GNUNET_CONNECTION_Handle *
885GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct GNUNET_CONFIGURATION_Handle *cfg,
886 const char *unixpath)
887{
888#ifdef AF_UNIX
889 struct GNUNET_CONNECTION_Handle *connection;
890 struct sockaddr_un *un;
891
892 GNUNET_assert (0 < strlen (unixpath)); /* sanity check */
893 un = GNUNET_new (struct sockaddr_un);
894 un->sun_family = AF_UNIX;
895 strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
896#ifdef LINUX
897 {
898 int abstract;
899
900 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
901 "TESTING",
902 "USE_ABSTRACT_SOCKETS");
903 if (GNUNET_YES == abstract)
904 un->sun_path[0] = '\0';
905 }
906#endif
907#if HAVE_SOCKADDR_UN_SUN_LEN
908 un->sun_len = (u_char) sizeof (struct sockaddr_un);
909#endif
910 connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
911 connection->cfg = cfg;
912 connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
913 connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
914 connection->port = 0;
915 connection->hostname = NULL;
916 connection->addr = (struct sockaddr *) un;
917 connection->addrlen = sizeof (struct sockaddr_un);
918 connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX,
919 SOCK_STREAM,
920 0);
921 if (NULL == connection->sock)
922 {
923 GNUNET_free (connection->addr);
924 GNUNET_free (connection->write_buffer);
925 GNUNET_free (connection);
926 return NULL;
927 }
928 if ( (GNUNET_OK !=
929 GNUNET_NETWORK_socket_connect (connection->sock,
930 connection->addr,
931 connection->addrlen)) &&
932 (EINPROGRESS != errno) )
933 {
934 /* Just return; we expect everything to work eventually so don't fail HARD */
935 GNUNET_break (GNUNET_OK ==
936 GNUNET_NETWORK_socket_close (connection->sock));
937 connection->sock = NULL;
938 return connection;
939 }
940 connect_success_continuation (connection);
941 return connection;
942#else
943 return NULL;
944#endif
945}
946
947
948/**
949 * Create a connection handle by (asynchronously) connecting to a host.
950 * This function returns immediately, even if the connection has not
951 * yet been established. This function only creates TCP connections.
952 *
953 * @param s socket to connect
954 * @param serv_addr server address
955 * @param addrlen length of @a serv_addr
956 * @return the connection handle
957 */
958struct GNUNET_CONNECTION_Handle *
959GNUNET_CONNECTION_connect_socket (struct GNUNET_NETWORK_Handle *s,
960 const struct sockaddr *serv_addr,
961 socklen_t addrlen)
962{
963 struct GNUNET_CONNECTION_Handle *connection;
964
965 if ( (GNUNET_OK !=
966 GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) &&
967 (EINPROGRESS != errno) )
968 {
969 /* maybe refused / unsupported address, try next */
970 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
971 "connect");
972 LOG (GNUNET_ERROR_TYPE_DEBUG,
973 "Attempt to connect to `%s' failed\n",
974 GNUNET_a2s (serv_addr,
975 addrlen));
976 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
977 return NULL;
978 }
979 connection = GNUNET_CONNECTION_create_from_existing (s);
980 connection->addr = GNUNET_malloc (addrlen);
981 GNUNET_memcpy (connection->addr, serv_addr, addrlen);
982 connection->addrlen = addrlen;
983 LOG (GNUNET_ERROR_TYPE_INFO,
984 "Trying to connect to `%s' (%p)\n",
985 GNUNET_a2s (serv_addr, addrlen),
986 connection);
987 return connection;
988}
989
990
991/**
992 * Create a connection handle by creating a socket and
993 * (asynchronously) connecting to a host. This function returns
994 * immediately, even if the connection has not yet been established.
995 * This function only creates TCP connections.
996 *
997 * @param af_family address family to use
998 * @param serv_addr server address
999 * @param addrlen length of @a serv_addr
1000 * @return the connection handle
1001 */
1002struct GNUNET_CONNECTION_Handle *
1003GNUNET_CONNECTION_create_from_sockaddr (int af_family,
1004 const struct sockaddr *serv_addr,
1005 socklen_t addrlen)
1006{
1007 struct GNUNET_NETWORK_Handle *s;
1008
1009 s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
1010 if (NULL == s)
1011 {
1012 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
1013 "socket");
1014 return NULL;
1015 }
1016 return GNUNET_CONNECTION_connect_socket (s,
1017 serv_addr,
1018 addrlen);
1019}
1020
1021
1022/**
1023 * Check if connection is valid (no fatal errors have happened so far).
1024 * Note that a connection that is still trying to connect is considered
1025 * valid.
1026 *
1027 * @param connection connection to check
1028 * @return #GNUNET_YES if valid, #GNUNET_NO otherwise
1029 */
1030int
1031GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection)
1032{
1033 if ((NULL != connection->ap_head) ||
1034 (NULL != connection->dns_active) ||
1035 (NULL != connection->proxy_handshake))
1036 return GNUNET_YES; /* still trying to connect */
1037 if ( (0 != connection->destroy_later) ||
1038 (NULL == connection->sock) )
1039 return GNUNET_NO;
1040 return GNUNET_YES;
1041}
1042
1043
1044/**
1045 * Close the connection and free associated resources. There must
1046 * not be any pending requests for reading or writing to the
1047 * connection at this time.
1048 *
1049 * @param connection connection to destroy
1050 */
1051void
1052GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
1053{
1054 struct AddressProbe *pos;
1055
1056 if (0 != connection->destroy_later)
1057 {
1058 connection->destroy_later = -1;
1059 return;
1060 }
1061 LOG (GNUNET_ERROR_TYPE_DEBUG,
1062 "Shutting down connection (%p)\n",
1063 connection);
1064 GNUNET_assert (NULL == connection->nth.notify_ready);
1065 GNUNET_assert (NULL == connection->receiver);
1066 if (NULL != connection->write_task)
1067 {
1068 GNUNET_SCHEDULER_cancel (connection->write_task);
1069 connection->write_task = NULL;
1070 connection->write_buffer_off = 0;
1071 }
1072 if (NULL != connection->read_task)
1073 {
1074 GNUNET_SCHEDULER_cancel (connection->read_task);
1075 connection->read_task = NULL;
1076 }
1077 if (NULL != connection->nth.timeout_task)
1078 {
1079 GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
1080 connection->nth.timeout_task = NULL;
1081 }
1082 connection->nth.notify_ready = NULL;
1083 if (NULL != connection->dns_active)
1084 {
1085 GNUNET_RESOLVER_request_cancel (connection->dns_active);
1086 connection->dns_active = NULL;
1087 }
1088 if (NULL != connection->proxy_handshake)
1089 {
1090 /* GNUNET_CONNECTION_destroy (connection->proxy_handshake); */
1091 connection->proxy_handshake->destroy_later = -1;
1092 connection->proxy_handshake = NULL; /* Not leaked ??? */
1093 }
1094 while (NULL != (pos = connection->ap_head))
1095 {
1096 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
1097 GNUNET_SCHEDULER_cancel (pos->task);
1098 GNUNET_CONTAINER_DLL_remove (connection->ap_head,
1099 connection->ap_tail,
1100 pos);
1101 GNUNET_free (pos);
1102 }
1103 if ( (NULL != connection->sock) &&
1104 (GNUNET_YES != connection->persist) )
1105 {
1106 if ((GNUNET_OK !=
1107 GNUNET_NETWORK_socket_shutdown (connection->sock,
1108 SHUT_RDWR)) &&
1109 (ENOTCONN != errno) &&
1110 (ECONNRESET != errno) )
1111 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1112 "shutdown");
1113 }
1114 if (NULL != connection->sock)
1115 {
1116 if (GNUNET_YES != connection->persist)
1117 {
1118 GNUNET_break (GNUNET_OK ==
1119 GNUNET_NETWORK_socket_close (connection->sock));
1120 }
1121 else
1122 {
1123 GNUNET_NETWORK_socket_free_memory_only_ (connection->sock); /* at least no memory leak (we deliberately
1124 * leak the socket in this special case) ... */
1125 }
1126 }
1127 GNUNET_free_non_null (connection->addr);
1128 GNUNET_free_non_null (connection->hostname);
1129 GNUNET_free (connection->write_buffer);
1130 GNUNET_free (connection);
1131}
1132
1133
1134/**
1135 * This function is called once we either timeout
1136 * or have data ready to read.
1137 *
1138 * @param cls connection to read from
1139 */
1140static void
1141receive_ready (void *cls)
1142{
1143 struct GNUNET_CONNECTION_Handle *connection = cls;
1144 const struct GNUNET_SCHEDULER_TaskContext *tc;
1145 char buffer[connection->max];
1146 ssize_t ret;
1147 GNUNET_CONNECTION_Receiver receiver;
1148
1149 connection->read_task = NULL;
1150 tc = GNUNET_SCHEDULER_get_task_context ();
1151 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
1152 {
1153 LOG (GNUNET_ERROR_TYPE_DEBUG,
1154 "Receive from `%s' encounters error: timeout (%s, %p)\n",
1155 GNUNET_a2s (connection->addr,
1156 connection->addrlen),
1157 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (connection->receive_timeout),
1158 GNUNET_YES),
1159 connection);
1160 signal_receive_timeout (connection);
1161 return;
1162 }
1163 if (NULL == connection->sock)
1164 {
1165 /* connect failed for good */
1166 signal_receive_error (connection, ECONNREFUSED);
1167 return;
1168 }
1169 GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready,
1170 connection->sock));
1171RETRY:
1172 ret = GNUNET_NETWORK_socket_recv (connection->sock,
1173 buffer,
1174 connection->max);
1175 if (-1 == ret)
1176 {
1177 if (EINTR == errno)
1178 goto RETRY;
1179 signal_receive_error (connection, errno);
1180 return;
1181 }
1182 LOG (GNUNET_ERROR_TYPE_DEBUG,
1183 "receive_ready read %u/%u bytes from `%s' (%p)!\n",
1184 (unsigned int) ret,
1185 connection->max,
1186 GNUNET_a2s (connection->addr,
1187 connection->addrlen),
1188 connection);
1189 GNUNET_assert (NULL != (receiver = connection->receiver));
1190 connection->receiver = NULL;
1191 receiver (connection->receiver_cls,
1192 buffer,
1193 ret,
1194 connection->addr,
1195 connection->addrlen,
1196 0);
1197}
1198
1199
1200/**
1201 * Receive data from the given connection. Note that this function
1202 * will call @a receiver asynchronously using the scheduler. It will
1203 * "immediately" return. Note that there MUST only be one active
1204 * receive call per connection at any given point in time (so do not
1205 * call receive again until the receiver callback has been invoked).
1206 *
1207 * @param connection connection handle
1208 * @param max maximum number of bytes to read
1209 * @param timeout maximum amount of time to wait
1210 * @param receiver function to call with received data
1211 * @param receiver_cls closure for @a receiver
1212 */
1213void
1214GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection,
1215 size_t max,
1216 struct GNUNET_TIME_Relative timeout,
1217 GNUNET_CONNECTION_Receiver receiver,
1218 void *receiver_cls)
1219{
1220 GNUNET_assert ((NULL == connection->read_task) &&
1221 (NULL == connection->receiver));
1222 GNUNET_assert (NULL != receiver);
1223 connection->receiver = receiver;
1224 connection->receiver_cls = receiver_cls;
1225 connection->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1226 connection->max = max;
1227 if (NULL != connection->sock)
1228 {
1229 connection->read_task =
1230 GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
1231 (connection->receive_timeout),
1232 connection->sock,
1233 &receive_ready,
1234 connection);
1235 return;
1236 }
1237 if ((NULL == connection->dns_active) &&
1238 (NULL == connection->ap_head) &&
1239 (NULL == connection->proxy_handshake))
1240 {
1241 connection->receiver = NULL;
1242 receiver (receiver_cls,
1243 NULL, 0,
1244 NULL, 0,
1245 ETIMEDOUT);
1246 return;
1247 }
1248}
1249
1250
1251/**
1252 * Cancel receive job on the given connection. Note that the
1253 * receiver callback must not have been called yet in order
1254 * for the cancellation to be valid.
1255 *
1256 * @param connection connection handle
1257 * @return closure of the original receiver callback closure
1258 */
1259void *
1260GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection)
1261{
1262 if (NULL != connection->read_task)
1263 {
1264 GNUNET_assert (connection ==
1265 GNUNET_SCHEDULER_cancel (connection->read_task));
1266 connection->read_task = NULL;
1267 }
1268 connection->receiver = NULL;
1269 return connection->receiver_cls;
1270}
1271
1272
1273/**
1274 * Try to call the transmit notify method (check if we do
1275 * have enough space available first)!
1276 *
1277 * @param connection connection for which we should do this processing
1278 * @return #GNUNET_YES if we were able to call notify
1279 */
1280static int
1281process_notify (struct GNUNET_CONNECTION_Handle *connection)
1282{
1283 size_t used;
1284 size_t avail;
1285 size_t size;
1286 GNUNET_CONNECTION_TransmitReadyNotify notify;
1287
1288 LOG (GNUNET_ERROR_TYPE_DEBUG,
1289 "process_notify is running\n");
1290 GNUNET_assert (NULL == connection->write_task);
1291 if (NULL == (notify = connection->nth.notify_ready))
1292 {
1293 LOG (GNUNET_ERROR_TYPE_DEBUG,
1294 "No one to notify\n");
1295 return GNUNET_NO;
1296 }
1297 used = connection->write_buffer_off - connection->write_buffer_pos;
1298 avail = connection->write_buffer_size - used;
1299 size = connection->nth.notify_size;
1300 if (size > avail)
1301 {
1302 LOG (GNUNET_ERROR_TYPE_DEBUG,
1303 "Not enough buffer\n");
1304 return GNUNET_NO;
1305 }
1306 connection->nth.notify_ready = NULL;
1307 if (connection->write_buffer_size - connection->write_buffer_off < size)
1308 {
1309 /* need to compact */
1310 memmove (connection->write_buffer,
1311 &connection->write_buffer[connection->write_buffer_pos],
1312 used);
1313 connection->write_buffer_off -= connection->write_buffer_pos;
1314 connection->write_buffer_pos = 0;
1315 }
1316 avail = connection->write_buffer_size - connection->write_buffer_off;
1317 GNUNET_assert (avail >= size);
1318 size =
1319 notify (connection->nth.notify_ready_cls, avail,
1320 &connection->write_buffer[connection->write_buffer_off]);
1321 GNUNET_assert (size <= avail);
1322 if (0 != size)
1323 connection->write_buffer_off += size;
1324 return GNUNET_YES;
1325}
1326
1327
1328/**
1329 * Task invoked by the scheduler when a call to transmit
1330 * is timing out (we never got enough buffer space to call
1331 * the callback function before the specified timeout
1332 * expired).
1333 *
1334 * This task notifies the client about the timeout.
1335 *
1336 * @param cls the `struct GNUNET_CONNECTION_Handle`
1337 */
1338static void
1339transmit_timeout (void *cls)
1340{
1341 struct GNUNET_CONNECTION_Handle *connection = cls;
1342 GNUNET_CONNECTION_TransmitReadyNotify notify;
1343
1344 connection->nth.timeout_task = NULL;
1345 LOG (GNUNET_ERROR_TYPE_DEBUG,
1346 "Transmit to `%s:%u/%s' fails, time out reached (%p).\n",
1347 connection->hostname,
1348 connection->port,
1349 GNUNET_a2s (connection->addr,
1350 connection->addrlen),
1351 connection);
1352 notify = connection->nth.notify_ready;
1353 GNUNET_assert (NULL != notify);
1354 connection->nth.notify_ready = NULL;
1355 notify (connection->nth.notify_ready_cls,
1356 0,
1357 NULL);
1358}
1359
1360
1361/**
1362 * Task invoked by the scheduler when we failed to connect
1363 * at the time of being asked to transmit.
1364 *
1365 * This task notifies the client about the error.
1366 *
1367 * @param cls the `struct GNUNET_CONNECTION_Handle`
1368 */
1369static void
1370connect_error (void *cls)
1371{
1372 struct GNUNET_CONNECTION_Handle *connection = cls;
1373 GNUNET_CONNECTION_TransmitReadyNotify notify;
1374
1375 LOG (GNUNET_ERROR_TYPE_DEBUG,
1376 "Transmission request of size %u fails (%s/%u), connection failed (%p).\n",
1377 connection->nth.notify_size,
1378 connection->hostname,
1379 connection->port,
1380 connection);
1381 connection->write_task = NULL;
1382 notify = connection->nth.notify_ready;
1383 connection->nth.notify_ready = NULL;
1384 notify (connection->nth.notify_ready_cls,
1385 0,
1386 NULL);
1387}
1388
1389
1390/**
1391 * We are ready to transmit (or got a timeout).
1392 *
1393 * @param cls our connection handle
1394 */
1395static void
1396transmit_ready (void *cls)
1397{
1398 struct GNUNET_CONNECTION_Handle *connection = cls;
1399 GNUNET_CONNECTION_TransmitReadyNotify notify;
1400 const struct GNUNET_SCHEDULER_TaskContext *tc;
1401 ssize_t ret;
1402 size_t have;
1403
1404 LOG (GNUNET_ERROR_TYPE_DEBUG,
1405 "transmit_ready running (%p).\n",
1406 connection);
1407 GNUNET_assert (NULL != connection->write_task);
1408 connection->write_task = NULL;
1409 GNUNET_assert (NULL == connection->nth.timeout_task);
1410 tc = GNUNET_SCHEDULER_get_task_context ();
1411 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
1412 {
1413 LOG (GNUNET_ERROR_TYPE_DEBUG,
1414 "Transmit to `%s' fails, time out reached (%p).\n",
1415 GNUNET_a2s (connection->addr,
1416 connection->addrlen),
1417 connection);
1418 notify = connection->nth.notify_ready;
1419 GNUNET_assert (NULL != notify);
1420 connection->nth.notify_ready = NULL;
1421 notify (connection->nth.notify_ready_cls, 0, NULL);
1422 return;
1423 }
1424 GNUNET_assert (NULL != connection->sock);
1425 if (NULL == tc->write_ready)
1426 {
1427 /* special circumstances (in particular, PREREQ_DONE after
1428 * connect): not yet ready to write, but no "fatal" error either.
1429 * Hence retry. */
1430 goto SCHEDULE_WRITE;
1431 }
1432 if (! GNUNET_NETWORK_fdset_isset (tc->write_ready,
1433 connection->sock))
1434 {
1435 GNUNET_assert (NULL == connection->write_task);
1436 /* special circumstances (in particular, shutdown): not yet ready
1437 * to write, but no "fatal" error either. Hence retry. */
1438 goto SCHEDULE_WRITE;
1439 }
1440 GNUNET_assert (connection->write_buffer_off >= connection->write_buffer_pos);
1441 if ((NULL != connection->nth.notify_ready) &&
1442 (connection->write_buffer_size < connection->nth.notify_size))
1443 {
1444 connection->write_buffer =
1445 GNUNET_realloc (connection->write_buffer, connection->nth.notify_size);
1446 connection->write_buffer_size = connection->nth.notify_size;
1447 }
1448 process_notify (connection);
1449 have = connection->write_buffer_off - connection->write_buffer_pos;
1450 if (0 == have)
1451 {
1452 /* no data ready for writing, terminate write loop */
1453 return;
1454 }
1455 GNUNET_assert (have <= connection->write_buffer_size);
1456 GNUNET_assert (have + connection->write_buffer_pos <= connection->write_buffer_size);
1457 GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size);
1458RETRY:
1459 ret =
1460 GNUNET_NETWORK_socket_send (connection->sock,
1461 &connection->write_buffer[connection->write_buffer_pos],
1462 have);
1463 if (-1 == ret)
1464 {
1465 if (EINTR == errno)
1466 goto RETRY;
1467 if (NULL != connection->write_task)
1468 {
1469 GNUNET_SCHEDULER_cancel (connection->write_task);
1470 connection->write_task = NULL;
1471 }
1472 signal_transmit_error (connection, errno);
1473 return;
1474 }
1475 LOG (GNUNET_ERROR_TYPE_DEBUG,
1476 "Connection transmitted %u/%u bytes to `%s' (%p)\n",
1477 (unsigned int) ret,
1478 have,
1479 GNUNET_a2s (connection->addr,
1480 connection->addrlen),
1481 connection);
1482 connection->write_buffer_pos += ret;
1483 if (connection->write_buffer_pos == connection->write_buffer_off)
1484 {
1485 /* transmitted all pending data */
1486 connection->write_buffer_pos = 0;
1487 connection->write_buffer_off = 0;
1488 }
1489 if ( (0 == connection->write_buffer_off) &&
1490 (NULL == connection->nth.notify_ready) )
1491 return; /* all data sent! */
1492 /* not done writing, schedule more */
1493SCHEDULE_WRITE:
1494 LOG (GNUNET_ERROR_TYPE_DEBUG,
1495 "Re-scheduling transmit_ready (more to do) (%p).\n",
1496 connection);
1497 have = connection->write_buffer_off - connection->write_buffer_pos;
1498 GNUNET_assert ( (NULL != connection->nth.notify_ready) ||
1499 (have > 0) );
1500 if (NULL == connection->write_task)
1501 connection->write_task =
1502 GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready ==
1503 NULL) ? GNUNET_TIME_UNIT_FOREVER_REL :
1504 GNUNET_TIME_absolute_get_remaining
1505 (connection->nth.transmit_timeout),
1506 connection->sock,
1507 &transmit_ready, connection);
1508}
1509
1510
1511/**
1512 * Ask the connection to call us once the specified number of bytes
1513 * are free in the transmission buffer. Will never call the @a notify
1514 * callback in this task, but always first go into the scheduler.
1515 *
1516 * @param connection connection
1517 * @param size number of bytes to send
1518 * @param timeout after how long should we give up (and call
1519 * @a notify with buf NULL and size 0)?
1520 * @param notify function to call
1521 * @param notify_cls closure for @a notify
1522 * @return non-NULL if the notify callback was queued,
1523 * NULL if we are already going to notify someone else (busy)
1524 */
1525struct GNUNET_CONNECTION_TransmitHandle *
1526GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connection,
1527 size_t size,
1528 struct GNUNET_TIME_Relative timeout,
1529 GNUNET_CONNECTION_TransmitReadyNotify notify,
1530 void *notify_cls)
1531{
1532 if (NULL != connection->nth.notify_ready)
1533 {
1534 GNUNET_assert (0);
1535 return NULL;
1536 }
1537 GNUNET_assert (NULL != notify);
1538 GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
1539 GNUNET_assert (connection->write_buffer_off <= connection->write_buffer_size);
1540 GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_size);
1541 GNUNET_assert (connection->write_buffer_pos <= connection->write_buffer_off);
1542 connection->nth.notify_ready = notify;
1543 connection->nth.notify_ready_cls = notify_cls;
1544 connection->nth.connection = connection;
1545 connection->nth.notify_size = size;
1546 connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1547 GNUNET_assert (NULL == connection->nth.timeout_task);
1548 if ((NULL == connection->sock) &&
1549 (NULL == connection->ap_head) &&
1550 (NULL == connection->dns_active) &&
1551 (NULL == connection->proxy_handshake))
1552 {
1553 if (NULL != connection->write_task)
1554 GNUNET_SCHEDULER_cancel (connection->write_task);
1555 connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error,
1556 connection);
1557 return &connection->nth;
1558 }
1559 if (NULL != connection->write_task)
1560 return &connection->nth; /* previous transmission still in progress */
1561 if (NULL != connection->sock)
1562 {
1563 /* connected, try to transmit now */
1564 LOG (GNUNET_ERROR_TYPE_DEBUG,
1565 "Scheduling transmission (%p).\n",
1566 connection);
1567 connection->write_task =
1568 GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
1569 (connection->nth.transmit_timeout),
1570 connection->sock,
1571 &transmit_ready, connection);
1572 return &connection->nth;
1573 }
1574 /* not yet connected, wait for connection */
1575 LOG (GNUNET_ERROR_TYPE_DEBUG,
1576 "Need to wait to schedule transmission for connection, adding timeout task (%p).\n",
1577 connection);
1578 connection->nth.timeout_task =
1579 GNUNET_SCHEDULER_add_delayed (timeout,
1580 &transmit_timeout,
1581 connection);
1582 return &connection->nth;
1583}
1584
1585
1586/**
1587 * Cancel the specified transmission-ready notification.
1588 *
1589 * @param th notification to cancel
1590 */
1591void
1592GNUNET_CONNECTION_notify_transmit_ready_cancel (struct GNUNET_CONNECTION_TransmitHandle *th)
1593{
1594 GNUNET_assert (NULL != th->notify_ready);
1595 th->notify_ready = NULL;
1596 if (NULL != th->timeout_task)
1597 {
1598 GNUNET_SCHEDULER_cancel (th->timeout_task);
1599 th->timeout_task = NULL;
1600 }
1601 if (NULL != th->connection->write_task)
1602 {
1603 GNUNET_SCHEDULER_cancel (th->connection->write_task);
1604 th->connection->write_task = NULL;
1605 }
1606}
1607
1608
1609/**
1610 * Create a connection to be proxied using a given connection.
1611 *
1612 * @param cph connection to proxy server
1613 * @return connection to be proxied
1614 */
1615struct GNUNET_CONNECTION_Handle *
1616GNUNET_CONNECTION_create_proxied_from_handshake (struct GNUNET_CONNECTION_Handle *cph)
1617{
1618 struct GNUNET_CONNECTION_Handle *proxied = GNUNET_CONNECTION_create_from_existing (NULL);
1619
1620 proxied->proxy_handshake = cph;
1621 return proxied;
1622}
1623
1624
1625/**
1626 * Activate proxied connection and destroy initial proxy handshake connection.
1627 * There must not be any pending requests for reading or writing to the
1628 * proxy hadshake connection at this time.
1629 *
1630 * @param proxied connection connection to proxy server
1631 */
1632void
1633GNUNET_CONNECTION_acivate_proxied (struct GNUNET_CONNECTION_Handle *proxied)
1634{
1635 struct GNUNET_CONNECTION_Handle *cph = proxied->proxy_handshake;
1636
1637 GNUNET_assert (NULL != cph);
1638 GNUNET_assert (NULL == proxied->sock);
1639 GNUNET_assert (NULL != cph->sock);
1640 proxied->sock = cph->sock;
1641 cph->sock = NULL;
1642 GNUNET_CONNECTION_destroy (cph);
1643 connect_success_continuation (proxied);
1644}
1645
1646
1647/* end of connection.c */