diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-09-27 23:12:21 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-09-27 23:12:21 +0200 |
commit | c8ed84e481b4abfb7d4ed844a4d74b979917c466 (patch) | |
tree | b37f1dfbfb279b78a4346ec22bc298bb500e8fb4 /src/util/client.c | |
parent | eadf4b7379049d32d7cfc5cffd4c88613f8a2a93 (diff) | |
download | gnunet-c8ed84e481b4abfb7d4ed844a4d74b979917c466.tar.gz gnunet-c8ed84e481b4abfb7d4ed844a4d74b979917c466.zip |
implementing GNUNET_CLIENT_test() to check for service operating
Diffstat (limited to 'src/util/client.c')
-rw-r--r-- | src/util/client.c | 177 |
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 | */ | ||
892 | int | ||
893 | GNUNET_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 | * |