GNUnet debian-0.24.3-29-g453fda2cf
 
Loading...
Searching...
No Matches
client.c File Reference

code for access to services More...

#include "platform.h"
#include "gnunet_protocols.h"
#include "gnunet_util_lib.h"
#include "gnunet_resolver_service.h"
#include "gnunet_socks.h"
Include dependency graph for client.c:

Go to the source code of this file.

Data Structures

struct  AddressProbe
 During connect, we try multiple possible IP addresses to find out which one might work. More...
 
struct  ClientState
 State we keep per client. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util-client", __VA_ARGS__)
 
#define CONNECT_RETRY_TIMEOUT
 Timeout we use on TCP connect before trying another result from the DNS resolver.
 

Functions

static void start_connect (void *cls)
 Try to connect to the service.
 
static void connect_fail_continuation (struct ClientState *cstate)
 We've failed for good to establish a connection (timeout or no more addresses to try).
 
static void transmit_ready (void *cls)
 We are ready to send a message to the service.
 
static enum GNUNET_GenericReturnValue recv_message (void *cls, const struct GNUNET_MessageHeader *msg)
 We have received a full message, pass to the MQ dispatcher.
 
static void cancel_aps (struct ClientState *cstate)
 Cancel all remaining connect attempts.
 
static void connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Implement the destruction of a message queue.
 
static void receive_ready (void *cls)
 This function is called once we have data ready to read.
 
static void connect_success_continuation (struct ClientState *cstate)
 We've succeeded in establishing a connection.
 
static struct GNUNET_NETWORK_Handletry_unixpath (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
 Try connecting to the server using UNIX domain sockets.
 
static void connect_probe_continuation (void *cls)
 Scheduler let us know that we're either ready to write on the socket OR connect timed out.
 
static void try_connect_using_address (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 Try to establish a connection given the specified address.
 
static int test_service_configuration (const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
 Test whether the configuration has proper values for connection (UNIXPATH || (PORT && HOSTNAME)).
 
static void connection_client_send_impl (struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
 Implements the transmission functionality of a message queue.
 
static void connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
 Cancel the currently sent message.
 
enum GNUNET_GenericReturnValue GNUNET_CLIENT_test (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name)
 Test if the port or UNIXPATH of the given service_name is in use and thus (most likely) the respective service is up.
 
struct GNUNET_MQ_HandleGNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
 Create a message queue to connect to a GNUnet service.
 

Detailed Description

code for access to services

Author
Christian Grothoff

Generic TCP code for reliable, record-oriented TCP connections between clients and service providers.

Definition in file client.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util-client", __VA_ARGS__)

Definition at line 37 of file client.c.

◆ CONNECT_RETRY_TIMEOUT

#define CONNECT_RETRY_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition time.c:486

Timeout we use on TCP connect before trying another result from the DNS resolver.

Actual value used is this value divided by the number of address families. Default is 5s.

Definition at line 45 of file client.c.

59{
63 struct AddressProbe *next;
64
68 struct AddressProbe *prev;
69
73 const struct sockaddr *addr;
74
78 struct GNUNET_NETWORK_Handle *sock;
79
83 struct ClientState *cstate;
84
88 socklen_t addrlen;
89
93 struct GNUNET_SCHEDULER_Task *task;
94};
95
96
100struct ClientState
101{
106
111
115 const struct GNUNET_CONFIGURATION_Handle *cfg;
116
121 struct AddressProbe *ap_head;
122
127 struct AddressProbe *ap_tail;
128
132 char *service_name;
133
137 char *hostname;
138
142 const struct GNUNET_MessageHeader *msg;
143
148
153
158
163
167 struct GNUNET_MQ_Handle *mq;
168
173
179
183 unsigned long long port;
184
188 size_t msg_off;
189
193 unsigned int attempts;
194
200 int in_destroy;
201};
202
203
209static void
210start_connect (void *cls);
211
212
219static void
221{
222 GNUNET_break (NULL == cstate->ap_head);
223 GNUNET_break (NULL == cstate->ap_tail);
224 GNUNET_break (NULL == cstate->dns_active);
225 GNUNET_break (NULL == cstate->sock);
226 GNUNET_assert (NULL == cstate->send_task);
227 GNUNET_assert (NULL == cstate->recv_task);
228 // GNUNET_assert (NULL == cstate->proxy_handshake);
229
230 cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
232 "Failed to establish connection to `%s', no further addresses to try, will try again in %s.\n",
233 cstate->service_name,
235 GNUNET_YES));
236 cstate->retry_task
239 cstate);
240}
241
242
248static void
249transmit_ready (void *cls)
250{
251 struct ClientState *cstate = cls;
252 ssize_t ret;
253 size_t len;
254 const char *pos;
255 int notify_in_flight;
256
257 cstate->send_task = NULL;
258 if (GNUNET_YES == cstate->in_destroy)
259 return;
260 pos = (const char *) cstate->msg;
261 len = ntohs (cstate->msg->size);
262 GNUNET_assert (cstate->msg_off < len);
264 "message of type %u and size %u trying to send with socket %p (MQ: %p\n",
265 ntohs (cstate->msg->type),
266 ntohs (cstate->msg->size),
267 cstate->sock,
268 cstate->mq);
269
270RETRY:
272 &pos[cstate->msg_off],
273 len - cstate->msg_off);
274 if ( (-1 == ret) &&
275 ( (EAGAIN == errno) ||
276 (EINTR == errno) ) )
277 {
278 /* ignore */
279 ret = 0;
280 }
281 if (-1 == ret)
282 {
284 "Error during sending message of type %u: %s\n",
285 ntohs (cstate->msg->type),
286 strerror (errno));
287 if (EINTR == errno)
288 {
290 "Retrying message of type %u\n",
291 ntohs (cstate->msg->type));
292 goto RETRY;
293 }
294 GNUNET_MQ_inject_error (cstate->mq,
296 return;
297 }
298 notify_in_flight = (0 == cstate->msg_off);
299 cstate->msg_off += ret;
300 if (cstate->msg_off < len)
301 {
303 "rescheduling message of type %u\n",
304 ntohs (cstate->msg->type));
305 cstate->send_task
307 cstate->sock,
309 cstate);
310 if (notify_in_flight)
312 return;
313 }
315 "sending message of type %u and size %u successful\n",
316 ntohs (cstate->msg->type),
317 ntohs (cstate->msg->size));
318 cstate->msg = NULL;
320}
321
322
334recv_message (void *cls,
335 const struct GNUNET_MessageHeader *msg)
336{
337 struct ClientState *cstate = cls;
338
339 if (GNUNET_YES == cstate->in_destroy)
340 return GNUNET_NO;
342 "Received message of type %u and size %u from %s\n",
343 ntohs (msg->type),
344 ntohs (msg->size),
345 cstate->service_name);
347 msg);
348 if (GNUNET_YES == cstate->in_destroy)
349 return GNUNET_NO;
350 return GNUNET_OK;
351}
352
353
359static void
360cancel_aps (struct ClientState *cstate)
361{
362 struct AddressProbe *pos;
363
364 while (NULL != (pos = cstate->ap_head))
365 {
371 pos);
372 GNUNET_free (pos);
373 }
374}
375
376
384static void
386 void *impl_state)
387{
388 struct ClientState *cstate = impl_state;
389
390 (void) mq;
391 if (NULL != cstate->dns_active)
392 {
394 cstate->dns_active = NULL;
395 }
396 if (NULL != cstate->send_task)
397 {
399 cstate->send_task = NULL;
400 }
401 if (NULL != cstate->retry_task)
402 {
404 cstate->retry_task = NULL;
405 }
406 if (GNUNET_SYSERR == cstate->in_destroy)
407 {
408 /* defer destruction */
409 cstate->in_destroy = GNUNET_YES;
410 cstate->mq = NULL;
411 return;
412 }
413 if (NULL != cstate->recv_task)
414 {
416 cstate->recv_task = NULL;
417 }
418 if (NULL != cstate->sock)
419 {
421 "destroying socket: %p\n",
422 cstate->sock);
424 }
425 cancel_aps (cstate);
426 GNUNET_free (cstate->service_name);
427 GNUNET_free (cstate->hostname);
428 GNUNET_MST_destroy (cstate->mst);
429 GNUNET_free (cstate);
430}
431
432
438static void
439receive_ready (void *cls)
440{
441 struct ClientState *cstate = cls;
443
444 cstate->recv_task = NULL;
445 cstate->in_destroy = GNUNET_SYSERR;
446 ret = GNUNET_MST_read (cstate->mst,
447 cstate->sock,
448 GNUNET_NO,
449 GNUNET_NO);
450 if (GNUNET_SYSERR == ret)
451 {
452 if (NULL != cstate->mq)
453 GNUNET_MQ_inject_error (cstate->mq,
455 if (GNUNET_YES == cstate->in_destroy)
457 cstate);
458 return;
459 }
460 if (GNUNET_YES == cstate->in_destroy)
461 {
463 cstate);
464 return;
465 }
466 cstate->in_destroy = GNUNET_NO;
467 GNUNET_assert (NULL == cstate->recv_task);
468 cstate->recv_task
470 cstate->sock,
472 cstate);
473}
474
475
481static void
483{
484 GNUNET_assert (NULL == cstate->recv_task);
485 cstate->recv_task
487 cstate->sock,
489 cstate);
490 if (NULL != cstate->msg)
491 {
492 GNUNET_assert (NULL == cstate->send_task);
493 cstate->send_task
495 cstate->sock,
497 cstate);
498 }
499}
500
501
509static struct GNUNET_NETWORK_Handle *
510try_unixpath (const char *service_name,
511 const struct GNUNET_CONFIGURATION_Handle *cfg)
512{
513#if AF_UNIX
514 struct GNUNET_NETWORK_Handle *sock;
515 char *unixpath;
516 struct sockaddr_un s_un;
517
518 unixpath = NULL;
519 if ((GNUNET_OK ==
522 "UNIXPATH",
523 &unixpath)) &&
524 (0 < strlen (unixpath)))
525 {
526 /* We have a non-NULL unixpath, need to validate it */
527 if (strlen (unixpath) >= sizeof(s_un.sun_path))
528 {
530 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
531 unixpath,
532 (unsigned long long) sizeof(s_un.sun_path));
533 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
535 _ ("Using `%s' instead\n"),
536 unixpath);
537 if (NULL == unixpath)
538 return NULL;
539 }
540 memset (&s_un,
541 0,
542 sizeof(s_un));
543 s_un.sun_family = AF_UNIX;
544 GNUNET_strlcpy (s_un.sun_path,
545 unixpath,
546 sizeof(s_un.sun_path));
547#if HAVE_SOCKADDR_UN_SUN_LEN
548 s_un.sun_len = (u_char) sizeof(struct sockaddr_un);
549#endif
550 sock = GNUNET_NETWORK_socket_create (AF_UNIX,
551 SOCK_STREAM,
552 0);
553 if ((NULL != sock) &&
554 ((GNUNET_OK ==
556 (struct sockaddr *) &s_un,
557 sizeof(s_un))) ||
558 (EINPROGRESS == errno)))
559 {
561 "Successfully connected to unixpath `%s'!\n",
562 unixpath);
563 GNUNET_free (unixpath);
564 return sock;
565 }
566 if (NULL != sock)
568 }
569 GNUNET_free (unixpath);
570#endif
571 return NULL;
572}
573
574
581static void
583{
584 struct AddressProbe *ap = cls;
585 struct ClientState *cstate = ap->cstate;
586 const struct GNUNET_SCHEDULER_TaskContext *tc;
587 int error;
588 socklen_t len;
589
590 ap->task = NULL;
591 GNUNET_assert (NULL != ap->sock);
593 cstate->ap_tail,
594 ap);
595 len = sizeof(error);
596 error = 0;
599 (GNUNET_OK !=
601 SOL_SOCKET,
602 SO_ERROR,
603 &error,
604 &len)) ||
605 (0 != error))
606 {
609 GNUNET_free (ap);
610 if ((NULL == cstate->ap_head) &&
611 // (NULL == cstate->proxy_handshake) &&
612 (NULL == cstate->dns_active))
614 return;
615 }
617 "Connection to `%s' succeeded!\n",
618 cstate->service_name);
619 /* trigger jobs that waited for the connection */
620 GNUNET_assert (NULL == cstate->sock);
621 cstate->sock = ap->sock;
622 GNUNET_free (ap);
623 cancel_aps (cstate);
625}
626
627
636static void
638 const struct sockaddr *addr,
639 socklen_t addrlen)
640{
641 struct ClientState *cstate = cls;
642 struct AddressProbe *ap;
643
644 if (NULL == addr)
645 {
646 cstate->dns_active = NULL;
647 if ((NULL == cstate->ap_head) &&
648 // (NULL == cstate->proxy_handshake) &&
649 (NULL == cstate->sock))
651 return;
652 }
653 if (NULL != cstate->sock)
654 return; /* already connected */
655 /* try to connect */
657 "Trying to connect using address `%s:%u'\n",
659 addrlen),
660 (unsigned int) cstate->port);
661 ap = GNUNET_malloc (sizeof(struct AddressProbe) + addrlen);
662 ap->addr = (const struct sockaddr *) &ap[1];
663 GNUNET_memcpy (&ap[1],
664 addr,
665 addrlen);
666 ap->addrlen = addrlen;
667 ap->cstate = cstate;
668
669 switch (ap->addr->sa_family)
670 {
671 case AF_INET:
672 ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
673 break;
674
675 case AF_INET6:
676 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
677 break;
678
679 default:
680 GNUNET_break (0);
681 GNUNET_free (ap);
682 return; /* not supported by us */
683 }
684 ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
685 SOCK_STREAM,
686 0);
687 if (NULL == ap->sock)
688 {
689 GNUNET_free (ap);
690 return; /* not supported by OS */
691 }
692 if ((GNUNET_OK !=
694 ap->addr,
695 ap->addrlen)) &&
696 (EINPROGRESS != errno))
697 {
698 /* maybe refused / unsupported address, try next */
700 "connect");
703 GNUNET_free (ap);
704 return;
705 }
707 cstate->ap_tail,
708 ap);
710 ap->sock,
712 ap);
713}
714
715
724static int
726 const struct GNUNET_CONFIGURATION_Handle *cfg)
727{
728 int ret = GNUNET_SYSERR;
729 char *hostname = NULL;
730 unsigned long long port;
731
732#if AF_UNIX
733 char *unixpath = NULL;
734
735 if ((GNUNET_OK ==
738 "UNIXPATH",
739 &unixpath)) &&
740 (0 < strlen (unixpath)))
741 ret = GNUNET_OK;
742 else if ((GNUNET_OK ==
745 "UNIXPATH")))
746 {
749 "UNIXPATH",
750 _ ("not a valid filename"));
751 GNUNET_free (unixpath);
752 return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */
753 }
754 GNUNET_free (unixpath);
755#endif
756
757 if ((GNUNET_YES ==
760 "PORT")) &&
761 (GNUNET_OK ==
764 "PORT",
765 &port)) &&
766 (port <= 65535) &&
767 (0 != port) &&
768 (GNUNET_OK ==
771 "HOSTNAME",
772 &hostname)) &&
773 (0 != strlen (hostname)))
774 ret = GNUNET_OK;
775 GNUNET_free (hostname);
776 return ret;
777}
778
779
785static void
786start_connect (void *cls)
787{
788 struct ClientState *cstate = cls;
789
790 cstate->retry_task = NULL;
791#if 0
792 /* Never use a local source if a proxy is configured */
793 if (GNUNET_YES ==
795 cstate->cfg))
796 {
797 socks_connect (cstate);
798 return;
799 }
800#endif
801
802 if ((0 == (cstate->attempts++ % 2)) ||
803 (0 == cstate->port) ||
804 (NULL == cstate->hostname))
805 {
806 /* on even rounds, try UNIX first, or always
807 if we do not have a DNS name and TCP port. */
808 cstate->sock = try_unixpath (cstate->service_name,
809 cstate->cfg);
810 if (NULL != cstate->sock)
811 {
813 return;
814 }
815 }
816 if ((NULL == cstate->hostname) ||
817 (0 == cstate->port))
818 {
819 /* All options failed. Boo! */
821 return;
822 }
823 cstate->dns_active
825 AF_UNSPEC,
828 cstate);
829}
830
831
839static void
841 const struct GNUNET_MessageHeader *msg,
842 void *impl_state)
843{
844 struct ClientState *cstate = impl_state;
845
846 (void) mq;
847 /* only one message at a time allowed */
848 GNUNET_assert (NULL == cstate->msg);
849 GNUNET_assert (NULL == cstate->send_task);
850 cstate->msg = msg;
851 cstate->msg_off = 0;
852 if (NULL == cstate->sock)
853 {
855 "message of type %u waiting for socket\n",
856 ntohs (msg->type));
857 return; /* still waiting for connection */
858 }
859 cstate->send_task
861 cstate);
862}
863
864
871static void
873 void *impl_state)
874{
875 struct ClientState *cstate = impl_state;
876
877 (void) mq;
878 GNUNET_assert (NULL != cstate->msg);
879 GNUNET_assert (0 == cstate->msg_off);
880 cstate->msg = NULL;
881 if (NULL != cstate->send_task)
882 {
884 cstate->send_task = NULL;
885 }
886}
887
888
903 const char *service_name)
904{
905 char *hostname = NULL;
906 unsigned long long port;
907 int ret;
908
909#if AF_UNIX
910 {
911 char *unixpath = NULL;
912
913 if (GNUNET_OK ==
916 "UNIXPATH",
917 &unixpath))
918 {
919 if (0 == strlen (unixpath))
920 {
921 GNUNET_free (unixpath);
922 return GNUNET_SYSERR; /* empty string not OK */
923 }
924 if (0 == access (unixpath,
925 F_OK))
926 {
927 GNUNET_free (unixpath);
928 return GNUNET_OK; /* file exists, we assume service is running */
929 }
930 GNUNET_free (unixpath);
931 }
932 else if (GNUNET_OK ==
935 "UNIXPATH"))
936 {
937 /* UNIXPATH specified but not a valid path! */
940 "UNIXPATH",
941 _ ("not a valid filename"));
942 return GNUNET_SYSERR;
943 }
944 }
945#endif
946
947 if ( (GNUNET_OK !=
950 "PORT",
951 &port)) ||
952 (port > 65535) ||
953 (0 == port) )
954 {
957 "PORT");
958 return GNUNET_SYSERR;
959 }
960 if (GNUNET_OK ==
963 "HOSTNAME",
964 &hostname))
965 {
966 /* We always assume remotes are up */
967 ret = GNUNET_YES;
968 }
969 else
970 {
971 /* We look for evidence the service is up */
972 ret = GNUNET_NO;
973 }
974 if ( (NULL == hostname) ||
975 (0 == strcasecmp (hostname,
976 "localhost")) ||
977 (0 == strcasecmp (hostname,
978 "ip6-localnet")) )
979 {
980 /* service runs on loopback */
981 struct sockaddr_in v4;
982 struct sockaddr_in6 v6;
983 int sock;
984
985 memset (&v4, 0, sizeof (v4));
986 memset (&v6, 0, sizeof (v6));
987 v4.sin_family = AF_INET;
988 v4.sin_port = htons ((uint16_t) port);
989#if HAVE_SOCKADDR_IN_SUN_LEN
990 v4.sin_len = (u_char) sizeof(struct sockaddr_in);
991#endif
992 GNUNET_assert (1 == inet_pton (AF_INET,
993 "127.0.0.1",
994 &v4.sin_addr));
995 ret = GNUNET_NO;
996 sock = socket (AF_INET,
997 SOCK_STREAM,
998 0);
999 if (-1 != sock)
1000 {
1001 if (0 != bind (sock,
1002 (struct sockaddr *) &v4,
1003 sizeof (v4)))
1004 {
1005 /* bind failed, so someone is listening! */
1006 ret = GNUNET_YES;
1007 }
1008 (void) close (sock);
1009 }
1010 else
1011 {
1013 "socket");
1014 if (GNUNET_NO == ret)
1016 }
1017 v6.sin6_family = AF_INET6;
1018 v6.sin6_port = htons ((uint16_t) port);
1019#if HAVE_SOCKADDR_IN_SUN_LEN
1020 v6.sin6_len = (u_char) sizeof(struct sockaddr_in6);
1021#endif
1022 inet_pton (AF_INET6,
1023 "::1",
1024 &v6.sin6_addr);
1025 sock = socket (AF_INET6,
1026 SOCK_STREAM,
1027 0);
1028 if (-1 != sock)
1029 {
1030 if (0 != bind (sock,
1031 (struct sockaddr *) &v6,
1032 sizeof (v6)))
1033 {
1034 /* bind failed, so someone is listening! */
1035 ret = GNUNET_YES;
1036 }
1037 (void) close (sock);
1038 }
1039 else
1040 {
1042 "socket");
1043 /* not changing 'ret' intentionally here, as
1044 v4 succeeding and v6 failing just means we
1045 should use v4 */
1046 }
1047 }
1048 else
1049 {
1050 /* service running remotely */
1051 ret = GNUNET_OK;
1052 }
1053 GNUNET_free (hostname);
1054 return ret;
1055}
1056
1057
1058struct GNUNET_MQ_Handle *
1060 const char *service_name,
1061 const struct GNUNET_MQ_MessageHandler *handlers,
1063 void *error_handler_cls)
1064{
1065 struct ClientState *cstate;
1066
1067 if (GNUNET_OK !=
1069 cfg))
1070 return NULL;
1071 cstate = GNUNET_new (struct ClientState);
1073 cstate->cfg = cfg;
1075 cstate);
1077 cstate);
1078 if (GNUNET_YES ==
1081 "PORT"))
1082 {
1083 if (! ((GNUNET_OK !=
1086 "PORT",
1087 &cstate->port)) ||
1088 (cstate->port > 65535) ||
1089 (GNUNET_SYSERR ==
1092 "HOSTNAME",
1093 &cstate->hostname))) &&
1094 (0 == strlen (cstate->hostname)))
1095 {
1096 GNUNET_free (cstate->hostname);
1097 cstate->hostname = NULL;
1099 _ ("Need a non-empty hostname for service `%s'.\n"),
1100 service_name);
1101 }
1102 }
1106 cstate,
1107 handlers,
1109 error_handler_cls);
1110 return cstate->mq;
1111}
1112
1113
1114/* end of client.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
static void error_handler(void *cls, enum GNUNET_MQ_Error error)
Function called on connection trouble.
static void try_connect_using_address(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Try to establish a connection given the specified address.
Definition client.c:638
static void connect_success_continuation(struct ClientState *cstate)
We've succeeded in establishing a connection.
Definition client.c:483
static void connection_client_cancel_impl(struct GNUNET_MQ_Handle *mq, void *impl_state)
Cancel the currently sent message.
Definition client.c:873
static void connection_client_send_impl(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *msg, void *impl_state)
Implements the transmission functionality of a message queue.
Definition client.c:841
static void start_connect(void *cls)
Try to connect to the service.
Definition client.c:787
static void transmit_ready(void *cls)
We are ready to send a message to the service.
Definition client.c:250
static void connect_probe_continuation(void *cls)
Scheduler let us know that we're either ready to write on the socket OR connect timed out.
Definition client.c:583
static enum GNUNET_GenericReturnValue recv_message(void *cls, const struct GNUNET_MessageHeader *msg)
We have received a full message, pass to the MQ dispatcher.
Definition client.c:335
static void receive_ready(void *cls)
This function is called once we have data ready to read.
Definition client.c:440
static void connection_client_destroy_impl(struct GNUNET_MQ_Handle *mq, void *impl_state)
Implement the destruction of a message queue.
Definition client.c:386
static void cancel_aps(struct ClientState *cstate)
Cancel all remaining connect attempts.
Definition client.c:361
static void connect_fail_continuation(struct ClientState *cstate)
We've failed for good to establish a connection (timeout or no more addresses to try).
Definition client.c:221
static int test_service_configuration(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
Test whether the configuration has proper values for connection (UNIXPATH || (PORT && HOSTNAME)).
Definition client.c:726
#define LOG(kind,...)
Definition client.c:37
static struct GNUNET_NETWORK_Handle * try_unixpath(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
Try connecting to the server using UNIX domain sockets.
Definition client.c:511
#define CONNECT_RETRY_TIMEOUT
Timeout we use on TCP connect before trying another result from the DNS resolver.
Definition client.c:45
static int ret
Final status code.
Definition gnunet-arm.c:93
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition gnunet-arm.c:108
static uint16_t port
Port number.
Definition gnunet-bcd.c:146
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition gnunet-vpn.c:50
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition client.c:1060
enum GNUNET_GenericReturnValue GNUNET_CLIENT_test(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name)
Test if the port or UNIXPATH of the given service_name is in use and thus (most likely) the respectiv...
Definition client.c:903
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_inject_error(struct GNUNET_MQ_Handle *mq, enum GNUNET_MQ_Error error)
Call the error handler of a message queue with the given error code.
Definition mq.c:269
struct GNUNET_MQ_Handle * GNUNET_MQ_queue_for_callbacks(GNUNET_MQ_SendImpl send, GNUNET_MQ_DestroyImpl destroy, GNUNET_MQ_CancelImpl cancel, void *impl_state, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *cls)
Create a message queue for the specified handlers.
Definition mq.c:482
void(* GNUNET_MQ_ErrorHandler)(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
void GNUNET_MQ_impl_send_continue(struct GNUNET_MQ_Handle *mq)
Call the send implementation for the next queued message, if any.
Definition mq.c:437
void GNUNET_MQ_inject_message(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MessageHeader *mh)
Call the message message handler that was registered for the type of the given message in the given m...
Definition mq.c:187
void GNUNET_MQ_impl_send_in_flight(struct GNUNET_MQ_Handle *mq)
Call the send notification for the current message, but do not try to send the next message until #gn...
Definition mq.c:461
@ GNUNET_MQ_ERROR_READ
Failed to read message from the network.
@ GNUNET_MQ_ERROR_WRITE
FIXME: document!
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_getsockopt(const struct GNUNET_NETWORK_Handle *desc, int level, int optname, void *optval, socklen_t *optlen)
Get socket options.
Definition network.c:627
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition network.c:508
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition network.c:143
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition network.c:833
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_connect(const struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Connect a socket to some remote address.
Definition network.c:602
ssize_t GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc, const void *buffer, size_t length)
Send data (always non-blocking).
Definition network.c:738
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1511
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_write_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *wfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition scheduler.c:1582
const struct GNUNET_SCHEDULER_TaskContext * GNUNET_SCHEDULER_get_task_context(void)
Obtain the reasoning why the current task was started.
Definition scheduler.c:758
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1277
@ GNUNET_SCHEDULER_REASON_WRITE_READY
The writing socket is ready.
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition mst.c:86
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition mst.c:404
enum GNUNET_GenericReturnValue GNUNET_MST_read(struct GNUNET_MessageStreamTokenizer *mst, struct GNUNET_NETWORK_Handle *sock, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition mst.c:338
int GNUNET_SOCKS_check_service(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg)
Check if a SOCKS proxy is required by a service.
Definition socks.c:594
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition strings.c:137
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition strings.c:599
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
#define _(String)
GNU gettext support macro.
Definition platform.h:179
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_SCHEDULER_TaskContext tc
Task context of the current task.
Definition scheduler.c:431
During connect, we try multiple possible IP addresses to find out which one might work.
Definition client.c:60
const struct sockaddr * addr
The address; do not free (allocated at the end of this struct).
Definition client.c:74
socklen_t addrlen
Length of addr.
Definition client.c:89
struct GNUNET_SCHEDULER_Task * task
Task waiting for the connection to finish connecting.
Definition client.c:94
struct AddressProbe * next
This is a linked list.
Definition client.c:64
struct ClientState * cstate
Connection for which we are probing.
Definition client.c:84
struct AddressProbe * prev
This is a doubly-linked list.
Definition client.c:69
struct GNUNET_NETWORK_Handle * sock
Underlying OS's socket.
Definition client.c:79
State we keep per client.
struct GNUNET_MQ_Handle * mq
MQ to talk to client.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition client.c:116
struct GNUNET_MessageStreamTokenizer * mst
Tokenizer for inbound messages.
Definition client.c:163
int in_destroy
Are we supposed to die? GNUNET_SYSERR if destruction must be deferred, GNUNET_NO by default,...
Definition client.c:201
unsigned int attempts
How often have we tried to connect?
Definition client.c:194
const struct GNUNET_MessageHeader * msg
Next message to transmit to the service.
Definition client.c:143
size_t msg_off
Offset in the message where we are for transmission.
Definition client.c:189
struct GNUNET_SCHEDULER_Task * retry_task
Task for trying to connect to the service.
Definition client.c:148
struct GNUNET_TIME_Relative back_off
Current value for our incremental back-off (for connect re-tries).
Definition client.c:179
struct GNUNET_SCHEDULER_Task * send_task
Task for sending messages to the service.
Definition client.c:153
char * hostname
Hostname, if any.
Definition client.c:138
struct GNUNET_RESOLVER_RequestHandle * dns_active
Handle to a pending DNS lookup request, NULL if DNS is finished.
Definition client.c:111
unsigned long long port
TCP port (0 for disabled).
Definition client.c:184
struct GNUNET_TIME_Absolute receive_timeout
Timeout for receiving a response (absolute time).
Definition client.c:173
struct GNUNET_SCHEDULER_Task * recv_task
Task for sending messages to the service.
Definition client.c:158
struct GNUNET_NETWORK_Handle * sock
The connection handle, NULL if not live.
Definition client.c:106
char * service_name
Name of the service we interact with.
Definition client.c:133
struct AddressProbe * ap_tail
Linked list of sockets we are currently trying out (during connect).
Definition client.c:128
struct AddressProbe * ap_head
Linked list of sockets we are currently trying out (during connect).
Definition client.c:122
Handle to a message queue.
Definition mq.c:87
void * error_handler_cls
Closure for the error handler.
Definition mq.c:122
Message handler for a specific message type.
Header for all communications.
Handle to a message stream tokenizer.
Definition mst.c:45
handle to a socket
Definition network.c:53
Handle to a request given to the resolver.
Context information passed to each scheduler task.
enum GNUNET_SCHEDULER_Reason reason
Reason why the task is run now.
Entry in list of pending tasks.
Definition scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.

Function Documentation

◆ start_connect()

static void start_connect ( void *  cls)
static

Try to connect to the service.

Parameters
clsthe struct ClientState to try to connect to the service

Definition at line 787 of file client.c.

788{
789 struct ClientState *cstate = cls;
790
791 cstate->retry_task = NULL;
792#if 0
793 /* Never use a local source if a proxy is configured */
794 if (GNUNET_YES ==
796 cstate->cfg))
797 {
798 socks_connect (cstate);
799 return;
800 }
801#endif
802
803 if ((0 == (cstate->attempts++ % 2)) ||
804 (0 == cstate->port) ||
805 (NULL == cstate->hostname))
806 {
807 /* on even rounds, try UNIX first, or always
808 if we do not have a DNS name and TCP port. */
809 cstate->sock = try_unixpath (cstate->service_name,
810 cstate->cfg);
811 if (NULL != cstate->sock)
812 {
814 return;
815 }
816 }
817 if ((NULL == cstate->hostname) ||
818 (0 == cstate->port))
819 {
820 /* All options failed. Boo! */
822 return;
823 }
824 cstate->dns_active
826 AF_UNSPEC,
829 cstate);
830}

References ClientState::attempts, ClientState::cfg, connect_fail_continuation(), CONNECT_RETRY_TIMEOUT, connect_success_continuation(), ClientState::dns_active, GNUNET_RESOLVER_ip_get(), GNUNET_SOCKS_check_service(), GNUNET_YES, ClientState::hostname, ClientState::port, ClientState::retry_task, ClientState::service_name, ClientState::sock, try_connect_using_address(), and try_unixpath().

Referenced by connect_fail_continuation(), and GNUNET_CLIENT_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connect_fail_continuation()

static void connect_fail_continuation ( struct ClientState cstate)
static

We've failed for good to establish a connection (timeout or no more addresses to try).

Parameters
cstatethe connection we tried to establish

Definition at line 221 of file client.c.

222{
223 GNUNET_break (NULL == cstate->ap_head);
224 GNUNET_break (NULL == cstate->ap_tail);
225 GNUNET_break (NULL == cstate->dns_active);
226 GNUNET_break (NULL == cstate->sock);
227 GNUNET_assert (NULL == cstate->send_task);
228 GNUNET_assert (NULL == cstate->recv_task);
229 // GNUNET_assert (NULL == cstate->proxy_handshake);
230
231 cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
233 "Failed to establish connection to `%s', no further addresses to try, will try again in %s.\n",
234 cstate->service_name,
236 GNUNET_YES));
237 cstate->retry_task
240 cstate);
241}

References ClientState::ap_head, ClientState::ap_tail, ClientState::back_off, ClientState::dns_active, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_delayed(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_STD_BACKOFF, GNUNET_YES, LOG, ClientState::recv_task, ClientState::retry_task, ClientState::send_task, ClientState::service_name, ClientState::sock, and start_connect().

Referenced by connect_probe_continuation(), start_connect(), and try_connect_using_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ transmit_ready()

static void transmit_ready ( void *  cls)
static

We are ready to send a message to the service.

Parameters
clsthe struct ClientState with the msg to transmit

Definition at line 250 of file client.c.

251{
252 struct ClientState *cstate = cls;
253 ssize_t ret;
254 size_t len;
255 const char *pos;
256 int notify_in_flight;
257
258 cstate->send_task = NULL;
259 if (GNUNET_YES == cstate->in_destroy)
260 return;
261 pos = (const char *) cstate->msg;
262 len = ntohs (cstate->msg->size);
263 GNUNET_assert (cstate->msg_off < len);
265 "message of type %u and size %u trying to send with socket %p (MQ: %p\n",
266 ntohs (cstate->msg->type),
267 ntohs (cstate->msg->size),
268 cstate->sock,
269 cstate->mq);
270
271RETRY:
273 &pos[cstate->msg_off],
274 len - cstate->msg_off);
275 if ( (-1 == ret) &&
276 ( (EAGAIN == errno) ||
277 (EINTR == errno) ) )
278 {
279 /* ignore */
280 ret = 0;
281 }
282 if (-1 == ret)
283 {
285 "Error during sending message of type %u: %s\n",
286 ntohs (cstate->msg->type),
287 strerror (errno));
288 if (EINTR == errno)
289 {
291 "Retrying message of type %u\n",
292 ntohs (cstate->msg->type));
293 goto RETRY;
294 }
295 GNUNET_MQ_inject_error (cstate->mq,
297 return;
298 }
299 notify_in_flight = (0 == cstate->msg_off);
300 cstate->msg_off += ret;
301 if (cstate->msg_off < len)
302 {
304 "rescheduling message of type %u\n",
305 ntohs (cstate->msg->type));
306 cstate->send_task
308 cstate->sock,
310 cstate);
311 if (notify_in_flight)
313 return;
314 }
316 "sending message of type %u and size %u successful\n",
317 ntohs (cstate->msg->type),
318 ntohs (cstate->msg->size));
319 cstate->msg = NULL;
321}

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_MQ_ERROR_WRITE, GNUNET_MQ_impl_send_continue(), GNUNET_MQ_impl_send_in_flight(), GNUNET_MQ_inject_error(), GNUNET_NETWORK_socket_send(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, ClientState::in_destroy, LOG, ClientState::mq, ClientState::msg, ClientState::msg_off, ret, ClientState::send_task, GNUNET_MessageHeader::size, ClientState::sock, transmit_ready(), and GNUNET_MessageHeader::type.

Referenced by connect_success_continuation(), connection_client_send_impl(), and transmit_ready().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ recv_message()

static enum GNUNET_GenericReturnValue recv_message ( void *  cls,
const struct GNUNET_MessageHeader msg 
)
static

We have received a full message, pass to the MQ dispatcher.

Called by the tokenizer via receive_ready().

Parameters
clsthe struct ClientState
msgmessage we received.
Returns
GNUNET_OK on success, GNUNET_NO to stop further processing due to disconnect (no error) GNUNET_SYSERR to stop further processing due to error

Definition at line 335 of file client.c.

337{
338 struct ClientState *cstate = cls;
339
340 if (GNUNET_YES == cstate->in_destroy)
341 return GNUNET_NO;
343 "Received message of type %u and size %u from %s\n",
344 ntohs (msg->type),
345 ntohs (msg->size),
346 cstate->service_name);
348 msg);
349 if (GNUNET_YES == cstate->in_destroy)
350 return GNUNET_NO;
351 return GNUNET_OK;
352}

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_MQ_inject_message(), GNUNET_NO, GNUNET_OK, GNUNET_YES, ClientState::in_destroy, LOG, ClientState::mq, msg, ClientState::service_name, GNUNET_MessageHeader::size, and GNUNET_MessageHeader::type.

Referenced by GNUNET_CLIENT_connect(), and reconnect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cancel_aps()

static void cancel_aps ( struct ClientState cstate)
static

Cancel all remaining connect attempts.

Parameters
cstatehandle of the client state to process

Definition at line 361 of file client.c.

362{
363 struct AddressProbe *pos;
364
365 while (NULL != (pos = cstate->ap_head))
366 {
372 pos);
373 GNUNET_free (pos);
374 }
375}

References ClientState::ap_head, ClientState::ap_tail, AddressProbe::cstate, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), AddressProbe::sock, and AddressProbe::task.

Referenced by connect_probe_continuation(), and connection_client_destroy_impl().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connection_client_destroy_impl()

static void connection_client_destroy_impl ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Implement the destruction of a message queue.

Implementations must not free mq, but should take care of impl_state.

Parameters
mqthe message queue to destroy
impl_stateour struct ClientState

Definition at line 386 of file client.c.

388{
389 struct ClientState *cstate = impl_state;
390
391 (void) mq;
392 if (NULL != cstate->dns_active)
393 {
395 cstate->dns_active = NULL;
396 }
397 if (NULL != cstate->send_task)
398 {
400 cstate->send_task = NULL;
401 }
402 if (NULL != cstate->retry_task)
403 {
405 cstate->retry_task = NULL;
406 }
407 if (GNUNET_SYSERR == cstate->in_destroy)
408 {
409 /* defer destruction */
410 cstate->in_destroy = GNUNET_YES;
411 cstate->mq = NULL;
412 return;
413 }
414 if (NULL != cstate->recv_task)
415 {
417 cstate->recv_task = NULL;
418 }
419 if (NULL != cstate->sock)
420 {
422 "destroying socket: %p\n",
423 cstate->sock);
425 }
426 cancel_aps (cstate);
427 GNUNET_free (cstate->service_name);
428 GNUNET_free (cstate->hostname);
429 GNUNET_MST_destroy (cstate->mst);
430 GNUNET_free (cstate);
431}

References cancel_aps(), ClientState::dns_active, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_MST_destroy(), GNUNET_NETWORK_socket_close(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_cancel(), GNUNET_SYSERR, GNUNET_YES, ClientState::hostname, ClientState::in_destroy, LOG, ClientState::mq, mq, ClientState::mst, ClientState::recv_task, ClientState::retry_task, ClientState::send_task, ClientState::service_name, and ClientState::sock.

Referenced by GNUNET_CLIENT_connect(), and receive_ready().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ receive_ready()

static void receive_ready ( void *  cls)
static

This function is called once we have data ready to read.

Parameters
clsstruct ClientState with connection to read from

Definition at line 440 of file client.c.

441{
442 struct ClientState *cstate = cls;
444
445 cstate->recv_task = NULL;
446 cstate->in_destroy = GNUNET_SYSERR;
447 ret = GNUNET_MST_read (cstate->mst,
448 cstate->sock,
449 GNUNET_NO,
450 GNUNET_NO);
451 if (GNUNET_SYSERR == ret)
452 {
453 if (NULL != cstate->mq)
454 GNUNET_MQ_inject_error (cstate->mq,
456 if (GNUNET_YES == cstate->in_destroy)
458 cstate);
459 return;
460 }
461 if (GNUNET_YES == cstate->in_destroy)
462 {
464 cstate);
465 return;
466 }
467 cstate->in_destroy = GNUNET_NO;
468 GNUNET_assert (NULL == cstate->recv_task);
469 cstate->recv_task
471 cstate->sock,
473 cstate);
474}

References connection_client_destroy_impl(), GNUNET_assert, GNUNET_MQ_ERROR_READ, GNUNET_MQ_inject_error(), GNUNET_MST_read(), GNUNET_NO, GNUNET_SCHEDULER_add_read_net(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, ClientState::in_destroy, ClientState::mq, ClientState::mst, receive_ready(), ClientState::recv_task, ret, and ClientState::sock.

Referenced by connect_success_continuation(), and receive_ready().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connect_success_continuation()

static void connect_success_continuation ( struct ClientState cstate)
static

We've succeeded in establishing a connection.

Parameters
cstatethe connection we tried to establish

Definition at line 483 of file client.c.

484{
485 GNUNET_assert (NULL == cstate->recv_task);
486 cstate->recv_task
488 cstate->sock,
490 cstate);
491 if (NULL != cstate->msg)
492 {
493 GNUNET_assert (NULL == cstate->send_task);
494 cstate->send_task
496 cstate->sock,
498 cstate);
499 }
500}

References GNUNET_assert, GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_write_net(), GNUNET_TIME_UNIT_FOREVER_REL, ClientState::msg, receive_ready(), ClientState::recv_task, ClientState::send_task, ClientState::sock, and transmit_ready().

Referenced by connect_probe_continuation(), and start_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_unixpath()

static struct GNUNET_NETWORK_Handle * try_unixpath ( const char *  service_name,
const struct GNUNET_CONFIGURATION_Handle cfg 
)
static

Try connecting to the server using UNIX domain sockets.

Parameters
service_namename of service to connect to
cfgconfiguration to use
Returns
NULL on error, socket connected to UNIX otherwise

Definition at line 511 of file client.c.

513{
514#if AF_UNIX
515 struct GNUNET_NETWORK_Handle *sock;
516 char *unixpath;
517 struct sockaddr_un s_un;
518
519 unixpath = NULL;
520 if ((GNUNET_OK ==
523 "UNIXPATH",
524 &unixpath)) &&
525 (0 < strlen (unixpath)))
526 {
527 /* We have a non-NULL unixpath, need to validate it */
528 if (strlen (unixpath) >= sizeof(s_un.sun_path))
529 {
531 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
532 unixpath,
533 (unsigned long long) sizeof(s_un.sun_path));
534 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
536 _ ("Using `%s' instead\n"),
537 unixpath);
538 if (NULL == unixpath)
539 return NULL;
540 }
541 memset (&s_un,
542 0,
543 sizeof(s_un));
544 s_un.sun_family = AF_UNIX;
545 GNUNET_strlcpy (s_un.sun_path,
546 unixpath,
547 sizeof(s_un.sun_path));
548#if HAVE_SOCKADDR_UN_SUN_LEN
549 s_un.sun_len = (u_char) sizeof(struct sockaddr_un);
550#endif
551 sock = GNUNET_NETWORK_socket_create (AF_UNIX,
552 SOCK_STREAM,
553 0);
554 if ((NULL != sock) &&
555 ((GNUNET_OK ==
557 (struct sockaddr *) &s_un,
558 sizeof(s_un))) ||
559 (EINPROGRESS == errno)))
560 {
562 "Successfully connected to unixpath `%s'!\n",
563 unixpath);
564 GNUNET_free (unixpath);
565 return sock;
566 }
567 if (NULL != sock)
569 }
570 GNUNET_free (unixpath);
571#endif
572 return NULL;
573}

References _, cfg, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_NETWORK_shorten_unixpath(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_connect(), GNUNET_NETWORK_socket_create(), GNUNET_OK, GNUNET_strlcpy(), LOG, and service_name.

Referenced by start_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connect_probe_continuation()

static void connect_probe_continuation ( void *  cls)
static

Scheduler let us know that we're either ready to write on the socket OR connect timed out.

Do the right thing.

Parameters
clsthe struct AddressProbe * with the address that we are probing

Definition at line 583 of file client.c.

584{
585 struct AddressProbe *ap = cls;
586 struct ClientState *cstate = ap->cstate;
587 const struct GNUNET_SCHEDULER_TaskContext *tc;
588 int error;
589 socklen_t len;
590
591 ap->task = NULL;
592 GNUNET_assert (NULL != ap->sock);
594 cstate->ap_tail,
595 ap);
596 len = sizeof(error);
597 error = 0;
600 (GNUNET_OK !=
602 SOL_SOCKET,
603 SO_ERROR,
604 &error,
605 &len)) ||
606 (0 != error))
607 {
610 GNUNET_free (ap);
611 if ((NULL == cstate->ap_head) &&
612 // (NULL == cstate->proxy_handshake) &&
613 (NULL == cstate->dns_active))
615 return;
616 }
618 "Connection to `%s' succeeded!\n",
619 cstate->service_name);
620 /* trigger jobs that waited for the connection */
621 GNUNET_assert (NULL == cstate->sock);
622 cstate->sock = ap->sock;
623 GNUNET_free (ap);
624 cancel_aps (cstate);
626}

References ClientState::ap_head, ClientState::ap_tail, cancel_aps(), connect_fail_continuation(), connect_success_continuation(), AddressProbe::cstate, ClientState::dns_active, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_getsockopt(), GNUNET_OK, GNUNET_SCHEDULER_get_task_context(), GNUNET_SCHEDULER_REASON_WRITE_READY, LOG, GNUNET_SCHEDULER_TaskContext::reason, ClientState::service_name, AddressProbe::sock, ClientState::sock, AddressProbe::task, and tc.

Referenced by try_connect_using_address().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_connect_using_address()

static void try_connect_using_address ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Try to establish a connection given the specified address.

This function is called by the resolver once we have a DNS reply.

Parameters
clsour struct ClientState *
addraddress to try, NULL for "last call"
addrlenlength of addr

Definition at line 638 of file client.c.

641{
642 struct ClientState *cstate = cls;
643 struct AddressProbe *ap;
644
645 if (NULL == addr)
646 {
647 cstate->dns_active = NULL;
648 if ((NULL == cstate->ap_head) &&
649 // (NULL == cstate->proxy_handshake) &&
650 (NULL == cstate->sock))
652 return;
653 }
654 if (NULL != cstate->sock)
655 return; /* already connected */
656 /* try to connect */
658 "Trying to connect using address `%s:%u'\n",
660 addrlen),
661 (unsigned int) cstate->port);
662 ap = GNUNET_malloc (sizeof(struct AddressProbe) + addrlen);
663 ap->addr = (const struct sockaddr *) &ap[1];
664 GNUNET_memcpy (&ap[1],
665 addr,
666 addrlen);
667 ap->addrlen = addrlen;
668 ap->cstate = cstate;
669
670 switch (ap->addr->sa_family)
671 {
672 case AF_INET:
673 ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
674 break;
675
676 case AF_INET6:
677 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
678 break;
679
680 default:
681 GNUNET_break (0);
682 GNUNET_free (ap);
683 return; /* not supported by us */
684 }
685 ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
686 SOCK_STREAM,
687 0);
688 if (NULL == ap->sock)
689 {
690 GNUNET_free (ap);
691 return; /* not supported by OS */
692 }
693 if ((GNUNET_OK !=
695 ap->addr,
696 ap->addrlen)) &&
697 (EINPROGRESS != errno))
698 {
699 /* maybe refused / unsupported address, try next */
701 "connect");
704 GNUNET_free (ap);
705 return;
706 }
708 cstate->ap_tail,
709 ap);
711 ap->sock,
713 ap);
714}

References AddressProbe::addr, AddressProbe::addrlen, ClientState::ap_head, ClientState::ap_tail, connect_fail_continuation(), connect_probe_continuation(), CONNECT_RETRY_TIMEOUT, AddressProbe::cstate, ClientState::dns_active, GNUNET_a2s(), GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log_strerror, GNUNET_malloc, GNUNET_memcpy, GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_connect(), GNUNET_NETWORK_socket_create(), GNUNET_OK, GNUNET_SCHEDULER_add_write_net(), LOG, ClientState::port, AddressProbe::sock, ClientState::sock, and AddressProbe::task.

Referenced by start_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ test_service_configuration()

static int test_service_configuration ( const char *  service_name,
const struct GNUNET_CONFIGURATION_Handle cfg 
)
static

Test whether the configuration has proper values for connection (UNIXPATH || (PORT && HOSTNAME)).

Parameters
service_namename of service to connect to
cfgconfiguration to use
Returns
GNUNET_OK if the configuration is valid, GNUNET_SYSERR if not

Definition at line 726 of file client.c.

728{
729 int ret = GNUNET_SYSERR;
730 char *hostname = NULL;
731 unsigned long long port;
732
733#if AF_UNIX
734 char *unixpath = NULL;
735
736 if ((GNUNET_OK ==
739 "UNIXPATH",
740 &unixpath)) &&
741 (0 < strlen (unixpath)))
742 ret = GNUNET_OK;
743 else if ((GNUNET_OK ==
746 "UNIXPATH")))
747 {
750 "UNIXPATH",
751 _ ("not a valid filename"));
752 GNUNET_free (unixpath);
753 return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */
754 }
755 GNUNET_free (unixpath);
756#endif
757
758 if ((GNUNET_YES ==
761 "PORT")) &&
762 (GNUNET_OK ==
765 "PORT",
766 &port)) &&
767 (port <= 65535) &&
768 (0 != port) &&
769 (GNUNET_OK ==
772 "HOSTNAME",
773 &hostname)) &&
774 (0 != strlen (hostname)))
775 ret = GNUNET_OK;
776 GNUNET_free (hostname);
777 return ret;
778}

References _, cfg, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_have_value(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log_config_invalid(), GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, port, ret, and service_name.

Referenced by GNUNET_CLIENT_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connection_client_send_impl()

static void connection_client_send_impl ( struct GNUNET_MQ_Handle mq,
const struct GNUNET_MessageHeader msg,
void *  impl_state 
)
static

Implements the transmission functionality of a message queue.

Parameters
mqthe message queue
msgthe message to send
impl_stateour struct ClientState

Definition at line 841 of file client.c.

844{
845 struct ClientState *cstate = impl_state;
846
847 (void) mq;
848 /* only one message at a time allowed */
849 GNUNET_assert (NULL == cstate->msg);
850 GNUNET_assert (NULL == cstate->send_task);
851 cstate->msg = msg;
852 cstate->msg_off = 0;
853 if (NULL == cstate->sock)
854 {
856 "message of type %u waiting for socket\n",
857 ntohs (msg->type));
858 return; /* still waiting for connection */
859 }
860 cstate->send_task
862 cstate);
863}

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_SCHEDULER_add_now(), LOG, mq, msg, ClientState::msg, ClientState::msg_off, ClientState::send_task, ClientState::sock, transmit_ready(), and GNUNET_MessageHeader::type.

Referenced by GNUNET_CLIENT_connect().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ connection_client_cancel_impl()

static void connection_client_cancel_impl ( struct GNUNET_MQ_Handle mq,
void *  impl_state 
)
static

Cancel the currently sent message.

Parameters
mqmessage queue
impl_stateour struct ClientState

Definition at line 873 of file client.c.

875{
876 struct ClientState *cstate = impl_state;
877
878 (void) mq;
879 GNUNET_assert (NULL != cstate->msg);
880 GNUNET_assert (0 == cstate->msg_off);
881 cstate->msg = NULL;
882 if (NULL != cstate->send_task)
883 {
885 cstate->send_task = NULL;
886 }
887}

References GNUNET_assert, GNUNET_SCHEDULER_cancel(), mq, ClientState::msg, ClientState::msg_off, and ClientState::send_task.

Referenced by GNUNET_CLIENT_connect().

Here is the call graph for this function:
Here is the caller graph for this function: