summaryrefslogtreecommitdiff
path: root/src/util/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/client.c')
-rw-r--r--src/util/client.c177
1 files changed, 166 insertions, 11 deletions
diff --git a/src/util/client.c b/src/util/client.c
index 5a77b9238..d431909cf 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -534,17 +534,6 @@ try_unixpath (const char *service_name,
534 GNUNET_strlcpy (s_un.sun_path, 534 GNUNET_strlcpy (s_un.sun_path,
535 unixpath, 535 unixpath,
536 sizeof(s_un.sun_path)); 536 sizeof(s_un.sun_path));
537#ifdef LINUX
538 {
539 int abstract;
540
541 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
542 "TESTING",
543 "USE_ABSTRACT_SOCKETS");
544 if (GNUNET_YES == abstract)
545 s_un.sun_path[0] = '\0';
546 }
547#endif
548#if HAVE_SOCKADDR_UN_SUN_LEN 537#if HAVE_SOCKADDR_UN_SUN_LEN
549 s_un.sun_len = (u_char) sizeof(struct sockaddr_un); 538 s_un.sun_len = (u_char) sizeof(struct sockaddr_un);
550#endif 539#endif
@@ -889,6 +878,172 @@ connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
889 878
890 879
891/** 880/**
881 * Test if the port or UNIXPATH of the given @a service_name
882 * is in use and thus (most likely) the respective service is up.
883 *
884 * @param cfg our configuration
885 * @param service_name name of the service to connect to
886 * @return #GNUNET_YES if the service is (likely) up,
887 * #GNUNET_NO if the service is (definitively) down,
888 * #GNUNET_SYSERR if the configuration does not give us
889 * the necessary information about the service, or if
890 * we could not check (i.e. socket() failed)
891 */
892int
893GNUNET_CLIENT_test (const struct GNUNET_CONFIGURATION_Handle *cfg,
894 const char *service_name)
895{
896 char *hostname = NULL;
897 unsigned long long port;
898 int ret;
899
900#if AF_UNIX
901 {
902 char *unixpath = NULL;
903
904 if (GNUNET_OK ==
905 GNUNET_CONFIGURATION_get_value_filename (cfg,
906 service_name,
907 "UNIXPATH",
908 &unixpath))
909 {
910 if (0 == strlen (unixpath))
911 {
912 GNUNET_free (unixpath);
913 return GNUNET_SYSERR; /* empty string not OK */
914 }
915 if (0 == access (unixpath,
916 F_OK))
917 {
918 GNUNET_free (unixpath);
919 return GNUNET_OK; /* file exists, we assume service is running */
920 }
921 GNUNET_free (unixpath);
922 }
923 else if (GNUNET_OK ==
924 GNUNET_CONFIGURATION_have_value (cfg,
925 service_name,
926 "UNIXPATH"))
927 {
928 /* UNIXPATH specified but not a valid path! */
929 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
930 service_name,
931 "UNIXPATH",
932 _ ("not a valid filename"));
933 return GNUNET_SYSERR;
934 }
935 }
936#endif
937
938 if ( (GNUNET_OK !=
939 GNUNET_CONFIGURATION_get_value_number (cfg,
940 service_name,
941 "PORT",
942 &port)) ||
943 (port > 65535) ||
944 (0 == port) )
945 {
946 return GNUNET_SYSERR;
947 }
948 if (GNUNET_OK ==
949 GNUNET_CONFIGURATION_get_value_string (cfg,
950 service_name,
951 "HOSTNAME",
952 &hostname))
953 {
954 /* We always assume remotes are up */
955 ret = GNUNET_YES;
956 }
957 else
958 {
959 /* We look for evidence the service is up */
960 ret = GNUNET_NO;
961 }
962 if ( (NULL == hostname) ||
963 (0 == strcasecmp (hostname,
964 "localhost")) ||
965 (0 == strcasecmp (hostname,
966 "ip6-localnet")) )
967 {
968 /* service runs on loopback */
969 struct sockaddr_in v4;
970 struct sockaddr_in6 v6;
971 int sock;
972
973 memset (&v4, 0, sizeof (v4));
974 memset (&v6, 0, sizeof (v6));
975 v4.sin_family = AF_INET;
976 v4.sin_port = htons ((uint16_t) port);
977#if HAVE_SOCKADDR_IN_SUN_LEN
978 v4.sin_len = (u_char) sizeof(struct sockaddr_in);
979#endif
980 inet_pton (AF_INET,
981 "127.0.0.1",
982 &v4.sin_addr);
983 ret = GNUNET_NO;
984 sock = socket (AF_INET,
985 SOCK_STREAM,
986 0);
987 if (-1 != sock)
988 {
989 if (0 != bind (sock,
990 (struct sockaddr *) &v4,
991 sizeof (v4)))
992 {
993 /* bind failed, so someone is listening! */
994 ret = GNUNET_YES;
995 }
996 (void) close (sock);
997 }
998 else
999 {
1000 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1001 "socket");
1002 if (GNUNET_NO == ret)
1003 ret = GNUNET_SYSERR;
1004 }
1005 v6.sin6_family = AF_INET6;
1006 v6.sin6_port = htons ((uint16_t) port);
1007#if HAVE_SOCKADDR_IN_SUN_LEN
1008 v6.sin6_len = (u_char) sizeof(struct sockaddr_in6);
1009#endif
1010 inet_pton (AF_INET6,
1011 "::1",
1012 &v6.sin6_addr);
1013 sock = socket (AF_INET6,
1014 SOCK_STREAM,
1015 0);
1016 if (-1 != sock)
1017 {
1018 if (0 != bind (sock,
1019 (struct sockaddr *) &v6,
1020 sizeof (v6)))
1021 {
1022 /* bind failed, so someone is listening! */
1023 ret = GNUNET_YES;
1024 }
1025 (void) close (sock);
1026 }
1027 else
1028 {
1029 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1030 "socket");
1031 /* not changing 'ret' intentionally here, as
1032 v4 succeeding and v6 failing just means we
1033 should use v4 */
1034 }
1035 }
1036 else
1037 {
1038 /* service running remotely */
1039 ret = GNUNET_OK;
1040 }
1041 GNUNET_free_non_null (hostname);
1042 return ret;
1043}
1044
1045
1046/**
892 * Create a message queue to connect to a GNUnet service. 1047 * Create a message queue to connect to a GNUnet service.
893 * If handlers are specfied, receive messages from the connection. 1048 * If handlers are specfied, receive messages from the connection.
894 * 1049 *