26 #include <arpa/inet.h>
54 const std::string &content =
"" ) :
55 pRedirector( mr ), pUserHandler( userHandler ), pBuffer(
85 response->
Get( info );
88 uint32_t bytesRead = info->
length;
89 uint64_t offset = info->
offset + bytesRead;
90 pContent += std::string( pBuffer, bytesRead );
96 pUserHandler, pContent );
108 delete pRedirector->pFile;
109 pRedirector->pFile = 0;
113 pRedirector->FinalizeInitialization();
123 pRedirector->FinalizeInitialization( *status );
148 std::string pContent;
164 pRedirector( mr ), pUserHandler( userHandler )
197 pRedirector->FinalizeInitialization( *status );
219 pUrl( url ), pFile( new
File(
File::DisableVirtRedirect ) ), pReady(
220 false ), pFileSize( -1 )
249 XRootDStatus MetalinkRedirector::Parse(
const std::string &metalink )
253 std::string glfnRedirector;
254 env->
GetString(
"GlfnRedirector", glfnRedirector );
257 glfnRedirector.empty() ? 0 : glfnRedirector.c_str() );
259 XrdOucFileInfo **fileInfos = parser.ConvertAll( metalink.c_str(), size,
264 const char * etxt = parser.GetStatus( ecode );
266 "Failed to parse the metalink file: %s (error code: %d)", etxt,
269 "Malformed or corrupted metalink file." );
278 InitCksum( fileInfos );
279 InitReplicas( fileInfos );
281 pFileSize = fileInfos[0]->
GetSize();
285 return XRootDStatus();
294 void MetalinkRedirector::FinalizeInitialization(
const XRootDStatus &status )
301 while( !pPendingRedirects.empty() )
303 const Message *msg = pPendingRedirects.front().first;
304 MsgHandler *handler = pPendingRedirects.front().second;
305 pPendingRedirects.pop_front();
306 if( !handler || !msg )
308 HandleRequestImpl( msg, handler );
315 std::shared_ptr<Message> MetalinkRedirector::GetResponse(
const Message *msg )
const
317 if( !pStatus.
IsOK() )
318 return GetErrorMsg( msg,
"Could not load the Metalink file.",
324 if( !GetReplica( *msg, replica ).
IsOK() )
325 return GetErrorMsg( msg,
"Metalink: no more replicas to try.",
kXR_noReplicas );
332 response->
hdr.
dlen = 4 + replica.size();
333 response->
body.redirect.port = -1;
334 memcpy( response->
body.redirect.host, replica.c_str(), replica.size() );
341 std::shared_ptr<Message> MetalinkRedirector::GetErrorMsg(
const Message *msg,
342 const std::string &errMsg,
XErrorCode code )
const
354 response->
hdr.
dlen = 4 + errMsg.size();
355 response->
body.error.errnum = htonl( code );
356 memcpy( response->
body.error.errmsg, errMsg.c_str(), errMsg.size() );
366 XRootDStatus MetalinkRedirector::HandleRequestImpl(
const Message *msg,
367 MsgHandler *handler )
369 auto resp = GetResponse( msg );
371 RedirectJob *job =
new RedirectJob( handler, std::move( resp ) );
372 jobMan->QueueJob( job );
373 return XRootDStatus();
388 pPendingRedirects.push_back(
389 std::make_pair( msg, handler ) );;
393 return HandleRequestImpl( msg, handler );
401 ReplicaList::const_iterator itr = GetReplica( req );
402 return pReplicas.end() - itr;
410 const char *chvalue = 0, *chtype = 0;
411 while( ( chtype = fileInfos[0]->GetDigest( chvalue ) ) )
413 pChecksums[chtype] = chvalue;
420 void MetalinkRedirector::InitReplicas(
XrdOucFileInfo **fileInfos )
424 while( ( url = fileInfos[0]->GetUrl() ) )
426 replica = URL( url );
427 if( !replica.IsValid() || replica.GetURL().size() > 4096 )
429 pReplicas.push_back( replica.GetURL() );
436 XRootDStatus MetalinkRedirector::GetReplica(
const Message &msg,
437 std::string &replica )
const
439 ReplicaList::const_iterator itr = GetReplica( msg );
440 if( itr == pReplicas.end() )
445 env->
GetInt(
"TlsMetalink", tlsmtl );
447 if( tlsmtl && ( url.GetProtocol() ==
"root" || url.GetProtocol() ==
"xroot" ) )
448 url.SetProtocol(
"roots" );
449 replica = url.GetURL();
451 return XRootDStatus();
457 MetalinkRedirector::ReplicaList::const_iterator
458 MetalinkRedirector::GetReplica(
const Message &msg )
const
460 if( pReplicas.empty() )
461 return pReplicas.cend();
464 if( !GetCgiInfo( msg,
"tried", tried ).IsOK() )
465 return pReplicas.cbegin();
467 ReplicaList triedList;
469 std::set<std::string> triedSet( triedList.begin(), triedList.end() );
471 ReplicaList::const_iterator itr = pReplicas.begin();
472 for( ; itr != pReplicas.end(); ++itr )
475 if( !triedSet.count( url.GetHostName() ) )
break;
484 XRootDStatus MetalinkRedirector::GetCgiInfo(
const Message &msg,
485 const std::string &key, std::string &value )
const
489 kXR_int32 dlen = msg.IsMarshalled() ? ntohl( req->
dlen ) : req->dlen;
490 std::string url( msg.GetBuffer( 24 ), dlen );
491 size_t pos = url.find(
'?' );
492 if( pos == std::string::npos )
493 return XRootDStatus(
stError );
494 size_t start = url.find( key, pos );
495 if( start == std::string::npos )
496 return XRootDStatus(
stError );
497 start += key.size() + 1;
498 size_t end = url.find(
'&', start );
499 if( end == std::string::npos )
501 value = url.substr( start, end - start );
502 return XRootDStatus();
union ServerResponse::@0 body
static int mapError(int rc)
void Get(Type &object)
Retrieve the object being held.
static Log * GetLog()
Get default log.
static PostMaster * GetPostMaster()
Get default post master.
static Env * GetEnv()
Get default client environment.
bool GetString(const std::string &key, std::string &value)
bool GetInt(const std::string &key, int &value)
XRootDStatus Read(uint64_t offset, uint32_t size, void *buffer, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
XRootDStatus Open(const std::string &url, OpenFlags::Flags flags, Access::Mode mode, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
void Error(uint64_t topic, const char *format,...)
Report an error.
The message representation used throughout the system.
JobManager * GetJobManager()
Get the job manager object user by the post master.
Handle an async response.
virtual void HandleResponseWithHosts(XRootDStatus *status, AnyObject *response, HostList *hostList)
virtual void HandleResponse(XRootDStatus *status, AnyObject *response)
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
const char * GetTargetName()
const int DefaultCPChunkSize
const uint16_t stError
An error occurred that could potentially be retried.
const uint16_t errNotFound
std::vector< HostInfo > HostList
const uint16_t errDataError
data is corrupted
const uint16_t errInternal
Internal error.
const int DefaultTlsMetalink
const uint64_t UtilityMsg
void DeallocArgs(XRootDStatus *status, AnyObject *response, HostList *hostList)
Describe a data chunk for vector read.
uint32_t length
offset in the file
@ Read
Open only for reading.
bool IsOK() const
We're fine.
uint32_t errNo
Errno, if any.