+* 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.)
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
--- /dev/null
+<?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>
.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
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
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.
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 \
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
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
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 \
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)
%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
#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
#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;
int noverify;
int anonymous;
int gridhttp;
- int verbose; } ;
+ int verbose;
+ int timeout;
+ char *groups; } ;
struct grst_index_blob { char *text;
size_t used;
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 */
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 >=
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},
{"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)
common_data.anonymous = 0;
common_data.gridhttp = 0;
+ common_data.groups = NULL;
+ common_data.timeout = 0;
+
while (1)
{
option_index = 0;
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);
}
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) ||