aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-11 11:05:35 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-11 11:05:35 +0000
commit6202dff2295abe7813a12bb53b90916bf26bb132 (patch)
treeb85554987672862cdff97a597f8311df8ce55b28
parentac8f7679c65c1bea265f2a1501a5f6901a1227e9 (diff)
downloadgnunet-6202dff2295abe7813a12bb53b90916bf26bb132.tar.gz
gnunet-6202dff2295abe7813a12bb53b90916bf26bb132.zip
use bind instead of connect to test if service is running to avoid long timeouts during startup
-rw-r--r--src/arm/arm_api.c3
-rw-r--r--src/arm/gnunet-arm.c2
-rw-r--r--src/transport/Makefile.am1
-rw-r--r--src/util/client.c174
-rw-r--r--src/util/network.c2
5 files changed, 176 insertions, 6 deletions
diff --git a/src/arm/arm_api.c b/src/arm/arm_api.c
index c5caa5393..4114b8528 100644
--- a/src/arm/arm_api.c
+++ b/src/arm/arm_api.c
@@ -379,8 +379,6 @@ arm_service_report (void *cls,
379 "Looks like `%s' is not running, will start it.\n", 379 "Looks like `%s' is not running, will start it.\n",
380 "gnunet-service-arm"); 380 "gnunet-service-arm");
381#endif 381#endif
382 /* FIXME: should we check that HOSTNAME for 'arm' is localhost? */
383
384 if (GNUNET_OK != 382 if (GNUNET_OK !=
385 GNUNET_CONFIGURATION_get_value_string (pos->h->cfg, 383 GNUNET_CONFIGURATION_get_value_string (pos->h->cfg,
386 "arm", "PREFIX", &loprefix)) 384 "arm", "PREFIX", &loprefix))
@@ -621,6 +619,7 @@ GNUNET_ARM_start_service (struct GNUNET_ARM_Handle *h,
621 struct RequestContext *sctx; 619 struct RequestContext *sctx;
622 struct GNUNET_CLIENT_Connection *client; 620 struct GNUNET_CLIENT_Connection *client;
623 size_t slen; 621 size_t slen;
622
624#if DEBUG_ARM 623#if DEBUG_ARM
625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
626 _("Asked to start service `%s' within %llu ms\n"), service_name, 625 _("Asked to start service `%s' within %llu ms\n"), service_name,
diff --git a/src/arm/gnunet-arm.c b/src/arm/gnunet-arm.c
index c2663aba9..ccad0f21f 100644
--- a/src/arm/gnunet-arm.c
+++ b/src/arm/gnunet-arm.c
@@ -46,7 +46,7 @@
46 * (by checking if running before starting, so really this time is always waited on 46 * (by checking if running before starting, so really this time is always waited on
47 * startup (annoying)). 47 * startup (annoying)).
48 */ 48 */
49#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 1000) 49#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
50 50
51/** 51/**
52 * Timeout for starting services, very short because of the strange way start works 52 * Timeout for starting services, very short because of the strange way start works
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 74f79013e..417fdef5a 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -333,6 +333,7 @@ test_transport_api_disconnect_SOURCES = \
333 test_transport_api_disconnect.c 333 test_transport_api_disconnect.c
334test_transport_api_disconnect_LDADD = \ 334test_transport_api_disconnect_LDADD = \
335 $(top_builddir)/src/transport/libgnunettransport.la \ 335 $(top_builddir)/src/transport/libgnunettransport.la \
336 $(top_builddir)/src/hello/libgnunethello.la \
336 $(top_builddir)/src/statistics/libgnunetstatistics.la \ 337 $(top_builddir)/src/statistics/libgnunetstatistics.la \
337 $(top_builddir)/src/testing/libgnunettesting.la \ 338 $(top_builddir)/src/testing/libgnunettesting.la \
338 $(top_builddir)/src/util/libgnunetutil.la 339 $(top_builddir)/src/util/libgnunetutil.la
diff --git a/src/util/client.c b/src/util/client.c
index 490d1f3da..a05c5bf75 100644
--- a/src/util/client.c
+++ b/src/util/client.c
@@ -666,6 +666,15 @@ confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg)
666} 666}
667 667
668 668
669/**
670 * Send the 'TEST' message to the service. If successful, prepare to
671 * receive the reply.
672 *
673 * @param cls the 'struct GNUNET_CLIENT_Connection' of the connection to test
674 * @param size number of bytes available in buf
675 * @param buf where to write the message
676 * @return number of bytes written to buf
677 */
669static size_t 678static size_t
670write_test (void *cls, size_t size, void *buf) 679write_test (void *cls, size_t size, void *buf)
671{ 680{
@@ -698,11 +707,13 @@ write_test (void *cls, size_t size, void *buf)
698 707
699 708
700/** 709/**
701 * Wait until the service is running. 710 * Test if the service is running. If we are given a UNIXPATH or a local address,
711 * we do this NOT by trying to connect to the service, but by trying to BIND to
712 * the same port. If the BIND fails, we know the service is running.
702 * 713 *
703 * @param service name of the service to wait for 714 * @param service name of the service to wait for
704 * @param cfg configuration to use 715 * @param cfg configuration to use
705 * @param timeout how long to wait at most in ms 716 * @param timeout how long to wait at most
706 * @param task task to run if service is running 717 * @param task task to run if service is running
707 * (reason will be "PREREQ_DONE" (service running) 718 * (reason will be "PREREQ_DONE" (service running)
708 * or "TIMEOUT" (service not known to be running)) 719 * or "TIMEOUT" (service not known to be running))
@@ -714,12 +725,171 @@ GNUNET_CLIENT_service_test (const char *service,
714 struct GNUNET_TIME_Relative timeout, 725 struct GNUNET_TIME_Relative timeout,
715 GNUNET_SCHEDULER_Task task, void *task_cls) 726 GNUNET_SCHEDULER_Task task, void *task_cls)
716{ 727{
728 char *hostname;
729 unsigned long long port;
730 struct GNUNET_NETWORK_Handle *sock;
717 struct GNUNET_CLIENT_Connection *conn; 731 struct GNUNET_CLIENT_Connection *conn;
718 732
719#if DEBUG_CLIENT 733#if DEBUG_CLIENT
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
721 "Testing if service `%s' is running.\n", service); 735 "Testing if service `%s' is running.\n", service);
722#endif 736#endif
737#ifdef AF_UNIX
738 {
739 /* probe UNIX support */
740 struct sockaddr_un s_un;
741 size_t slen;
742 char *unixpath;
743
744 unixpath = NULL;
745 if ( (GNUNET_OK ==
746 GNUNET_CONFIGURATION_get_value_string (cfg,
747 service,
748 "UNIXPATH", &unixpath)) &&
749 (0 < strlen (unixpath)) ) /* We have a non-NULL unixpath, does that mean it's valid? */
750 {
751 if (strlen(unixpath) >= sizeof(s_un.sun_path))
752 {
753 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
754 _("UNIXPATH `%s' too long, maximum length is %llu\n"),
755 unixpath,
756 sizeof(s_un.sun_path));
757 }
758 else
759 {
760 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
761 if (sock != NULL)
762 {
763 memset (&s_un, 0, sizeof (s_un));
764 s_un.sun_family = AF_UNIX;
765 slen = strlen (unixpath) + 1;
766 if (slen >= sizeof (s_un.sun_path))
767 slen = sizeof (s_un.sun_path) - 1;
768 memcpy (s_un.sun_path,
769 unixpath,
770 slen);
771 s_un.sun_path[slen] = '\0';
772 slen = sizeof (struct sockaddr_un);
773#if LINUX
774 s_un.sun_path[0] = '\0';
775#endif
776#if HAVE_SOCKADDR_IN_SIN_LEN
777 s_un.sun_len = (u_char) slen;
778#endif
779 if (GNUNET_OK !=
780 GNUNET_NETWORK_socket_bind (sock,
781 (const struct sockaddr*) &s_un,
782 slen))
783 {
784 /* failed to bind => service must be running */
785 GNUNET_free (unixpath);
786 (void) GNUNET_NETWORK_socket_close (sock);
787 GNUNET_SCHEDULER_add_continuation (task,
788 task_cls,
789 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
790 return;
791 }
792 (void) GNUNET_NETWORK_socket_close (sock);
793 }
794 /* let's try IP */
795 }
796 }
797 GNUNET_free_non_null (unixpath);
798 }
799#endif
800
801 hostname = NULL;
802 if ((GNUNET_OK !=
803 GNUNET_CONFIGURATION_get_value_number (cfg,
804 service,
805 "PORT",
806 &port)) ||
807 (port > 65535) ||
808 (GNUNET_OK !=
809 GNUNET_CONFIGURATION_get_value_string (cfg,
810 service,
811 "HOSTNAME", &hostname)))
812 {
813 /* UNIXPATH failed (if possible) AND IP failed => error */
814 service_test_error (task, task_cls);
815 return;
816 }
817
818 if (0 == strcmp ("localhost", hostname))
819 {
820 /* can test using 'bind' */
821 struct sockaddr_in s_in;
822
823 memset (&s_in, 0, sizeof (s_in));
824#if HAVE_SOCKADDR_IN_SIN_LEN
825 s_in.sin_len = saddrlens[1];
826#endif
827 s_in.sin_family = AF_INET;
828 s_in.sin_port = htons (port);
829
830 sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
831 if (sock != NULL)
832 {
833 if (GNUNET_OK !=
834 GNUNET_NETWORK_socket_bind (sock,
835 (const struct sockaddr*) &s_in,
836 sizeof (s_in)))
837 {
838 /* failed to bind => service must be running */
839 GNUNET_free (hostname);
840 (void) GNUNET_NETWORK_socket_close (sock);
841 GNUNET_SCHEDULER_add_continuation (task,
842 task_cls,
843 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
844 return;
845 }
846 (void) GNUNET_NETWORK_socket_close (sock);
847 }
848 }
849
850 if (0 == strcmp ("ip6-localhost", hostname))
851 {
852 /* can test using 'bind' */
853 struct sockaddr_in6 s_in6;
854
855 memset (&s_in6, 0, sizeof (s_in6));
856#if HAVE_SOCKADDR_IN_SIN_LEN
857 s_in6.sin6_len = saddrlens[1];
858#endif
859 s_in6.sin6_family = AF_INET6;
860 s_in6.sin6_port = htons (port);
861
862 sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
863 if (sock != NULL)
864 {
865 if (GNUNET_OK !=
866 GNUNET_NETWORK_socket_bind (sock,
867 (const struct sockaddr*) &s_in6,
868 sizeof (s_in6)))
869 {
870 /* failed to bind => service must be running */
871 GNUNET_free (hostname);
872 (void) GNUNET_NETWORK_socket_close (sock);
873 GNUNET_SCHEDULER_add_continuation (task,
874 task_cls,
875 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
876 return;
877 }
878 (void) GNUNET_NETWORK_socket_close (sock);
879 }
880 }
881
882 if ( (0 == strcmp ("localhost", hostname)) ||
883 (0 == strcmp ("ip6-localhost", hostname)) )
884 {
885 /* all binds succeeded => claim service not running right now */
886 GNUNET_free_non_null (hostname);
887 service_test_error (task, task_cls);
888 return;
889 }
890 GNUNET_free_non_null (hostname);
891
892 /* non-localhost, try 'connect' method */
723 conn = GNUNET_CLIENT_connect (service, cfg); 893 conn = GNUNET_CLIENT_connect (service, cfg);
724 if (conn == NULL) 894 if (conn == NULL)
725 { 895 {
diff --git a/src/util/network.c b/src/util/network.c
index 9c6d0c90b..98eeb7b0c 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -321,7 +321,7 @@ GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
321 SetErrnoFromWinsockError (WSAGetLastError ()); 321 SetErrnoFromWinsockError (WSAGetLastError ());
322#endif 322#endif
323 if (ret != 0) 323 if (ret != 0)
324 return GNUNET_SYSERR; 324 return GNUNET_SYSERR;
325#ifndef MINGW 325#ifndef MINGW
326#ifndef LINUX 326#ifndef LINUX
327 desc->addr = GNUNET_malloc (address_len); 327 desc->addr = GNUNET_malloc (address_len);