Add SiteCast ping to htcp
authorAndrew McNab <andrew.mcnab@manchester.ac.uk>
Fri, 30 Sep 2005 21:03:39 +0000 (21:03 +0000)
committerAndrew McNab <andrew.mcnab@manchester.ac.uk>
Fri, 30 Sep 2005 21:03:39 +0000 (21:03 +0000)
org.gridsite.core/CHANGES
org.gridsite.core/doc/config.html
org.gridsite.core/doc/delegation-1.wsdl [new file with mode: 0644]
org.gridsite.core/doc/htcp.1
org.gridsite.core/src/Makefile
org.gridsite.core/src/gridsite.spec
org.gridsite.core/src/htcp
org.gridsite.core/src/htcp.c

index beef484..ba03db6 100644 (file)
@@ -1,3 +1,5 @@
+* Fri Sep 30 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
+- Add SiteCast ping (NOP) support to htcp
 * Thu Sep 29 2005 Andrew McNab <Andrew.McNab@man.ac.uk>
 - Add SiteCast support to mod_gridsite (file location
   discovery via UDP multicast of HTCP messages.)
index 2edeb27..8c3811c 100644 (file)
@@ -36,9 +36,8 @@ GridSite also includes some commands and man pages in /usr/bin and
 You must also install the CA root certificates of the CA's 
 used by the users you wish to talk to. These should be installed in
 /etc/grid-security/certificates as files like 01621954.0, and RPMs and tar
-files for many common European and North American CAs are available from
-<a href="https://datagrid.in2p3.fr/distribution/datagrid/security/">
-https://datagrid.in2p3.fr/distribution/datagrid/security/</a>
+files for many common European and North American CAs are available via the
+<a href="http://www.eugridpma.org/">EU Grid PMA</a>.
 
 <p>
 This location also has VOMS server certificate RPMs which install into
diff --git a/org.gridsite.core/doc/delegation-1.wsdl b/org.gridsite.core/doc/delegation-1.wsdl
new file mode 100644 (file)
index 0000000..35c46ef
--- /dev/null
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<definitions 
+    targetNamespace="http://www.gridsite.org/namespaces/delegation-1" 
+    xmlns="http://schemas.xmlsoap.org/wsdl/" 
+    xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" 
+    xmlns:tns="http://www.gridsite.org/namespaces/delegation-1" 
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <types>
+  <schema 
+        targetNamespace="http://www.gridsite.org/namespaces/delegation-1" 
+        xmlns="http://www.w3.org/2001/XMLSchema">
+   <complexType name="DelegationException">
+    <sequence>
+     <element name="message" nillable="true" type="xsd:string"/>
+    </sequence>
+   </complexType>
+  </schema>
+ </types>
+
+   <message name="getProxyReqResponse">
+      <part name="getProxyReqReturn" type="xsd:string"/>
+   </message>
+   <message name="getProxyReqRequest">
+      <part name="delegationID" type="xsd:string"/>
+   </message>
+
+   <message name="DelegationException">
+      <part name="fault" type="tns:DelegationException"/>
+   </message>
+
+   <message name="putProxyResponse"/>
+   <message name="putProxyRequest">
+      <part name="delegationID" type="xsd:string"/>
+      <part name="proxy" type="xsd:string"/>
+   </message>
+
+   <portType name="Delegation">
+      <operation name="getProxyReq" parameterOrder="delegationID">
+         <documentation>
+            Starts the delegation procedure by asking for a certificate 
+            signing request from the server. The server answers with a
+            certificate signing request which includes the public key 
+            for the new delegated credentials. Uses PEM encoding.
+         </documentation>
+         <input message="tns:getProxyReqRequest" name="getProxyReqRequest"/>
+         <output message="tns:getProxyReqResponse" name="getProxyReqResponse"/>
+         <fault message="tns:DelegationException" name="DelegationException"/>
+      </operation>
+      
+      <operation name="putProxy" parameterOrder="delegationID proxy">
+         <documentation>
+            Finishes the delegation procedure by sending the signed 
+            proxy certificate to the server. Uses PEM encoding.
+         </documentation>
+         <input message="tns:putProxyRequest" name="putProxyRequest"/>
+         <output message="tns:putProxyResponse" name="putProxyResponse"/>
+         <fault message="tns:DelegationException" name="DelegationException"/>
+      </operation>
+   </portType>
+
+   <binding name="DelegationSoapBinding" type="tns:Delegation">
+      <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+
+      <operation name="getProxyReq">
+         <wsdlsoap:operation soapAction=""/>
+         <input name="getProxyReqRequest">
+            <wsdlsoap:body namespace="http://www.gridsite.org/namespaces/delegation-1" use="literal"/>
+         </input>
+         <output name="getProxyReqResponse">
+            <wsdlsoap:body namespace="http://www.gridsite.org/namespaces/delegation-1" use="literal"/>
+         </output>
+         <fault name="DelegationException">
+            <wsdlsoap:fault name="DelegationException" use="literal"/>
+         </fault>
+      </operation>
+
+      <operation name="putProxy">
+         <wsdlsoap:operation soapAction=""/>
+         <input name="putProxyRequest">
+            <wsdlsoap:body namespace="http://www.gridsite.org/namespaces/delegation-1" use="literal"/>
+         </input>
+         <output name="putProxyResponse">
+            <wsdlsoap:body namespace="http://www.gridsite.org/namespaces/delegation-1" use="literal"/>
+         </output>
+         <fault name="DelegationException">
+            <wsdlsoap:fault name="DelegationException" use="literal"/>
+         </fault>
+      </operation>
+   </binding>
+
+</definitions>
index eff665e..f5ce2ac 100644 (file)
@@ -1,16 +1,23 @@
 .TH htcp 1 "September 2005" htcp "HTCP Manual"
 .SH NAME
-.B htcp, htrm, htls, htll, htmkdir, htmv
-\- get, put, delete, list or move HTTP/HTTPS files or directories
+.B htcp, htmv, htrm, htls, htll, htmkdir, htping
+\- file transfers and queries via HTTP/HTTPS/SiteCast
 .SH SYNOPSIS
-.B htcp [options]
-.I Source-URL[s] [Destination URL]
+.B htcp, htmv
+[\fIoptions\fR] \fISource-URL\fR[\fIs\fR] \fIDestination-URL\fR
+.br
+.B htrm, htls, htll, htmkir
+[\fIoptions\fR] \fITarget-URL\fR[\fIs\fR]
+.br
+.B htping
+[\fIoptions\fR]
 .SH DESCRIPTION
 .B htcp
 is a client to fetch files or directory listings from remote servers using
 HTTP or HTTPS, or to put or delete files or directories onto remote servers
 using HTTPS. htcp is similar to scp(1), but uses HTTP/HTTPS rather than ssh
-as its transfer protocol.
+as its transfer protocol. htcp can also use the HTCP protocol to query
+GridSite via SiteCast. 
 
 When talking to an HTTPS server, htcp can run "anonymously", with a
 standard X.509 user certificate and key, or with a GSI Proxy. This makes
@@ -42,22 +49,33 @@ Instead of copying files, output lists of files located in the URL-directories
 given on the command line. Calling the program as htls has the same effect.
 
 .IP "--long-list"
+.br
 Instead of copying files, output long listings of files located in the
 URL-directories given on the command line. If available, the size in bytes
 and modification time of each file is given. Calling the program as 
 htll has the same effect.
 
 .IP "--mkdir"
+.br
 Instead of copying files, attempt to create a directory on a remote server
 with HTTP PUT. The server must support the convention that PUT to a URL with
 a trailing slash means create a directory. No file body is sent. Calling the
 program as htmkdir has the same effect.
 
 .IP "--move"
+.br
 Move/rename files on a single remote server, given the two, absolute URLs
 of the remote file names. Server must support HTTP/WebDAV MOVE. Calling the
 program as htmv has the same effect.
 
+.IP "--ping"
+.br
+Query specified multicast groups with the HTCP NOP code. SiteCast enabled
+servers will respond immediately with a NOP reply, and all of the responses
+will be listed, with the round trip time in milliseconds. Any waiting times
+specified in the --groups option will be ignored. Calling the program as
+htping has the same effect.
+
 .IP "--anon"
 .br
 Do not attempt to use X.509 user certificates or GSI proxies to authenticate
@@ -97,6 +115,17 @@ the GRID_AUTH_ONETIME single-use passcode obtained via HTTPS. The --grid-http
 option will be ignored for directory operations or HTTP URLs. If a redirected
 transfer isn't possible, a normal HTTPS data transfer will be attempted.
 
+.IP "--groups <IP Groups>"
+IP multicast groups to use for SiteCast queries. IP Groups is a comma
+separated list of groups, in the format: 
+nnn.nnn.nnn.nnn[:port[:ttl[:seconds]]] The IP number must be
+specified. If the UDP port isn't given, the default 777 will be used.
+The IP time-to-live, ttl, controls how many networks the multicast packets may
+pass through - the default, 1, limits packets to the local network. Multiple
+groups may be specified, separated by commas.
+If multiple groups are specified, then seconds is the time to wait before
+making the next multicast - 1 second is the default.
+
 .SH FILES
 .IP /tmp/x509up_uID
 Default GSI Proxy file for Unix UID equal to ID.
index 5eeac2e..1ac72cf 100644 (file)
@@ -151,18 +151,18 @@ libgridsite_globus.a: libgridsite.a
 endif
 
 gsexec:        gsexec.c gsexec.h
-       gcc -g -DVERSION=\"$(PATCH_VERSION)\" -I/usr/include/httpd \
-           -I/usr/include/apr-0 \
+       gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
            -o gsexec gsexec.c
 
 urlencode: urlencode.c libgridsite.a
        gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
             -o urlencode urlencode.c -L. \
-             -I/usr/kerberos/include -lgridsite
+            -I/usr/kerberos/include -lgridsite
 
-htcp: htcp.c
-       gcc -g -DVERSION=\"$(PATCH_VERSION)\" -I. -o htcp htcp.c \
-          `curl-config --cflags` `curl-config --libs` 
+htcp: htcp.c libgridsite.a
+       gcc -g -DVERSION=\"$(PATCH_VERSION)\" $(MYCFLAGS) \
+           -o htcp htcp.c -L. \
+            `curl-config --cflags` `curl-config --libs` -lgridsite
 
 mod_gridsite.so: mod_gridsite.c mod_ssl-private.h libgridsite.a
        gcc -g $(MYCFLAGS) -shared -Wl,-soname=gridsite_module \
@@ -295,7 +295,7 @@ install: apidoc
        cp -f ../CHANGES ../README ../INSTALL ../LICENSE ../VERSION \
                $(prefix)/share/doc/gridsite-$(PATCH_VERSION)
        cp -f ../doc/*.html ../doc/*.conf ../doc/*.1 ../doc/*.8 ../doc/*.sh \
-               $(prefix)/share/doc/gridsite-$(VERSION)
+               ../doc/*.wsdl $(prefix)/share/doc/gridsite-$(VERSION)
        cp -f ../doc/*.1 $(prefix)/share/man/man1
        cp -f ../doc/*.8 $(prefix)/share/man/man8
        gzip -f $(prefix)/share/man/man1/*.1
@@ -308,6 +308,7 @@ install: apidoc
        ln -sf htcp $(prefix)/bin/htrm
        ln -sf htcp $(prefix)/bin/htmkdir
        ln -sf htcp $(prefix)/bin/htmv
+       ln -sf htcp $(prefix)/bin/htping
        cp -f gsexec $(prefix)/sbin
        cp -f mod_gridsite.so $(prefix)/lib/httpd/modules
 
@@ -330,7 +331,7 @@ dist:
                  Doxyfile doxygen.css doxyheader.html \
                  ../gridsite-$(PATCH_VERSION)/src
        cp -f ../doc/*.html ../doc/*.1 ../doc/*.8 ../doc/*.conf ../doc/*.sh \
-                 ../gridsite-$(PATCH_VERSION)/doc
+              ../doc/*.wsdl ../gridsite-$(PATCH_VERSION)/doc
        cp -f ../interface/*.h \
                  ../gridsite-$(PATCH_VERSION)/interface
        cd .. ; tar zcvf gridsite-$(PATCH_VERSION).src.tar.gz \
@@ -345,13 +346,14 @@ htcp-bin: htcp
        cp -f ../doc/README.htcp-bin ../htcp-bin-$(PATCH_VERSION)
        cp -f htcp ../htcp-bin-$(PATCH_VERSION)/bin
        cp -f ../doc/htcp.1 ../doc/htrm.1 ../doc/htls.1 ../doc/htll.1 \
-              ../doc/htmkdir.1 ../doc/htmv.1 \
+              ../doc/htmkdir.1 ../doc/htmv.1 ../doc/htping.1 \
               ../htcp-bin-$(PATCH_VERSION)/man/man1
        ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htls
        ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htll
        ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htrm
        ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htmkdir
        ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htmv
+       ln -sf htcp ../htcp-bin-$(PATCH_VERSION)/bin/htping
        cd ../htcp-bin-$(VERSION) ; tar zcvf ../htcp-$(VERSION).bin.tar.gz .
        rm -Rf ../htcp-bin-$(PATCH_VERSION)
 
index 44bafe3..53d751f 100644 (file)
@@ -90,6 +90,7 @@ rm -f %(echo ${MYPREFIX:-/usr})/share/doc/gridsite
 %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htrm
 %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htmkdir
 %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htmv
+%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htping
 %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htcp.1.gz
 %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htrm.1.gz
 %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htls.1.gz
index 96935f7..42bba47 100644 (file)
Binary files a/org.gridsite.core/src/htcp and b/org.gridsite.core/src/htcp differ
index 3421af5..5b8e281 100644 (file)
 #include <string.h>
 #include <malloc.h>
 #include <dirent.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/select.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <curl/curl.h>
 
+#include "gridsite.h"
+
 /* deal with older versions of libcurl and curl.h */
 
 #ifndef CURLOPT_WRITEDATA
@@ -73,6 +79,9 @@
 #define HTCP_LONGLIST  5
 #define HTCP_MKDIR     6
 #define HTCP_MOVE      7
+#define HTCP_PING      8
+
+#define HTCP_SITECAST_GROUPS 32
 
 struct grst_stream_data { char *source;
                           char *destination;
@@ -87,7 +96,9 @@ struct grst_stream_data { char *source;
                           int   noverify;
                           int   anonymous;
                           int   gridhttp;
-                          int   verbose;       } ;
+                          int   verbose;       
+                          int   timeout;
+                          char *groups;    } ;
                           
 struct grst_index_blob { char   *text;
                          size_t  used;
@@ -108,6 +119,10 @@ struct grst_header_data { int    retcode;
                           int    modified_set;
                           struct grst_stream_data *common_data; } ;
 
+struct grst_sitecast_group { unsigned char quad1; unsigned char quad2; 
+                             unsigned char quad3; unsigned char quad4;
+                             int port; int timewait; int ttl; };
+
 size_t headers_callback(void *ptr, size_t size, size_t nmemb, void *p)
 /* Find the values of the return code, Content-Length, Last-Modified
    and Location headers */
@@ -567,6 +582,125 @@ int do_mkdirs(char *sources[], struct grst_stream_data *common_data)
   return anyerror;
 }
 
+int do_ping(struct grst_stream_data *common_data_ptr)
+{
+  int request_length, response_length, i, ret, s, igroup;
+  struct sockaddr_in srv, from;
+  socklen_t fromlen;
+#define MAXBUF 8192  
+  char *request, response[MAXBUF], *p;
+  GRSThtcpMessage msg;
+  struct timeval start_timeval, wait_timeval, response_timeval;
+  struct grst_sitecast_group sitecast_groups[HTCP_SITECAST_GROUPS];
+  fd_set readsckts;
+
+  /* parse common_data_ptr->groups */ 
+
+  p = common_data_ptr->groups;
+  igroup = -1;
+
+  for (igroup=-1; igroup+1 < HTCP_SITECAST_GROUPS; ++igroup)
+     {  
+       sitecast_groups[igroup+1].port     = GRST_HTCP_PORT;
+       sitecast_groups[igroup+1].timewait = 1;
+       sitecast_groups[igroup+1].ttl      = 1;
+       
+       ret = sscanf(p, "%d.%d.%d.%d:%d:%d:%d", 
+                 &(sitecast_groups[igroup+1].quad1),
+                 &(sitecast_groups[igroup+1].quad2),    
+                 &(sitecast_groups[igroup+1].quad3),
+                 &(sitecast_groups[igroup+1].quad4),    
+                 &(sitecast_groups[igroup+1].port),
+                 &(sitecast_groups[igroup+1].timewait), 
+                 &(sitecast_groups[igroup+1].ttl));
+
+       if (ret == 0) break; /* end of list ? */
+         
+       if (ret < 4)
+         {
+           fprintf(stderr, "Failed to parse multicast group "
+                     "parameter %s\n", p);
+           return CURLE_FAILED_INIT;
+         }
+           
+       ++igroup;
+       
+       if ((p = index(p, ',')) == NULL) break;       
+       ++p;
+     }
+
+  if (igroup == -1)
+    {
+      fprintf(stderr, "Failed to parse multicast group parameter %s\n", p);
+      return CURLE_FAILED_INIT;
+    }
+
+  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
+    {
+      fprintf(stderr, "Failed to open UDP socket\n");
+      return CURLE_FAILED_INIT;
+    }
+
+  /* loop through multicast groups and send off the NOP pings */
+
+  gettimeofday(&start_timeval, NULL);
+
+  for (i=0; i <= igroup; ++i)
+     {
+       bzero(&srv, sizeof(srv));
+       srv.sin_family = AF_INET;
+       srv.sin_port = htons(sitecast_groups[i].port);
+       srv.sin_addr.s_addr = htonl(sitecast_groups[i].quad1*0x1000000
+                                 + sitecast_groups[i].quad2*0x10000
+                                 + sitecast_groups[i].quad3*0x100
+                                 + sitecast_groups[i].quad4);
+
+       GRSThtcpNOPrequestMake(&request, &request_length, 
+                              (int) (start_timeval.tv_usec + i));
+     
+       sendto(s, request, request_length, 0, (struct sockaddr *) &srv,
+                                                    sizeof(srv));
+       free(request);
+     }
+
+  /* reusing wait_timeval is a Linux-specific feature of select() */
+  wait_timeval.tv_sec = common_data_ptr->timeout 
+                                 ? common_data_ptr->timeout : 60;
+  wait_timeval.tv_usec = 0;
+
+  while ((wait_timeval.tv_sec > 0) || (wait_timeval.tv_usec > 0))
+       {
+         FD_ZERO(&readsckts);
+         FD_SET(s, &readsckts);
+  
+         ret = select(s + 1, &readsckts, NULL, NULL, &wait_timeval);
+         gettimeofday(&response_timeval, NULL);
+
+         if (ret > 0)
+           {
+             response_length = recvfrom(s, response, MAXBUF,
+                                        0, &from, &fromlen);
+  
+             if ((GRSThtcpMessageParse(&msg, response, response_length) 
+                                                      == GRST_RET_OK) &&
+                 (msg.opcode == 0) && (msg.rr == 1) && 
+                 (msg.trans_id >= (int) start_timeval.tv_usec) &&
+                 (msg.trans_id <= (int) (start_timeval.tv_usec + igroup)))
+               {
+                 printf("%s:%d %.3fms\n", 
+                          inet_ntoa(from.sin_addr),
+                          ntohs(from.sin_port), 
+                          (((long) 1000000 * response_timeval.tv_sec) +
+                           ((long) response_timeval.tv_usec) -
+                           ((long) 1000000 * start_timeval.tv_sec) -
+                           ((long) start_timeval.tv_usec)) / 1000.0);
+               }
+           }
+       }
+
+   return GRST_RET_OK;
+}
+
 size_t rawindex_callback(void *ptr, size_t size, size_t nmemb, void *data)
 {
   if ( ((struct grst_index_blob *) data)->used + size * nmemb >=
@@ -1043,6 +1177,7 @@ int main(int argc, char *argv[])
   int    c, i, option_index, anyerror;
   struct stat statbuf;
   struct grst_stream_data common_data;
+  struct grst_sitecast_group sitecast_groups[HTCP_SITECAST_GROUPS];
   struct passwd *userpasswd;
   struct option long_options[] = {     {"verbose",             0, 0, 'v'},
                                        {"cert",                1, 0, 0},
@@ -1056,9 +1191,9 @@ int main(int argc, char *argv[])
                                        {"anon",                0, 0, 0},
                                        {"grid-http",           0, 0, 0},
                                        {"move",                0, 0, 0},
-//                                     {"streams",             1, 0, 0},
-//                                     {"blocksize",           1, 0, 0},
-//                                     {"recursive",           0, 0, 0},
+                                       {"ping",                0, 0, 0},
+                                       {"groups",              1, 0, 0},
+                                       {"timeout",             1, 0, 0},
                                        {0, 0, 0, 0}  };
 
 #if (LIBCURL_VERSION_NUM < 0x070908)
@@ -1083,6 +1218,9 @@ int main(int argc, char *argv[])
   common_data.anonymous = 0;
   common_data.gridhttp  = 0;
   
+  common_data.groups    = NULL;
+  common_data.timeout   = 0;
+    
   while (1)
        {
          option_index = 0;
@@ -1103,6 +1241,9 @@ int main(int argc, char *argv[])
              else if (option_index == 9) common_data.anonymous = 1;
              else if (option_index ==10) common_data.gridhttp  = 1;
              else if (option_index ==11) common_data.method    = HTCP_MOVE;
+             else if (option_index ==12) common_data.method    = HTCP_PING;
+             else if (option_index ==13) common_data.groups    = optarg;
+             else if (option_index ==14) common_data.timeout   = atoi(optarg);
            }
          else if (c == 'v') ++(common_data.verbose);
        }
@@ -1185,6 +1326,16 @@ int main(int argc, char *argv[])
       else if (strcmp(executable,"htrm")==0) common_data.method=HTCP_DELETE;
       else if (strcmp(executable,"htmkdir")==0) common_data.method=HTCP_MKDIR;
       else if (strcmp(executable,"htmv")==0) common_data.method=HTCP_MOVE;
+      else if (strcmp(executable,"htping")==0) common_data.method=HTCP_PING;
+    }
+    
+  if (common_data.method == HTCP_PING)
+    {
+      if (common_data.groups != NULL) return do_ping(&common_data);
+
+      fprintf(stderr, "Must specify at least one multicast group\n\n"); 
+      printsyntax(argv[0]);      
+      return CURLE_FAILED_INIT;      
     }
 
   if ((common_data.method == HTCP_DELETE) ||