/******************************************************************************/
/* */
/* X r d C l i e n t P r o t o c o l . c c */
/* */
/* Author: Fabrizio Furano (INFN Padova, 2004) */
/* Adapted from TXNetFile (root.cern.ch) originally done by */
/* Alvise Dorigo, Fabrizio Furano */
/* INFN Padova, 2003 */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
//////////////////////////////////////////////////////////////////////////
// //
// utility functions to deal with the protocol //
// //
//////////////////////////////////////////////////////////////////////////
#include "XProtocol/XProtocol.hh"
#include "XrdSys/XrdSysPlatform.hh"
#include
#ifndef WIN32
#include
#include // needed to use htonl/htons byte swap functions
#endif
#include // proto for memcpy (wanted by Solaris compiler)
#include
#define _htonll(x) htonll(x)
// //____________________________________________________________________________
// kXR_int64 _htonll(kXR_int64 n)
// {
// // custom client routine to convert long long (64 bit integers) from
// // host to network byte order
// return (kXR_int64)host2net(n);
// }
//___________________________________________________________________________
void clientMarshall(ClientRequest* str)
{
// This function applies the network byte order on those
// parts of the 16-bytes buffer, only if it is composed
// by some binary part
kXR_int64 tmpl;
switch(str->header.requestid) {
case kXR_auth:
// no swap on ASCII fields
break;
case kXR_chmod:
str->chmod.mode = htons(str->chmod.mode);
break;
case kXR_close:
// no swap on ASCII fields
break;
case kXR_dirlist:
// no swap on ASCII fields
break;
case kXR_getfile:
str->getfile.options = htonl(str->getfile.options);
str->getfile.buffsz = htonl(str->getfile.buffsz);
break;
case kXR_locate:
str->locate.options = htons(str->getfile.options);
break;
case kXR_login:
str->login.pid = htonl(str->login.pid);
break;
case kXR_mkdir:
// no swap on ASCII fields
str->mkdir.mode = htons(str->mkdir.mode);
break;
case kXR_mv:
// no swap on ASCII fields
break;
case kXR_open:
str->open.mode = htons(str->open.mode);
str->open.options = htons(str->open.options);
break;
case kXR_ping:
// no swap on ASCII fields
break;
case kXR_protocol:
str->protocol.clientpv = htons( str->protocol.clientpv );
break;
case kXR_putfile:
str->putfile.options = htonl(str->putfile.options);
str->putfile.buffsz = htonl(str->putfile.buffsz);
break;
case kXR_query:
str->query.infotype = htons(str->query.infotype);
break;
case kXR_read:
memcpy(&tmpl, &str->read.offset, sizeof(kXR_int64) );
tmpl = _htonll(tmpl);
memcpy(&str->read.offset, &tmpl, sizeof(kXR_int64) );
str->read.rlen = htonl(str->read.rlen);
break;
case kXR_readv:
// no swap on ASCII fields
// and the swap of the list is done in
// clientMarshallReadAheadList
break;
case kXR_rm:
// no swap on ASCII fields
break;
case kXR_rmdir:
// no swap on ASCII fields
break;
case kXR_set:
// no swap on ASCII fields
break;
case kXR_stat:
// no swap on ASCII fields
break;
case kXR_sync:
// no swap on ASCII fields
break;
case kXR_write:
memcpy(&tmpl, &str->write.offset, sizeof(kXR_int64) );
tmpl = _htonll(tmpl);
memcpy(&str->write.offset, &tmpl, sizeof(kXR_int64) );
break;
case kXR_truncate:
memcpy(&tmpl, &str->truncate.offset, sizeof(kXR_int64) );
tmpl = _htonll(tmpl);
memcpy(&str->truncate.offset, &tmpl, sizeof(kXR_int64) );
break;
}
str->header.requestid = htons(str->header.requestid);
str->header.dlen = htonl(str->header.dlen);
}
//___________________________________________________________________________
void clientMarshallReadAheadList(readahead_list *buf_list, kXR_int32 dlen)
{
// This function applies the network byte order on the
// vector of read-ahead information
kXR_int64 tmpl;
int n = dlen / (sizeof(struct readahead_list));
for( int i = 0; i < n; i++ ) {
memcpy(&tmpl, &(buf_list[i].offset), sizeof(kXR_int64) );
tmpl = htonll(tmpl);
memcpy(&(buf_list[i].offset), &tmpl, sizeof(kXR_int64) );
buf_list[i].rlen = htonl(buf_list[i].rlen);
}
}
//___________________________________________________________________________
void clientUnMarshallReadAheadList(readahead_list *buf_list, kXR_int32 dlen)
{
// This function applies the network byte order on the
// vector of read-ahead information
kXR_int64 tmpl;
int n = dlen / (sizeof(struct readahead_list));
for( int i = 0; i < n; i++ ) {
memcpy(&tmpl, &(buf_list[i].offset), sizeof(kXR_int64) );
tmpl = ntohll(tmpl);
memcpy(&(buf_list[i].offset), &tmpl, sizeof(kXR_int64) );
buf_list[i].rlen = ntohl(buf_list[i].rlen);
}
}
//_________________________________________________________________________
void clientUnmarshall(struct ServerResponseHeader* str)
{
str->status = ntohs(str->status);
str->dlen = ntohl(str->dlen);
}
//_________________________________________________________________________
void ServerResponseHeader2NetFmt(struct ServerResponseHeader *srh)
{
srh->status = htons(srh->status);
srh->dlen = htonl(srh->dlen);
}
//_________________________________________________________________________
void ServerInitHandShake2HostFmt(struct ServerInitHandShake *srh)
{
srh->msglen = ntohl(srh->msglen);
srh->protover = ntohl(srh->protover);
srh->msgval = ntohl(srh->msgval);
}
//_________________________________________________________________________
bool isRedir(struct ServerResponseHeader *ServerResponse)
{
// Recognizes if the response contains a redirection
return ( (ServerResponse->status == kXR_redirect) ? true : false);
}
//_________________________________________________________________________
char *convertRequestIdToChar(kXR_unt16 requestid)
{
// This procedure convert the request code id (an integer defined in
// XProtocol.hhh) in the ascii label (human readable)
switch(requestid) {
case kXR_auth:
return (char *)"kXR_auth";
break;
case kXR_chmod:
return (char *)"kXR_chmod";
break;
case kXR_close:
return (char *)"kXR_close";
break;
case kXR_dirlist:
return (char *)"kXR_dirlist";
break;
case kXR_getfile:
return (char *)"kXR_getfile";
break;
case kXR_locate:
return (char *)"kXR_locate";
break;
case kXR_login:
return (char *)"kXR_login";
break;
case kXR_mkdir:
return (char *)"kXR_mkdir";
break;
case kXR_mv:
return (char *)"kXR_mv";
break;
case kXR_open:
return (char *)"kXR_open";
break;
case kXR_ping:
return (char *)"kXR_ping";
break;
case kXR_protocol:
return (char *)"kXR_protocol";
break;
case kXR_putfile:
return (char *)"kXR_putfile";
break;
case kXR_query:
return (char *)"kXR_query";
break;
case kXR_read:
return (char *)"kXR_read";
break;
case kXR_readv:
return (char *)"kXR_readv";
break;
case kXR_rm:
return (char *)"kXR_rm";
break;
case kXR_rmdir:
return (char *)"kXR_rmdir";
break;
case kXR_set:
return (char *)"kXR_set";
break;
case kXR_stat:
return (char *)"kXR_stat";
break;
case kXR_sync:
return (char *)"kXR_sync";
break;
case kXR_write:
return (char *)"kXR_write";
break;
case kXR_prepare:
return (char *)"kXR_prepare";
break;
case kXR_admin:
return (char *)"kXR_admin";
break;
case kXR_statx:
return (char *)"kXR_statx";
break;
case kXR_endsess:
return (char *)"kXR_endsess";
break;
case kXR_bind:
return (char *)"kXR_bind";
break;
case kXR_truncate:
return (char *)"kXR_truncate";
break;
default:
return (char *)"kXR_UNKNOWN";
break;
}
return (char *)"kXR_UNKNOWN";
}
//___________________________________________________________________________
void PutFilehandleInRequest(ClientRequest* str, char *fHandle)
{
// this function inserts a filehandle in a generic request header
// already composed
switch(str->header.requestid) {
case kXR_close:
memcpy( str->close.fhandle, fHandle, sizeof(str->close.fhandle) );
break;
case kXR_read:
memcpy( str->read.fhandle, fHandle, sizeof(str->read.fhandle) );
break;
case kXR_sync:
memcpy( str->sync.fhandle, fHandle, sizeof(str->sync.fhandle) );
break;
case kXR_write:
memcpy( str->write.fhandle, fHandle, sizeof(str->write.fhandle) );
break;
}
}
//___________________________________________________________________________
char *convertRespStatusToChar(kXR_unt16 status)
{
switch( status) {
case kXR_ok:
return (char *)"kXR_ok";
break;
case kXR_oksofar:
return (char *)"kXR_oksofar";
break;
case kXR_attn:
return (char *)"kXR_attn";
break;
case kXR_authmore:
return (char *)"kXR_authmore";
break;
case kXR_error:
return (char *)"kXR_error";
break;
case kXR_redirect:
return (char *)"kXR_redirect";
break;
case kXR_wait:
return (char *)"kXR_wait";
break;
case kXR_waitresp:
return (char *)"kXR_waitresp";
break;
default:
return (char *)"kXR_UNKNOWN";
break;
}
}
//___________________________________________________________________________
void smartPrintClientHeader(ClientRequest* hdr)
{
kXR_int64 tmpl;
fprintf(stderr, "\n\n================= DUMPING CLIENT REQUEST HEADER =================\n");
fprintf(stderr, "%40s0x%.2x 0x%.2x\n", "ClientHeader.streamid = ",
hdr->header.streamid[0],
hdr->header.streamid[1]);
fprintf(stderr, "%40s%s (%d)\n",
"ClientHeader.requestid = ",
convertRequestIdToChar(hdr->header.requestid), hdr->header.requestid);
switch(hdr->header.requestid) {
case kXR_admin:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.admin.reserved = ",
(kXR_int32)sizeof(hdr->admin.reserved));
break;
case kXR_auth:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.auth.reserved = ",
(kXR_int32)sizeof(hdr->auth.reserved));
fprintf(stderr, " ClientHeader.auth.credtype= 0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
hdr->auth.credtype[0],
hdr->auth.credtype[1],
hdr->auth.credtype[2],
hdr->auth.credtype[3]);
break;
case kXR_chmod:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.chmod.reserved = ",
(kXR_int32)sizeof(hdr->chmod.reserved));
fprintf(stderr, " ClientHeader.chmod.mode= 0x%.2x 0x%.2x \n",
*((kXR_char *)&hdr->chmod.mode),
*(((kXR_char *)&hdr->chmod.mode)+1)
);
break;
case kXR_close:
fprintf(stderr, "%40s0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
"ClientHeader.close.fhandle = ",
hdr->close.fhandle[0],
hdr->close.fhandle[1],
hdr->close.fhandle[2],
hdr->close.fhandle[3]);
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.close.reserved = ",
(kXR_int32)sizeof(hdr->close.reserved));
break;
case kXR_dirlist:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.dirlist.reserved = ",
(kXR_int32)sizeof(hdr->dirlist.reserved));
break;
case kXR_locate:
fprintf(stderr, " ClientHeader.locate.options= 0x%.2x 0x%.2x \n",
*((kXR_char *)&hdr->locate.options),
*(((kXR_char *)&hdr->locate.options)+1)
);
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.locate.reserved = ",
(kXR_int32)sizeof(hdr->locate.reserved));
break;
case kXR_login:
fprintf(stderr, "%40s%d \n",
"ClientHeader.login.pid = ",
hdr->login.pid);
fprintf(stderr, "%40s%s\n",
"ClientHeader.login_body.username = ",
hdr->login.username);
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.login.reserved = ",
(kXR_int32)sizeof(hdr->login.reserved));
fprintf(stderr, "%40s%d\n",
"ClientHeader.login.capver = ",
hdr->login.capver[0]);
fprintf(stderr, "%40s%d\n",
"ClientHeader.login.role = ",
hdr->login.role[0]);
break;
case kXR_mkdir:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.mkdir.reserved = ",
(kXR_int32)sizeof(hdr->mkdir.reserved));
fprintf(stderr, "%40s0x%.2x 0x%.2x\n",
"ClientHeader.mkdir.mode = ",
*((kXR_char*)&hdr->mkdir.mode),
*(((kXR_char*)&hdr->mkdir.mode)+1)
);
break;
case kXR_mv:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.mv.reserved = ",
(kXR_int32)sizeof(hdr->mv.reserved));
break;
case kXR_open:
fprintf(stderr, "%40s0x%.2x 0x%.2x\n",
"ClientHeader.open.mode = ",
*((kXR_char*)&hdr->open.mode),
*(((kXR_char*)&hdr->open.mode)+1)
);
fprintf(stderr, "%40s0x%.2x 0x%.2x\n",
"ClientHeader.open.options = ",
*((kXR_char*)&hdr->open.options),
*(((kXR_char*)&hdr->open.options)+1));
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.open.reserved = ",
(kXR_int32)sizeof(hdr->open.reserved));
break;
case kXR_ping:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.ping.reserved = ",
(kXR_int32)sizeof(hdr->ping.reserved));
break;
case kXR_protocol:
fprintf(stderr, "%40s0x%.2x\n",
"ClientHeader.protocol.clientpv = ",
hdr->protocol.clientpv );
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.protocol.reserved = ",
(kXR_int32)sizeof(hdr->protocol.reserved));
break;
case kXR_prepare:
fprintf(stderr, "%40s0x%.2x\n",
"ClientHeader.prepare.options = ",
hdr->prepare.options);
fprintf(stderr, "%40s0x%.2x\n",
"ClientHeader.prepare.prty = ",
hdr->prepare.prty);
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.prepare.reserved = ",
(kXR_int32)sizeof(hdr->prepare.reserved));
break;
case kXR_read:
fprintf(stderr, "%40s0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
"ClientHeader.read.fhandle = ",
hdr->read.fhandle[0],
hdr->read.fhandle[1],
hdr->read.fhandle[2],
hdr->read.fhandle[3]);
memcpy(&tmpl, &hdr->read.offset, sizeof(kXR_int64) );
fprintf(stderr, "%40s%lld\n",
"ClientHeader.read.offset = ",
tmpl);
fprintf(stderr, "%40s%d\n",
"ClientHeader.read.rlen = ",
hdr->read.rlen);
break;
case kXR_readv:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.readv.reserved = ",
(kXR_int32)sizeof(hdr->readv.reserved));
break;
case kXR_rm:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.rm.reserved = ",
(kXR_int32)sizeof(hdr->rm.reserved));
break;
case kXR_rmdir:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.rmdir.reserved = ",
(kXR_int32)sizeof(hdr->rmdir.reserved));
break;
case kXR_set:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.set.reserved = ",
(kXR_int32)sizeof(hdr->set.reserved));
break;
case kXR_stat:
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.stat.reserved = ",
(kXR_int32)sizeof(hdr->stat.reserved));
break;
case kXR_sync:
fprintf(stderr, "%40s0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
"ClientHeader.sync.fhandle = ",
hdr->sync.fhandle[0],
hdr->sync.fhandle[1],
hdr->sync.fhandle[2],
hdr->sync.fhandle[3]);
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.sync.reserved = ",
(kXR_int32)sizeof(hdr->sync.reserved));
break;
case kXR_write:
fprintf(stderr, "%40s0x%.2x 0x%.2x 0x%.2x 0x%.2x \n",
"ClientHeader.write.fhandle = ",
hdr->write.fhandle[0],
hdr->write.fhandle[1],
hdr->write.fhandle[2],
hdr->write.fhandle[3]);
memcpy(&tmpl, &hdr->write.offset, sizeof(kXR_int64) );
fprintf(stderr, "%40s%lld\n",
"ClientHeader.write.offset = ",
tmpl);
fprintf(stderr, "%40s%d\n",
"ClientHeader.write.pathid = ",
hdr->write.pathid);
fprintf(stderr, "%40s0 repeated %d times\n",
"ClientHeader.write.reserved = ",
(kXR_int32)sizeof(hdr->write.reserved));
break;
}
fprintf(stderr, "%40s%d",
"ClientHeader.header.dlen = ",
hdr->header.dlen);
fprintf(stderr, "\n=================== END CLIENT HEADER DUMPING ===================\n\n");
}
//___________________________________________________________________________
void smartPrintServerHeader(struct ServerResponseHeader* hdr)
{
fprintf(stderr, "\n\n======== DUMPING SERVER RESPONSE HEADER ========\n");
fprintf(stderr, "%30s0x%.2x 0x%.2x\n",
"ServerHeader.streamid = ",
hdr->streamid[0],
hdr->streamid[1]);
switch(hdr->status) {
case kXR_ok:
fprintf(stderr, "%30skXR_ok",
"ServerHeader.status = ");
break;
case kXR_attn:
fprintf(stderr, "%30skXR_attn",
"ServerHeader.status = ");
break;
case kXR_authmore:
fprintf(stderr, "%30skXR_authmore",
"ServerHeader.status = ");
break;
case kXR_error:
fprintf(stderr, "%30skXR_error",
"ServerHeader.status = ");
break;
case kXR_oksofar:
fprintf(stderr, "%30skXR_oksofar",
"ServerHeader.status = ");
break;
case kXR_redirect:
fprintf(stderr, "%30skXR_redirect",
"ServerHeader.status = ");
break;
case kXR_wait:
fprintf(stderr, "%30skXR_wait",
"ServerHeader.status = ");
break;
}
fprintf(stderr, " (%d)\n", hdr->status);
fprintf(stderr, "%30s%d",
"ServerHeader.dlen = ", hdr->dlen);
fprintf(stderr, "\n========== END DUMPING SERVER HEADER ===========\n\n");
}