XRootD
XrdClXRootDTransport.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // This file is part of the XRootD software suite.
6 //
7 // XRootD is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // XRootD is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19 //
20 // In applying this licence, CERN does not waive the privileges and immunities
21 // granted to it by virtue of its status as an Intergovernmental Organization
22 // or submit itself to any jurisdiction.
23 //------------------------------------------------------------------------------
24 
26 #include "XrdCl/XrdClConstants.hh"
27 #include "XrdCl/XrdClLog.hh"
28 #include "XrdCl/XrdClSocket.hh"
29 #include "XrdCl/XrdClMessage.hh"
30 #include "XrdCl/XrdClDefaultEnv.hh"
31 #include "XrdCl/XrdClSIDManager.hh"
32 #include "XrdCl/XrdClUtils.hh"
34 #include "XrdCl/XrdClTls.hh"
35 #include "XrdNet/XrdNetAddr.hh"
36 #include "XrdNet/XrdNetUtils.hh"
37 #include "XrdSys/XrdSysPlatform.hh"
38 #include "XrdOuc/XrdOucErrInfo.hh"
39 #include "XrdOuc/XrdOucUtils.hh"
40 #include "XrdOuc/XrdOucCRC.hh"
42 #include "XrdSys/XrdSysTimer.hh"
43 #include "XrdSys/XrdSysAtomics.hh"
44 #include "XrdSys/XrdSysPlugin.hh"
46 #include "XrdSec/XrdSecProtect.hh"
47 #include "XrdSys/XrdSysE2T.hh"
48 #include "XrdCl/XrdClTls.hh"
49 #include "XrdCl/XrdClSocket.hh"
50 #include "XProtocol/XProtocol.hh"
51 #include "XrdVersion.hh"
52 
53 #include <arpa/inet.h>
54 #include <sys/types.h>
55 #include <unistd.h>
56 #include <dlfcn.h>
57 #include <sstream>
58 #include <iomanip>
59 #include <set>
60 #include <limits>
61 
62 #include <atomic>
63 
65 
66 namespace XrdCl
67 {
69  {
70  PluginUnloadHandler() : unloaded( false ) { }
71 
72  static void UnloadHandler()
73  {
74  UnloadHandler( "root" );
75  UnloadHandler( "xroot" );
76  }
77 
78  static void UnloadHandler( const std::string &trProt )
79  {
81  TransportHandler *trHandler = trManager->GetHandler( trProt );
82  trHandler->WaitBeforeExit();
83  }
84 
85  void Register( const std::string &protocol )
86  {
87  XrdSysRWLockHelper scope( lock, false ); // obtain write lock
88  std::pair< std::set<std::string>::iterator, bool > ret = protocols.insert( protocol );
89  // if that's the first time we are using the protocol, the sec lib
90  // was just loaded so now's the time to register the atexit handler
91  if( ret.second )
92  {
93  atexit( UnloadHandler );
94  }
95  }
96 
98  bool unloaded;
99  std::set<std::string> protocols;
100  };
101 
102  //----------------------------------------------------------------------------
104  //----------------------------------------------------------------------------
106  {
107  //--------------------------------------------------------------------------
108  // Define the stream status for the link negotiation purposes
109  //--------------------------------------------------------------------------
111  {
120  Connected
121  };
122 
123  //--------------------------------------------------------------------------
124  // Constructor
125  //--------------------------------------------------------------------------
127  {
128  }
129 
131  uint8_t pathId;
132  };
133 
134  //----------------------------------------------------------------------------
136  //----------------------------------------------------------------------------
138  {
139  StreamSelector( uint16_t size )
140  {
141  //----------------------------------------------------------------------
142  // Subtract one because we shouldn't take into account the control
143  // stream.
144  //----------------------------------------------------------------------
145  strmqueues.resize( size - 1, 0 );
146  }
147 
148  //------------------------------------------------------------------------
149  // @param size : number of streams
150  //------------------------------------------------------------------------
151  void AdjustQueues( uint16_t size )
152  {
153  strmqueues.resize( size - 1, 0);
154  }
155 
156  //------------------------------------------------------------------------
157  // @param connected : bitarray stating if given sub-stream is connected
158  //
159  // @return : substream number
160  //------------------------------------------------------------------------
161  uint16_t Select( const std::vector<bool> &connected )
162  {
163  uint16_t ret = 0;
164  size_t minval = std::numeric_limits<size_t>::max();
165 
166  for( uint16_t i = 0; i < connected.size() && i < strmqueues.size(); ++i )
167  {
168  if( !connected[i] ) continue;
169 
170  if( strmqueues[i] < minval )
171  {
172  ret = i;
173  minval = strmqueues[i];
174  }
175  }
176 
177  ++strmqueues[ret];
178  return ret + 1;
179  }
180 
181  //--------------------------------------------------------------------------
182  // Update queue for given substream
183  //--------------------------------------------------------------------------
184  void MsgReceived( uint16_t substrm )
185  {
186  if( substrm > 0 )
187  --strmqueues[substrm - 1];
188  }
189 
190  private:
191 
192  std::vector<size_t> strmqueues;
193  };
194 
196  {
197  BindPrefSelector( std::vector<std::string> && bindprefs ) :
198  bindprefs( std::move( bindprefs ) ), next( 0 )
199  {
200  }
201 
202  inline const std::string& Get()
203  {
204  std::string &ret = bindprefs[next];
205  ++next;
206  if( next >= bindprefs.size() )
207  next = 0;
208  return ret;
209  }
210 
211  private:
212  std::vector<std::string> bindprefs;
213  size_t next;
214  };
215 
216  //----------------------------------------------------------------------------
218  //----------------------------------------------------------------------------
220  {
221  //--------------------------------------------------------------------------
222  // Constructor
223  //--------------------------------------------------------------------------
224  XRootDChannelInfo( const URL &url ):
225  serverFlags(0),
226  protocolVersion(0),
227  firstLogIn(true),
228  authBuffer(0),
229  authProtocol(0),
230  authParams(0),
231  authEnv(0),
232  finstcnt(0),
233  openFiles(0),
234  waitBarrier(0),
235  protection(0),
236  protRespBody(0),
237  protRespSize(0),
238  encrypted(false),
239  istpc(false)
240  {
242  memset( sessionId, 0, 16 );
243  memset( oldSessionId, 0, 16 );
244  }
245 
246  //--------------------------------------------------------------------------
247  // Destructor
248  //--------------------------------------------------------------------------
250  {
251  delete [] authBuffer;
252  }
253 
254  typedef std::vector<XRootDStreamInfo> StreamInfoVector;
255 
256  //--------------------------------------------------------------------------
257  // Data
258  //--------------------------------------------------------------------------
259  uint32_t serverFlags;
260  uint32_t protocolVersion;
261  uint8_t sessionId[16];
262  uint8_t oldSessionId[16];
264  std::shared_ptr<SIDManager> sidManager;
265  char *authBuffer;
270  std::string streamName;
271  std::string authProtocolName;
272  std::set<uint16_t> sentOpens;
273  std::set<uint16_t> sentCloses;
274  std::atomic<uint32_t> finstcnt; // file instance count
275  uint32_t openFiles;
276  time_t waitBarrier;
279  unsigned int protRespSize;
280  std::unique_ptr<StreamSelector> strmSelector;
281  bool encrypted;
282  bool istpc;
283  std::unique_ptr<BindPrefSelector> bindSelector;
284  std::string logintoken;
286  };
287 
288  //----------------------------------------------------------------------------
289  // Constructor
290  //----------------------------------------------------------------------------
292  pSecUnloadHandler( new PluginUnloadHandler() )
293  {
294  }
295 
296  //----------------------------------------------------------------------------
297  // Destructor
298  //----------------------------------------------------------------------------
300  {
301  delete pSecUnloadHandler; pSecUnloadHandler = 0;
302  }
303 
304  //----------------------------------------------------------------------------
305  // Read message header from socket
306  //----------------------------------------------------------------------------
308  {
309  //--------------------------------------------------------------------------
310  // A new message - allocate the space needed for the header
311  //--------------------------------------------------------------------------
312  if( message.GetCursor() == 0 && message.GetSize() < 8 )
313  message.Allocate( 8 );
314 
315  //--------------------------------------------------------------------------
316  // Read the message header
317  //--------------------------------------------------------------------------
318  if( message.GetCursor() < 8 )
319  {
320  size_t leftToBeRead = 8 - message.GetCursor();
321  while( leftToBeRead )
322  {
323  int bytesRead = 0;
324  XRootDStatus status = socket->Read( message.GetBufferAtCursor(),
325  leftToBeRead, bytesRead );
326  if( !status.IsOK() || status.code == suRetry )
327  return status;
328 
329  leftToBeRead -= bytesRead;
330  message.AdvanceCursor( bytesRead );
331  }
332  UnMarshallHeader( message );
333 
334  uint32_t bodySize = *(uint32_t*)(message.GetBuffer(4));
335  Log *log = DefaultEnv::GetLog();
336  log->Dump( XRootDTransportMsg, "[msg: %p] Expecting %d bytes of message "
337  "body", &message, bodySize );
338 
339  return XRootDStatus( stOK, suDone );
340  }
341  return XRootDStatus( stError, errInternal );
342  }
343 
344  //----------------------------------------------------------------------------
345  // Read message body from socket
346  //----------------------------------------------------------------------------
348  {
349  //--------------------------------------------------------------------------
350  // Retrieve the body
351  //--------------------------------------------------------------------------
352  size_t leftToBeRead = 0;
353  uint32_t bodySize = 0;
355  bodySize = rsphdr->dlen;
356 
357  if( message.GetSize() < bodySize + 8 )
358  message.ReAllocate( bodySize + 8 );
359 
360  leftToBeRead = bodySize-(message.GetCursor()-8);
361  while( leftToBeRead )
362  {
363  int bytesRead = 0;
364  XRootDStatus status = socket->Read( message.GetBufferAtCursor(), leftToBeRead, bytesRead );
365 
366  if( !status.IsOK() || status.code == suRetry )
367  return status;
368 
369  leftToBeRead -= bytesRead;
370  message.AdvanceCursor( bytesRead );
371  }
372 
373  return XRootDStatus( stOK, suDone );
374  }
375 
376  //----------------------------------------------------------------------------
377  // Read more of the message body from socket
378  //----------------------------------------------------------------------------
380  {
382  if( rsphdr->status != kXR_status )
383  return XRootDStatus( stError, errInvalidOp );
384 
385  //--------------------------------------------------------------------------
386  // In case of non kXR_status responses we read all the response, including
387  // data. For kXR_status responses we first read only the remainder of the
388  // header. The header must then be unmarshalled, and then a second call to
389  // GetMore (repeated for suRetry as needed) will read the data.
390  //--------------------------------------------------------------------------
391 
392  uint32_t bodySize = rsphdr->dlen;
393  if( bodySize+8 < sizeof( ServerResponseStatus ) )
395  "kXR_status: invalid message size." );
396 
398  bodySize += rspst->bdy.dlen;
399 
400  if( message.GetSize() < bodySize + 8 )
401  message.ReAllocate( bodySize + 8 );
402 
403  size_t leftToBeRead = bodySize-(message.GetCursor()-8);
404  while( leftToBeRead )
405  {
406  int bytesRead = 0;
407  XRootDStatus status = socket->Read( message.GetBufferAtCursor(), leftToBeRead, bytesRead );
408 
409  if( !status.IsOK() || status.code == suRetry )
410  return status;
411 
412  leftToBeRead -= bytesRead;
413  message.AdvanceCursor( bytesRead );
414  }
415 
416  // Unmarchal to message body
417  Log *log = DefaultEnv::GetLog();
419  if( !st.IsOK() && st.code == errDataError )
420  {
421  log->Error( XRootDTransportMsg, "[msg: %p] %s", &message,
422  st.GetErrorMessage().c_str() );
423  return st;
424  }
425 
426  if( !st.IsOK() )
427  {
428  log->Error( XRootDTransportMsg, "[msg: %p] Failed to unmarshall status body.",
429  &message );
430  return st;
431  }
432 
433  return XRootDStatus( stOK, suDone );
434  }
435 
436  //----------------------------------------------------------------------------
437  // Initialize channel
438  //----------------------------------------------------------------------------
440  AnyObject &channelData )
441  {
442  XRootDChannelInfo *info = new XRootDChannelInfo( url );
443  XrdSysMutexHelper scopedLock( info->mutex );
444  channelData.Set( info );
445 
446  Env *env = DefaultEnv::GetEnv();
447  int streams = DefaultSubStreamsPerChannel;
448  env->GetInt( "SubStreamsPerChannel", streams );
449  if( streams < 1 ) streams = 1;
450  info->stream.resize( streams );
451  info->strmSelector.reset( new StreamSelector( streams ) );
452  info->encrypted = url.IsSecure();
453  info->istpc = url.IsTPC();
454  info->logintoken = url.GetLoginToken();
455  }
456 
457  //----------------------------------------------------------------------------
458  // Finalize channel
459  //----------------------------------------------------------------------------
461  {
462  }
463 
464  //----------------------------------------------------------------------------
465  // HandShake
466  //----------------------------------------------------------------------------
468  AnyObject &channelData )
469  {
470  XRootDChannelInfo *info = 0;
471  channelData.Get( info );
472  XrdSysMutexHelper scopedLock( info->mutex );
473 
474  if( info->stream.size() <= handShakeData->subStreamId )
475  {
476  Log *log = DefaultEnv::GetLog();
478  "[%s] Internal error: not enough substreams",
479  handShakeData->streamName.c_str() );
480  return XRootDStatus( stFatal, errInternal );
481  }
482 
483  if( handShakeData->subStreamId == 0 )
484  {
485  info->streamName = handShakeData->streamName;
486  return HandShakeMain( handShakeData, channelData );
487  }
488  return HandShakeParallel( handShakeData, channelData );
489  }
490 
491  //----------------------------------------------------------------------------
492  // Hand shake the main stream
493  //----------------------------------------------------------------------------
494  XRootDStatus XRootDTransport::HandShakeMain( HandShakeData *handShakeData,
495  AnyObject &channelData )
496  {
497  XRootDChannelInfo *info = 0;
498  channelData.Get( info );
499  XRootDStreamInfo &sInfo = info->stream[handShakeData->subStreamId];
500 
501  //--------------------------------------------------------------------------
502  // First step - we need to create and initial handshake and send it out
503  //--------------------------------------------------------------------------
504  if( sInfo.status == XRootDStreamInfo::Disconnected ||
506  {
507  handShakeData->out = GenerateInitialHSProtocol( handShakeData, info,
510  return XRootDStatus( stOK, suContinue );
511  }
512 
513  //--------------------------------------------------------------------------
514  // Second step - we got the reply message to the initial handshake
515  //--------------------------------------------------------------------------
517  {
518  XRootDStatus st = ProcessServerHS( handShakeData, info );
519  if( st.IsOK() )
521  else
523  return st;
524  }
525 
526  //--------------------------------------------------------------------------
527  // Third step - we got the response to the protocol request, we need
528  // to process it and send out a login request
529  //--------------------------------------------------------------------------
531  {
532  XRootDStatus st = ProcessProtocolResp( handShakeData, info );
533 
534  if( !st.IsOK() )
535  {
537  return st;
538  }
539 
540  if( st.code == suRetry )
541  {
542  handShakeData->out = GenerateProtocol( handShakeData, info,
545  return XRootDStatus( stOK, suRetry );
546  }
547 
548  handShakeData->out = GenerateLogIn( handShakeData, info );
550  return XRootDStatus( stOK, suContinue );
551  }
552 
553  //--------------------------------------------------------------------------
554  // Fourth step - handle the log in response and proceed with the
555  // authentication if required by the server
556  //--------------------------------------------------------------------------
557  if( sInfo.status == XRootDStreamInfo::LoginSent )
558  {
559  XRootDStatus st = ProcessLogInResp( handShakeData, info );
560 
561  if( !st.IsOK() )
562  {
564  return st;
565  }
566 
567  if( st.IsOK() && st.code == suDone )
568  {
569  //----------------------------------------------------------------------
570  // If it's not our first log in we need to end the previous session
571  // to make sure that the server noticed our disconnection and closed
572  // all the writable handles that we owned
573  //----------------------------------------------------------------------
574  if( !info->firstLogIn )
575  {
576  handShakeData->out = GenerateEndSession( handShakeData, info );
578  return XRootDStatus( stOK, suContinue );
579  }
580 
582  info->firstLogIn = false;
583  return st;
584  }
585 
586  st = DoAuthentication( handShakeData, info );
587  if( !st.IsOK() )
589  else
591  return st;
592  }
593 
594  //--------------------------------------------------------------------------
595  // Fifth step and later - proceed with the authentication
596  //--------------------------------------------------------------------------
597  if( sInfo.status == XRootDStreamInfo::AuthSent )
598  {
599  XRootDStatus st = DoAuthentication( handShakeData, info );
600 
601  if( !st.IsOK() )
602  {
604  return st;
605  }
606 
607  if( st.IsOK() && st.code == suDone )
608  {
609  //----------------------------------------------------------------------
610  // If it's not our first log in we need to end the previous session
611  //----------------------------------------------------------------------
612  if( !info->firstLogIn )
613  {
614  handShakeData->out = GenerateEndSession( handShakeData, info );
616  return XRootDStatus( stOK, suContinue );
617  }
618 
620  info->firstLogIn = false;
621  return st;
622  }
623 
624  return st;
625  }
626 
627  //--------------------------------------------------------------------------
628  // The last step - kXR_endsess returned
629  //--------------------------------------------------------------------------
631  {
632  XRootDStatus st = ProcessEndSessionResp( handShakeData, info );
633 
634  if( st.IsOK() && st.code == suDone )
635  {
637  }
638  else if( !st.IsOK() )
639  {
641  }
642 
643  return st;
644  }
645 
646  return XRootDStatus( stOK, suDone );
647  }
648 
649  //----------------------------------------------------------------------------
650  // Hand shake parallel stream
651  //----------------------------------------------------------------------------
652  XRootDStatus XRootDTransport::HandShakeParallel( HandShakeData *handShakeData,
653  AnyObject &channelData )
654  {
655  XRootDChannelInfo *info = 0;
656  channelData.Get( info );
657 
658  XRootDStreamInfo &sInfo = info->stream[handShakeData->subStreamId];
659 
660  //--------------------------------------------------------------------------
661  // First step - we need to create and initial handshake and send it out
662  //--------------------------------------------------------------------------
663  if( sInfo.status == XRootDStreamInfo::Disconnected ||
664  sInfo.status == XRootDStreamInfo::Broken )
665  {
666  handShakeData->out = GenerateInitialHSProtocol( handShakeData, info,
668  sInfo.status = XRootDStreamInfo::HandShakeSent;
669  return XRootDStatus( stOK, suContinue );
670  }
671 
672  //--------------------------------------------------------------------------
673  // Second step - we got the reply message to the initial handshake,
674  // if successful we need to send bind
675  //--------------------------------------------------------------------------
676  if( sInfo.status == XRootDStreamInfo::HandShakeSent )
677  {
678  XRootDStatus st = ProcessServerHS( handShakeData, info );
679  if( st.IsOK() )
681  else
682  sInfo.status = XRootDStreamInfo::Broken;
683  return st;
684  }
685 
686  //--------------------------------------------------------------------------
687  // Second step bis - we got the response to the protocol request, we need
688  // to process it and send out a bind request
689  //--------------------------------------------------------------------------
690  if( sInfo.status == XRootDStreamInfo::HandShakeReceived )
691  {
692  XRootDStatus st = ProcessProtocolResp( handShakeData, info );
693 
694  if( !st.IsOK() )
695  {
696  sInfo.status = XRootDStreamInfo::Broken;
697  return st;
698  }
699 
700  handShakeData->out = GenerateBind( handShakeData, info );
701  sInfo.status = XRootDStreamInfo::BindSent;
702  return XRootDStatus( stOK, suContinue );
703  }
704 
705  //--------------------------------------------------------------------------
706  // Third step - we got the response to the kXR_bind
707  //--------------------------------------------------------------------------
708  if( sInfo.status == XRootDStreamInfo::BindSent )
709  {
710  XRootDStatus st = ProcessBindResp( handShakeData, info );
711 
712  if( !st.IsOK() )
713  {
714  sInfo.status = XRootDStreamInfo::Broken;
715  return st;
716  }
717  sInfo.status = XRootDStreamInfo::Connected;
718  return XRootDStatus();
719  }
720  return XRootDStatus();
721  }
722 
723  //------------------------------------------------------------------------
724  // @return true if handshake has been done and stream is connected,
725  // false otherwise
726  //------------------------------------------------------------------------
728  AnyObject &channelData )
729  {
730  XRootDChannelInfo *info = 0;
731  channelData.Get( info );
732  XRootDStreamInfo &sInfo = info->stream[handShakeData->subStreamId];
733  return ( sInfo.status == XRootDStreamInfo::Connected );
734  }
735 
736  //----------------------------------------------------------------------------
737  // Check if the stream should be disconnected
738  //----------------------------------------------------------------------------
739  bool XRootDTransport::IsStreamTTLElapsed( time_t inactiveTime,
740  AnyObject &channelData )
741  {
742  XRootDChannelInfo *info = 0;
743  channelData.Get( info );
744  Env *env = DefaultEnv::GetEnv();
745  Log *log = DefaultEnv::GetLog();
746 
747  //--------------------------------------------------------------------------
748  // Check the TTL settings for the current server
749  //--------------------------------------------------------------------------
750  int ttl;
751  if( info->serverFlags & kXR_isServer )
752  {
753  ttl = DefaultDataServerTTL;
754  env->GetInt( "DataServerTTL", ttl );
755  }
756  else
757  {
759  env->GetInt( "LoadBalancerTTL", ttl );
760  }
761 
762  //--------------------------------------------------------------------------
763  // See whether we can give a go-ahead for the disconnection
764  //--------------------------------------------------------------------------
765  XrdSysMutexHelper scopedLock( info->mutex );
766  uint16_t allocatedSIDs = info->sidManager->GetNumberOfAllocatedSIDs();
767  log->Dump( XRootDTransportMsg, "[%s] Stream inactive since %lld seconds, "
768  "TTL: %d, allocated SIDs: %d, open files: %d, bound file objects: %d",
769  info->streamName.c_str(), (long long) inactiveTime, ttl, allocatedSIDs,
770  info->openFiles, info->finstcnt.load( std::memory_order_relaxed ) );
771 
772  if( info->openFiles != 0 && info->finstcnt.load( std::memory_order_relaxed ) != 0 )
773  return false;
774 
775  if( !allocatedSIDs && inactiveTime > ttl )
776  return true;
777 
778  return false;
779  }
780 
781  //----------------------------------------------------------------------------
782  // Check the stream is broken - ie. TCP connection got broken and
783  // went undetected by the TCP stack
784  //----------------------------------------------------------------------------
786  AnyObject &channelData )
787  {
788  XRootDChannelInfo *info = 0;
789  channelData.Get( info );
790  Env *env = DefaultEnv::GetEnv();
791  Log *log = DefaultEnv::GetLog();
792 
793  int streamTimeout = DefaultStreamTimeout;
794  env->GetInt( "StreamTimeout", streamTimeout );
795 
796  XrdSysMutexHelper scopedLock( info->mutex );
797 
798  const time_t now = time(0);
799  const bool anySID =
800  info->sidManager->IsAnySIDOldAs( now - streamTimeout );
801 
802  log->Dump( XRootDTransportMsg, "[%s] Stream inactive since %lld seconds, "
803  "stream timeout: %d, any SID: %d, wait barrier: %s",
804  info->streamName.c_str(), (long long) inactiveTime, streamTimeout,
805  anySID, Utils::TimeToString(info->waitBarrier).c_str() );
806 
807  if( inactiveTime < streamTimeout )
808  return Status();
809 
810  if( now < info->waitBarrier )
811  return Status();
812 
813  if( !anySID )
814  return Status();
815 
816  return Status( stError, errSocketTimeout );
817  }
818 
819  //----------------------------------------------------------------------------
820  // Multiplex
821  //----------------------------------------------------------------------------
823  {
824  return PathID( 0, 0 );
825  }
826 
827  //----------------------------------------------------------------------------
828  // Multiplex
829  //----------------------------------------------------------------------------
831  AnyObject &channelData,
832  PathID *hint )
833  {
834  XRootDChannelInfo *info = 0;
835  channelData.Get( info );
836  XrdSysMutexHelper scopedLock( info->mutex );
837 
838  //--------------------------------------------------------------------------
839  // If we're not connected to a data server or we don't know that yet
840  // we stream through 0
841  //--------------------------------------------------------------------------
842  if( !(info->serverFlags & kXR_isServer) || info->stream.size() == 0 )
843  return PathID( 0, 0 );
844 
845  //--------------------------------------------------------------------------
846  // Select the streams
847  //--------------------------------------------------------------------------
848  Log *log = DefaultEnv::GetLog();
849  uint16_t upStream = 0;
850  uint16_t downStream = 0;
851 
852  if( hint )
853  {
854  upStream = hint->up;
855  downStream = hint->down;
856  }
857  else
858  {
859  upStream = 0;
860  std::vector<bool> connected;
861  connected.reserve( info->stream.size() - 1 );
862  size_t nbConnected = 0;
863  for( size_t i = 1; i < info->stream.size(); ++i )
864  if( info->stream[i].status == XRootDStreamInfo::Connected )
865  {
866  connected.push_back( true );
867  ++nbConnected;
868  }
869  else
870  connected.push_back( false );
871 
872  if( nbConnected == 0 )
873  downStream = 0;
874  else
875  downStream = info->strmSelector->Select( connected );
876  }
877 
878  if( upStream >= info->stream.size() )
879  {
881  "[%s] Up link stream %d does not exist, using 0",
882  info->streamName.c_str(), upStream );
883  upStream = 0;
884  }
885 
886  if( downStream >= info->stream.size() )
887  {
889  "[%s] Down link stream %d does not exist, using 0",
890  info->streamName.c_str(), downStream );
891  downStream = 0;
892  }
893 
894  //--------------------------------------------------------------------------
895  // Modify the message
896  //--------------------------------------------------------------------------
897  UnMarshallRequest( msg );
899  switch( hdr->requestid )
900  {
901  //------------------------------------------------------------------------
902  // Read - we update the path id to tell the server where we want to
903  // get the response, but we still send the request through stream 0
904  // We need to allocate space for read_args if we don't have it
905  // included yet
906  //------------------------------------------------------------------------
907  case kXR_read:
908  {
909  if( msg->GetSize() < sizeof(ClientReadRequest) + 8 )
910  {
911  msg->ReAllocate( sizeof(ClientReadRequest) + 8 );
912  void *newBuf = msg->GetBuffer(sizeof(ClientReadRequest));
913  memset( newBuf, 0, 8 );
915  req->dlen += 8;
916  }
917  read_args *args = (read_args*)msg->GetBuffer(sizeof(ClientReadRequest));
918  args->pathid = info->stream[downStream].pathId;
919  break;
920  }
921 
922 
923  //------------------------------------------------------------------------
924  // PgRead - we update the path id to tell the server where we want to
925  // get the response, but we still send the request through stream 0
926  // We need to allocate space for ClientPgReadReqArgs if we don't have it
927  // included yet
928  //------------------------------------------------------------------------
929  case kXR_pgread:
930  {
931  if( msg->GetSize() < sizeof( ClientPgReadRequest ) + sizeof( ClientPgReadReqArgs ) )
932  {
933  msg->ReAllocate( sizeof( ClientPgReadRequest ) + sizeof( ClientPgReadReqArgs ) );
934  void *newBuf = msg->GetBuffer( sizeof( ClientPgReadRequest ) );
935  memset( newBuf, 0, sizeof( ClientPgReadReqArgs ) );
937  req->dlen += sizeof( ClientPgReadReqArgs );
938  }
939  ClientPgReadReqArgs *args = reinterpret_cast<ClientPgReadReqArgs*>(
940  msg->GetBuffer( sizeof( ClientPgReadRequest ) ) );
941  args->pathid = info->stream[downStream].pathId;
942  break;
943  }
944 
945  //------------------------------------------------------------------------
946  // ReadV - the situation is identical to read but we don't need any
947  // additional structures to specify the return path
948  //------------------------------------------------------------------------
949  case kXR_readv:
950  {
952  req->pathid = info->stream[downStream].pathId;
953  break;
954  }
955 
956  //------------------------------------------------------------------------
957  // Write - multiplexing writes doesn't work properly in the server
958  //------------------------------------------------------------------------
959  case kXR_write:
960  {
961 // ClientWriteRequest *req = (ClientWriteRequest*)msg->GetBuffer();
962 // req->pathid = info->stream[downStream].pathId;
963  break;
964  }
965 
966  //------------------------------------------------------------------------
967  // WriteV - multiplexing writes doesn't work properly in the server
968  //------------------------------------------------------------------------
969  case kXR_writev:
970  {
971 // ClientWriteVRequest *req = (ClientWriteVRequest*)msg->GetBuffer();
972 // req->pathid = info->stream[downStream].pathId;
973  break;
974  }
975 
976  //------------------------------------------------------------------------
977  // PgWrite - multiplexing writes doesn't work properly in the server
978  //------------------------------------------------------------------------
979  case kXR_pgwrite:
980  {
981 // ClientWriteVRequest *req = (ClientWriteVRequest*)msg->GetBuffer();
982 // req->pathid = info->stream[downStream].pathId;
983  break;
984  }
985  };
986  MarshallRequest( msg );
987  return PathID( upStream, downStream );
988  }
989 
990  //----------------------------------------------------------------------------
991  // Return a number of substreams per stream that should be created
992  // This depends on the environment and whether we are connected to
993  // a data server or not
994  //----------------------------------------------------------------------------
996  {
997  XRootDChannelInfo *info = 0;
998  channelData.Get( info );
999  XrdSysMutexHelper scopedLock( info->mutex );
1000 
1001  //--------------------------------------------------------------------------
1002  // If the connection has been opened in order to orchestrate a TPC or
1003  // the remote server is a Manager or Metamanager we will need only one
1004  // (control) stream.
1005  //--------------------------------------------------------------------------
1006  if( info->istpc || !(info->serverFlags & kXR_isServer ) ) return 1;
1007 
1008  //--------------------------------------------------------------------------
1009  // Number of streams requested by user
1010  //--------------------------------------------------------------------------
1011  uint16_t ret = info->stream.size();
1012 
1014  int nodata = DefaultTlsNoData;
1015  env->GetInt( "TlsNoData", nodata );
1016 
1017  // Does the server require the stream 0 to be encrypted?
1018  bool srvTlsStrm0 = ( info->serverFlags & kXR_gotoTLS ) ||
1019  ( info->serverFlags & kXR_tlsLogin ) ||
1020  ( info->serverFlags & kXR_tlsSess );
1021  // Does the server NOT require the data streams to be encrypted?
1022  bool srvNoTlsData = !( info->serverFlags & kXR_tlsData );
1023  // Does the user require the stream 0 to be encrypted?
1024  bool usrTlsStrm0 = info->encrypted;
1025  // Does the user NOT require the data streams to be encrypted?
1026  bool usrNoTlsData = !info->encrypted || ( info->encrypted && nodata );
1027 
1028  if( ( usrTlsStrm0 && usrNoTlsData && srvNoTlsData ) ||
1029  ( srvTlsStrm0 && srvNoTlsData && usrNoTlsData ) )
1030  {
1031  //------------------------------------------------------------------------
1032  // The server or user asked us to encrypt stream 0, but to send the data
1033  // (read/write) using a plain TCP connection
1034  //------------------------------------------------------------------------
1035  if( ret == 1 ) ++ret;
1036  }
1037 
1038  if( ret > info->stream.size() )
1039  {
1040  info->stream.resize( ret );
1041  info->strmSelector->AdjustQueues( ret );
1042  }
1043 
1044  return ret;
1045  }
1046 
1047  //----------------------------------------------------------------------------
1048  // Marshall
1049  //----------------------------------------------------------------------------
1051  {
1052  ClientRequest *req = (ClientRequest*)msg;
1053  switch( req->header.requestid )
1054  {
1055  //------------------------------------------------------------------------
1056  // kXR_protocol
1057  //------------------------------------------------------------------------
1058  case kXR_protocol:
1059  req->protocol.clientpv = htonl( req->protocol.clientpv );
1060  break;
1061 
1062  //------------------------------------------------------------------------
1063  // kXR_login
1064  //------------------------------------------------------------------------
1065  case kXR_login:
1066  req->login.pid = htonl( req->login.pid );
1067  break;
1068 
1069  //------------------------------------------------------------------------
1070  // kXR_locate
1071  //------------------------------------------------------------------------
1072  case kXR_locate:
1073  req->locate.options = htons( req->locate.options );
1074  break;
1075 
1076  //------------------------------------------------------------------------
1077  // kXR_query
1078  //------------------------------------------------------------------------
1079  case kXR_query:
1080  req->query.infotype = htons( req->query.infotype );
1081  break;
1082 
1083  //------------------------------------------------------------------------
1084  // kXR_truncate
1085  //------------------------------------------------------------------------
1086  case kXR_truncate:
1087  req->truncate.offset = htonll( req->truncate.offset );
1088  break;
1089 
1090  //------------------------------------------------------------------------
1091  // kXR_mkdir
1092  //------------------------------------------------------------------------
1093  case kXR_mkdir:
1094  req->mkdir.mode = htons( req->mkdir.mode );
1095  break;
1096 
1097  //------------------------------------------------------------------------
1098  // kXR_chmod
1099  //------------------------------------------------------------------------
1100  case kXR_chmod:
1101  req->chmod.mode = htons( req->chmod.mode );
1102  break;
1103 
1104  //------------------------------------------------------------------------
1105  // kXR_open
1106  //------------------------------------------------------------------------
1107  case kXR_open:
1108  req->open.mode = htons( req->open.mode );
1109  req->open.options = htons( req->open.options );
1110  break;
1111 
1112  //------------------------------------------------------------------------
1113  // kXR_read
1114  //------------------------------------------------------------------------
1115  case kXR_read:
1116  req->read.offset = htonll( req->read.offset );
1117  req->read.rlen = htonl( req->read.rlen );
1118  break;
1119 
1120  //------------------------------------------------------------------------
1121  // kXR_write
1122  //------------------------------------------------------------------------
1123  case kXR_write:
1124  req->write.offset = htonll( req->write.offset );
1125  break;
1126 
1127  //------------------------------------------------------------------------
1128  // kXR_mv
1129  //------------------------------------------------------------------------
1130  case kXR_mv:
1131  req->mv.arg1len = htons( req->mv.arg1len );
1132  break;
1133 
1134  //------------------------------------------------------------------------
1135  // kXR_readv
1136  //------------------------------------------------------------------------
1137  case kXR_readv:
1138  {
1139  uint16_t numChunks = (req->readv.dlen)/16;
1140  readahead_list *dataChunk = (readahead_list*)( msg + 24 );
1141  for( size_t i = 0; i < numChunks; ++i )
1142  {
1143  dataChunk[i].rlen = htonl( dataChunk[i].rlen );
1144  dataChunk[i].offset = htonll( dataChunk[i].offset );
1145  }
1146  break;
1147  }
1148 
1149  //------------------------------------------------------------------------
1150  // kXR_writev
1151  //------------------------------------------------------------------------
1152  case kXR_writev:
1153  {
1154  uint16_t numChunks = (req->writev.dlen)/16;
1155  XrdProto::write_list *wrtList =
1156  reinterpret_cast<XrdProto::write_list*>( msg + 24 );
1157  for( size_t i = 0; i < numChunks; ++i )
1158  {
1159  wrtList[i].wlen = htonl( wrtList[i].wlen );
1160  wrtList[i].offset = htonll( wrtList[i].offset );
1161  }
1162 
1163  break;
1164  }
1165 
1166  case kXR_pgread:
1167  {
1168  req->pgread.offset = htonll( req->pgread.offset );
1169  req->pgread.rlen = htonl( req->pgread.rlen );
1170  break;
1171  }
1172 
1173  case kXR_pgwrite:
1174  {
1175  req->pgwrite.offset = htonll( req->pgwrite.offset );
1176  break;
1177  }
1178 
1179  //------------------------------------------------------------------------
1180  // kXR_prepare
1181  //------------------------------------------------------------------------
1182  case kXR_prepare:
1183  {
1184  req->prepare.optionX = htons( req->prepare.optionX );
1185  req->prepare.port = htons( req->prepare.port );
1186  break;
1187  }
1188 
1189  case kXR_chkpoint:
1190  {
1191  if( req->chkpoint.opcode == kXR_ckpXeq )
1192  MarshallRequest( msg + 24 );
1193  break;
1194  }
1195  };
1196 
1197  req->header.requestid = htons( req->header.requestid );
1198  req->header.dlen = htonl( req->header.dlen );
1199  return XRootDStatus();
1200  }
1201 
1202  //----------------------------------------------------------------------------
1203  // Unmarshall the request - sometimes the requests need to be rewritten,
1204  // so we need to unmarshall them
1205  //----------------------------------------------------------------------------
1207  {
1208  if( !msg->IsMarshalled() ) return XRootDStatus( stOK, suAlreadyDone );
1209  // We rely on the marshaling process to be symmetric!
1210  // First we unmarshall the request ID and the length because
1211  // MarshallRequest() relies on these, and then we need to unmarshall these
1212  // two again, because they get marshalled in MarshallRequest().
1213  // All this is pretty damn ugly and should be rewritten.
1214  ClientRequest *req = (ClientRequest*)msg->GetBuffer();
1215  req->header.requestid = htons( req->header.requestid );
1216  req->header.dlen = htonl( req->header.dlen );
1217  XRootDStatus st = MarshallRequest( msg );
1218  req->header.requestid = htons( req->header.requestid );
1219  req->header.dlen = htonl( req->header.dlen );
1220  msg->SetIsMarshalled( false );
1221  return st;
1222  }
1223 
1224  //----------------------------------------------------------------------------
1225  // Unmarshall the body of the incoming message
1226  //----------------------------------------------------------------------------
1228  {
1229  ServerResponse *m = (ServerResponse *)msg->GetBuffer();
1230 
1231  //--------------------------------------------------------------------------
1232  // kXR_ok
1233  //--------------------------------------------------------------------------
1234  if( m->hdr.status == kXR_ok )
1235  {
1236  switch( reqType )
1237  {
1238  //----------------------------------------------------------------------
1239  // kXR_protocol
1240  //----------------------------------------------------------------------
1241  case kXR_protocol:
1242  if( m->hdr.dlen < 8 )
1243  return XRootDStatus( stError, errInvalidMessage, 0, "kXR_protocol: body too short." );
1244  m->body.protocol.pval = ntohl( m->body.protocol.pval );
1245  m->body.protocol.flags = ntohl( m->body.protocol.flags );
1246  break;
1247  }
1248  }
1249  //--------------------------------------------------------------------------
1250  // kXR_error
1251  //--------------------------------------------------------------------------
1252  else if( m->hdr.status == kXR_error )
1253  {
1254  if( m->hdr.dlen < 4 )
1255  return XRootDStatus( stError, errInvalidMessage, 0, "kXR_error: body too short." );
1256  m->body.error.errnum = ntohl( m->body.error.errnum );
1257  }
1258 
1259  //--------------------------------------------------------------------------
1260  // kXR_wait
1261  //--------------------------------------------------------------------------
1262  else if( m->hdr.status == kXR_wait )
1263  {
1264  if( m->hdr.dlen < 4 )
1265  return XRootDStatus( stError, errInvalidMessage, 0, "kXR_wait: body too short." );
1266  m->body.wait.seconds = htonl( m->body.wait.seconds );
1267  }
1268 
1269  //--------------------------------------------------------------------------
1270  // kXR_redirect
1271  //--------------------------------------------------------------------------
1272  else if( m->hdr.status == kXR_redirect )
1273  {
1274  if( m->hdr.dlen < 4 )
1275  return XRootDStatus( stError, errInvalidMessage, 0, "kXR_redirect: body too short." );
1276  m->body.redirect.port = htonl( m->body.redirect.port );
1277  }
1278 
1279  //--------------------------------------------------------------------------
1280  // kXR_waitresp
1281  //--------------------------------------------------------------------------
1282  else if( m->hdr.status == kXR_waitresp )
1283  {
1284  if( m->hdr.dlen < 4 )
1285  return XRootDStatus( stError, errInvalidMessage, 0, "kXR_waitresp: body too short." );
1286  m->body.waitresp.seconds = htonl( m->body.waitresp.seconds );
1287  }
1288 
1289  //--------------------------------------------------------------------------
1290  // kXR_attn
1291  //--------------------------------------------------------------------------
1292  else if( m->hdr.status == kXR_attn )
1293  {
1294  if( m->hdr.dlen < 4 )
1295  return XRootDStatus( stError, errInvalidMessage, 0, "kXR_attn: body too short." );
1296  m->body.attn.actnum = htonl( m->body.attn.actnum );
1297  }
1298 
1299  return XRootDStatus();
1300  }
1301 
1302  //------------------------------------------------------------------------
1304  //------------------------------------------------------------------------
1306  {
1307  //--------------------------------------------------------------------------
1308  // Calculate the crc32c before the unmarshaling the body!
1309  //--------------------------------------------------------------------------
1311  char *buffer = msg.GetBuffer( 8 + sizeof( rspst->bdy.crc32c ) );
1312  size_t length = rspst->hdr.dlen - sizeof( rspst->bdy.crc32c );
1313  uint32_t crcval = XrdOucCRC::Calc32C( buffer, length );
1314 
1315  size_t stlen = sizeof( ServerResponseStatus );
1316  switch( reqType )
1317  {
1318  case kXR_pgread:
1319  {
1320  stlen += sizeof( ServerResponseBody_pgRead );
1321  break;
1322  }
1323 
1324  case kXR_pgwrite:
1325  {
1326  stlen += sizeof( ServerResponseBody_pgWrite );
1327  break;
1328  }
1329  }
1330 
1331  if( msg.GetSize() < stlen ) return XRootDStatus( stError, errInvalidMessage, 0,
1332  "kXR_status: invalid message size." );
1333 
1334  rspst->bdy.crc32c = ntohl( rspst->bdy.crc32c );
1335  rspst->bdy.dlen = ntohl( rspst->bdy.dlen );
1336 
1337  switch( reqType )
1338  {
1339  case kXR_pgread:
1340  {
1342  pgrdbdy->offset = ntohll( pgrdbdy->offset );
1343  break;
1344  }
1345 
1346  case kXR_pgwrite:
1347  {
1349  pgwrtbdy->offset = ntohll( pgwrtbdy->offset );
1350  break;
1351  }
1352  }
1353 
1354  //--------------------------------------------------------------------------
1355  // Do the integrity checks
1356  //--------------------------------------------------------------------------
1357  if( crcval != rspst->bdy.crc32c )
1358  {
1359  return XRootDStatus( stError, errDataError, 0, "kXR_status response header "
1360  "corrupted (crc32c integrity check failed)." );
1361  }
1362 
1363  if( rspst->hdr.streamid[0] != rspst->bdy.streamID[0] ||
1364  rspst->hdr.streamid[1] != rspst->bdy.streamID[1] )
1365  {
1366  return XRootDStatus( stError, errDataError, 0, "response header corrupted "
1367  "(stream ID mismatch)." );
1368  }
1369 
1370 
1371 
1372  if( rspst->bdy.requestid + kXR_1stRequest != reqType )
1373  {
1374  return XRootDStatus( stError, errDataError, 0, "kXR_status response header corrupted "
1375  "(request ID mismatch)." );
1376  }
1377 
1378  return XRootDStatus();
1379  }
1380 
1382  {
1384  uint16_t reqType = rsp->status.bdy.requestid + kXR_1stRequest;
1385 
1386  switch( reqType )
1387  {
1388  case kXR_pgwrite:
1389  {
1390  //--------------------------------------------------------------------------
1391  // If there's no additional data there's nothing to unmarshal
1392  //--------------------------------------------------------------------------
1393  if( rsp->status.bdy.dlen == 0 ) return XRootDStatus();
1394  //--------------------------------------------------------------------------
1395  // If there's not enough data to form correction-segment report an error
1396  //--------------------------------------------------------------------------
1397  if( size_t( rsp->status.bdy.dlen ) < sizeof( ServerResponseBody_pgWrCSE ) )
1399  "kXR_status: invalid message size." );
1400 
1401  //--------------------------------------------------------------------------
1402  // Calculate the crc32c for the additional data
1403  //--------------------------------------------------------------------------
1405  cse->cseCRC = ntohl( cse->cseCRC );
1406  size_t length = rsp->status.bdy.dlen - sizeof( uint32_t );
1407  void* buffer = msg.GetBuffer( sizeof( ServerResponseV2 ) + sizeof( uint32_t ) );
1408  uint32_t crcval = XrdOucCRC::Calc32C( buffer, length );
1409 
1410  //--------------------------------------------------------------------------
1411  // Do the integrity checks
1412  //--------------------------------------------------------------------------
1413  if( crcval != cse->cseCRC )
1414  {
1415  return XRootDStatus( stError, errDataError, 0, "kXR_status response header "
1416  "corrupted (crc32c integrity check failed)." );
1417  }
1418 
1419  cse->dlFirst = ntohs( cse->dlFirst );
1420  cse->dlLast = ntohs( cse->dlLast );
1421 
1422  size_t pgcnt = ( rsp->status.bdy.dlen - sizeof( ServerResponseBody_pgWrCSE ) ) /
1423  sizeof( kXR_int64 );
1424  kXR_int64 *pgoffs = (kXR_int64*)msg.GetBuffer( sizeof( ServerResponseV2 ) +
1425  sizeof( ServerResponseBody_pgWrCSE ) );
1426 
1427  for( size_t i = 0; i < pgcnt; ++i )
1428  pgoffs[i] = ntohll( pgoffs[i] );
1429 
1430  return XRootDStatus();
1431  break;
1432  }
1433 
1434  default:
1435  break;
1436  }
1437 
1439  }
1440 
1441  //----------------------------------------------------------------------------
1442  // Unmarshall the header of the incoming message
1443  //----------------------------------------------------------------------------
1445  {
1447  header->status = ntohs( header->status );
1448  header->dlen = ntohl( header->dlen );
1449  }
1450 
1451  //----------------------------------------------------------------------------
1452  // Log server error response
1453  //----------------------------------------------------------------------------
1455  {
1456  Log *log = DefaultEnv::GetLog();
1457  ServerResponse *rsp = (ServerResponse *)msg.GetBuffer();
1458  char *errmsg = new char[rsp->hdr.dlen-3]; errmsg[rsp->hdr.dlen-4] = 0;
1459  memcpy( errmsg, rsp->body.error.errmsg, rsp->hdr.dlen-4 );
1460  log->Error( XRootDTransportMsg, "Server responded with an error [%d]: %s",
1461  rsp->body.error.errnum, errmsg );
1462  delete [] errmsg;
1463  }
1464 
1465  //------------------------------------------------------------------------
1466  // Number of currently connected data streams
1467  //------------------------------------------------------------------------
1469  {
1470  XRootDChannelInfo *info = 0;
1471  channelData.Get( info );
1472  XrdSysMutexHelper scopedLock( info->mutex );
1473 
1474  uint16_t nbConnected = 0;
1475  for( size_t i = 1; i < info->stream.size(); ++i )
1476  if( info->stream[i].status == XRootDStreamInfo::Connected )
1477  ++nbConnected;
1478 
1479  return nbConnected;
1480  }
1481 
1482  //----------------------------------------------------------------------------
1483  // The stream has been disconnected, do the cleanups
1484  //----------------------------------------------------------------------------
1486  uint16_t subStreamId )
1487  {
1488  XRootDChannelInfo *info = 0;
1489  channelData.Get( info );
1490  XrdSysMutexHelper scopedLock( info->mutex );
1491 
1492  CleanUpProtection( info );
1493 
1494  if( !info->stream.empty() )
1495  {
1496  XRootDStreamInfo &sInfo = info->stream[subStreamId];
1498  }
1499 
1500  if( subStreamId == 0 )
1501  {
1502  info->sidManager->ReleaseAllTimedOut();
1503  info->sentOpens.clear();
1504  info->sentCloses.clear();
1505  info->openFiles = 0;
1506  info->waitBarrier = 0;
1507  }
1508  }
1509 
1510  //------------------------------------------------------------------------
1511  // Query the channel
1512  //------------------------------------------------------------------------
1514  AnyObject &result,
1515  AnyObject &channelData )
1516  {
1517  XRootDChannelInfo *info = 0;
1518  channelData.Get( info );
1519  XrdSysMutexHelper scopedLock( info->mutex );
1520 
1521  switch( query )
1522  {
1523  //------------------------------------------------------------------------
1524  // Protocol name
1525  //------------------------------------------------------------------------
1526  case TransportQuery::Name:
1527  result.Set( (const char*)"XRootD", false );
1528  return Status();
1529 
1530  //------------------------------------------------------------------------
1531  // Authentication
1532  //------------------------------------------------------------------------
1533  case TransportQuery::Auth:
1534  result.Set( new std::string( info->authProtocolName ), false );
1535  return Status();
1536 
1537  //------------------------------------------------------------------------
1538  // Server flags
1539  //------------------------------------------------------------------------
1541  result.Set( new int( info->serverFlags ), false );
1542  return Status();
1543 
1544  //------------------------------------------------------------------------
1545  // Protocol version
1546  //------------------------------------------------------------------------
1548  result.Set( new int( info->protocolVersion ), false );
1549  return Status();
1550 
1552  result.Set( new bool( info->encrypted ), false );
1553  return Status();
1554  };
1555  return Status( stError, errQueryNotSupported );
1556  }
1557 
1558  //----------------------------------------------------------------------------
1559  // Check whether the transport can hijack the message
1560  //----------------------------------------------------------------------------
1562  uint16_t subStream,
1563  AnyObject &channelData )
1564  {
1565  XRootDChannelInfo *info = 0;
1566  channelData.Get( info );
1567  XrdSysMutexHelper scopedLock( info->mutex );
1568  Log *log = DefaultEnv::GetLog();
1569 
1570  //--------------------------------------------------------------------------
1571  // Update the substream queues
1572  //--------------------------------------------------------------------------
1573  info->strmSelector->MsgReceived( subStream );
1574 
1575  //--------------------------------------------------------------------------
1576  // Check whether this message is a response to a request that has
1577  // timed out, and if so, drop it
1578  //--------------------------------------------------------------------------
1579  ServerResponse *rsp = (ServerResponse*)msg.GetBuffer();
1580  if( rsp->hdr.status == kXR_attn )
1581  {
1582  return NoAction;
1583  }
1584 
1585  if( info->sidManager->IsTimedOut( rsp->hdr.streamid ) )
1586  {
1587  log->Error( XRootDTransportMsg, "Message %p, stream [%d, %d] is a "
1588  "response that we're no longer interested in (timed out)",
1589  &msg, rsp->hdr.streamid[0], rsp->hdr.streamid[1] );
1590  //------------------------------------------------------------------------
1591  // If it is kXR_waitresp there will be another one,
1592  // so we don't release the sid yet
1593  //------------------------------------------------------------------------
1594  if( rsp->hdr.status != kXR_waitresp )
1595  info->sidManager->ReleaseTimedOut( rsp->hdr.streamid );
1596  //------------------------------------------------------------------------
1597  // If it is a successful response to an open request
1598  // that timed out, we need to send a close
1599  //------------------------------------------------------------------------
1600  uint16_t sid; memcpy( &sid, rsp->hdr.streamid, 2 );
1601  std::set<uint16_t>::iterator sidIt = info->sentOpens.find( sid );
1602  if( sidIt != info->sentOpens.end() )
1603  {
1604  info->sentOpens.erase( sidIt );
1605  if( rsp->hdr.status == kXR_ok ) return RequestClose;
1606  }
1607  return DigestMsg;
1608  }
1609 
1610  //--------------------------------------------------------------------------
1611  // If we have a wait or waitresp
1612  //--------------------------------------------------------------------------
1613  uint32_t seconds = 0;
1614  if( rsp->hdr.status == kXR_wait )
1615  seconds = ntohl( rsp->body.wait.seconds ) + 5; // we need extra time
1616  // to re-send the request
1617  else if( rsp->hdr.status == kXR_waitresp )
1618  {
1619  seconds = ntohl( rsp->body.waitresp.seconds );
1620 
1621  log->Dump( XRootDMsg, "[%s] Got kXR_waitresp response of %u seconds, "
1622  "setting up wait barrier.",
1623  info->streamName.c_str(),
1624  seconds );
1625  }
1626 
1627  time_t barrier = time(0) + seconds;
1628  if( info->waitBarrier < barrier )
1629  info->waitBarrier = barrier;
1630 
1631  //--------------------------------------------------------------------------
1632  // If we got a response to an open request, we may need to bump the counter
1633  // of open files
1634  //--------------------------------------------------------------------------
1635  uint16_t sid; memcpy( &sid, rsp->hdr.streamid, 2 );
1636  std::set<uint16_t>::iterator sidIt = info->sentOpens.find( sid );
1637  if( sidIt != info->sentOpens.end() )
1638  {
1639  if( rsp->hdr.status == kXR_waitresp )
1640  return NoAction;
1641  info->sentOpens.erase( sidIt );
1642  if( rsp->hdr.status == kXR_ok )
1643  {
1644  ++info->openFiles;
1645  info->finstcnt.fetch_add( 1, std::memory_order_relaxed ); // another file File object instance has been bound with this connection
1646  }
1647  return NoAction;
1648  }
1649 
1650  //--------------------------------------------------------------------------
1651  // If we got a response to a close, we may need to decrement the counter of
1652  // open files
1653  //--------------------------------------------------------------------------
1654  sidIt = info->sentCloses.find( sid );
1655  if( sidIt != info->sentCloses.end() )
1656  {
1657  if( rsp->hdr.status == kXR_waitresp )
1658  return NoAction;
1659  info->sentCloses.erase( sidIt );
1660  --info->openFiles;
1661  return NoAction;
1662  }
1663  return NoAction;
1664  }
1665 
1666  //----------------------------------------------------------------------------
1667  // Notify the transport about a message having been sent
1668  //----------------------------------------------------------------------------
1670  uint16_t subStream,
1671  uint32_t bytesSent,
1672  AnyObject &channelData )
1673  {
1674  XRootDChannelInfo *info = 0;
1675  channelData.Get( info );
1676  XrdSysMutexHelper scopedLock( info->mutex );
1677  ClientRequest *req = (ClientRequest*)msg->GetBuffer();
1678  uint16_t reqid = ntohs( req->header.requestid );
1679 
1680 
1681  //--------------------------------------------------------------------------
1682  // We need to track opens to know if we can close streams due to idleness
1683  //--------------------------------------------------------------------------
1684  uint16_t sid;
1685  memcpy( &sid, req->header.streamid, 2 );
1686 
1687  if( reqid == kXR_open )
1688  info->sentOpens.insert( sid );
1689  else if( reqid == kXR_close )
1690  info->sentCloses.insert( sid );
1691  }
1692 
1693 
1694  //----------------------------------------------------------------------------
1695  // Get signature for given message
1696  //----------------------------------------------------------------------------
1698  {
1699  XRootDChannelInfo *info = 0;
1700  channelData.Get( info );
1701  return GetSignature( toSign, sign, info );
1702  }
1703 
1704  //------------------------------------------------------------------------
1706  //------------------------------------------------------------------------
1708  Message *&sign,
1709  XRootDChannelInfo *info )
1710  {
1711  XrdSysRWLockHelper scope( pSecUnloadHandler->lock );
1712  if( pSecUnloadHandler->unloaded ) return Status( stError, errInvalidOp );
1713 
1714  ClientRequest *thereq = reinterpret_cast<ClientRequest*>( toSign->GetBuffer() );
1715  if( !info ) return Status( stError, errInternal );
1716  if( info->protection )
1717  {
1718  SecurityRequest *newreq = 0;
1719  // check if we have to secure the request in the first place
1720  if( !( NEED2SECURE ( info->protection )( *thereq ) ) ) return Status();
1721  // secure (sign/encrypt) the request
1722  int rc = info->protection->Secure( newreq, *thereq, 0 );
1723  // there was an error
1724  if( rc < 0 )
1725  return Status( stError, errInternal, -rc );
1726 
1727  sign = new Message();
1728  sign->Grab( reinterpret_cast<char*>( newreq ), rc );
1729  }
1730 
1731  return Status();
1732  }
1733 
1734  //------------------------------------------------------------------------
1736  //------------------------------------------------------------------------
1738  {
1739  XRootDChannelInfo *info = 0;
1740  channelData.Get( info );
1741  if( info->finstcnt.load( std::memory_order_relaxed ) > 0 )
1742  info->finstcnt.fetch_sub( 1, std::memory_order_relaxed );
1743  }
1744 
1745  //----------------------------------------------------------------------------
1746  // Wait before exit
1747  //----------------------------------------------------------------------------
1749  {
1750  XrdSysRWLockHelper scope( pSecUnloadHandler->lock, false ); // obtain write lock
1751  pSecUnloadHandler->unloaded = true;
1752  }
1753 
1754  //----------------------------------------------------------------------------
1755  // @return : true if encryption should be turned on, false otherwise
1756  //----------------------------------------------------------------------------
1758  AnyObject &channelData )
1759  {
1760  XRootDChannelInfo *info = 0;
1761  channelData.Get( info );
1762 
1764  int notlsok = DefaultNoTlsOK;
1765  env->GetInt( "NoTlsOK", notlsok );
1766 
1767  if( notlsok )
1768  return info->encrypted;
1769 
1770  // Did the server instructed us to switch to TLS right away?
1771  if( info->serverFlags & kXR_gotoTLS )
1772  {
1773  info->encrypted = true;
1774  return true ;
1775  }
1776 
1777  XRootDStreamInfo &sInfo = info->stream[handShakeData->subStreamId];
1778 
1779  //--------------------------------------------------------------------------
1780  // The control stream (sub-stream 0) might need to switch to TLS before
1781  // login or after login
1782  //--------------------------------------------------------------------------
1783  if( handShakeData->subStreamId == 0 )
1784  {
1785  //------------------------------------------------------------------------
1786  // We are about to login and the server asked to start encrypting
1787  // before login
1788  //------------------------------------------------------------------------
1789  if( ( sInfo.status == XRootDStreamInfo::LoginSent ) &&
1790  ( info->serverFlags & kXR_tlsLogin ) )
1791  {
1792  info->encrypted = true;
1793  return true;
1794  }
1795 
1796  //--------------------------------------------------------------------
1797  // The hand-shake is done and the server requested to encrypt the session
1798  //--------------------------------------------------------------------
1799  if( (sInfo.status == XRootDStreamInfo::Connected ||
1800  //--------------------------------------------------------------------
1801  // we really need to turn on TLS before we sent kXR_endsess and we
1802  // are about to do so (1st enable encryption, then send kXR_endsess)
1803  //--------------------------------------------------------------------
1805  ( info->serverFlags & kXR_tlsSess ) )
1806  {
1807  info->encrypted = true;
1808  return true;
1809  }
1810  }
1811  //--------------------------------------------------------------------------
1812  // A data stream (sub-stream > 0) if need be will be switched to TLS before
1813  // bind.
1814  //--------------------------------------------------------------------------
1815  else
1816  {
1817  //------------------------------------------------------------------------
1818  // We are about to bind a data stream and the server asked to start
1819  // encrypting before bind
1820  //------------------------------------------------------------------------
1821  if( ( sInfo.status == XRootDStreamInfo::BindSent ) &&
1822  ( info->serverFlags & kXR_tlsData ) )
1823  {
1824  info->encrypted = true;
1825  return true;
1826  }
1827  }
1828 
1829  return false;
1830  }
1831 
1832  //------------------------------------------------------------------------
1833  // Get bind preference for the next data stream
1834  //------------------------------------------------------------------------
1836  AnyObject &channelData )
1837  {
1838  XRootDChannelInfo *info = 0;
1839  channelData.Get( info );
1840  if( !bool( info->bindSelector ) )
1841  return url;
1842 
1843  return URL( info->bindSelector->Get() );
1844  }
1845 
1846  //----------------------------------------------------------------------------
1847  // Generate the message to be sent as an initial handshake
1848  // (handshake+kXR_protocol)
1849  //----------------------------------------------------------------------------
1850  Message *XRootDTransport::GenerateInitialHSProtocol( HandShakeData *hsData,
1851  XRootDChannelInfo *info,
1852  kXR_char expect )
1853  {
1854  Log *log = DefaultEnv::GetLog();
1855  log->Debug( XRootDTransportMsg,
1856  "[%s] Sending out the initial hand shake + kXR_protocol",
1857  hsData->streamName.c_str() );
1858 
1859  Message *msg = new Message();
1860 
1861  msg->Allocate( 20+sizeof(ClientProtocolRequest) );
1862  msg->Zero();
1863 
1865  init->fourth = htonl(4);
1866  init->fifth = htonl(2012);
1867 
1869  InitProtocolReq( proto, info, expect );
1870 
1871  return msg;
1872  }
1873 
1874  //------------------------------------------------------------------------
1875  // Generate the protocol message
1876  //------------------------------------------------------------------------
1877  Message *XRootDTransport::GenerateProtocol( HandShakeData *hsData,
1878  XRootDChannelInfo *info,
1879  kXR_char expect )
1880  {
1881  Log *log = DefaultEnv::GetLog();
1882  log->Debug( XRootDTransportMsg,
1883  "[%s] Sending out the kXR_protocol",
1884  hsData->streamName.c_str() );
1885 
1886  Message *msg = new Message();
1887  msg->Allocate( sizeof(ClientProtocolRequest) );
1888  msg->Zero();
1889 
1890  ClientProtocolRequest *proto = (ClientProtocolRequest *)msg->GetBuffer();
1891  InitProtocolReq( proto, info, expect );
1892 
1893  return msg;
1894  }
1895 
1896  //------------------------------------------------------------------------
1897  // Initialize protocol request
1898  //------------------------------------------------------------------------
1899  void XRootDTransport::InitProtocolReq( ClientProtocolRequest *request,
1900  XRootDChannelInfo *info,
1901  kXR_char expect )
1902  {
1903  request->requestid = htons(kXR_protocol);
1904  request->clientpv = htonl(kXR_PROTOCOLVERSION);
1907 
1908  int notlsok = DefaultNoTlsOK;
1909  int tlsnodata = DefaultTlsNoData;
1910 
1912 
1913  env->GetInt( "NoTlsOK", notlsok );
1914 
1916  env->GetInt( "TlsNoData", tlsnodata );
1917 
1918  if (info->encrypted || InitTLS())
1920 
1921  if (info->encrypted && !(notlsok || tlsnodata))
1923 
1924  request->expect = expect;
1925 
1926  //--------------------------------------------------------------------------
1927  // If we are in the curse of establishing a connection in the context of
1928  // TPC update the expect! (this will be never followed be a bind)
1929  //--------------------------------------------------------------------------
1930  if( info->istpc )
1932  }
1933 
1934  //----------------------------------------------------------------------------
1935  // Process the server initial handshake response
1936  //----------------------------------------------------------------------------
1937  XRootDStatus XRootDTransport::ProcessServerHS( HandShakeData *hsData,
1938  XRootDChannelInfo *info )
1939  {
1940  Log *log = DefaultEnv::GetLog();
1941 
1942  Message *msg = hsData->in;
1943  ServerResponseHeader *respHdr = (ServerResponseHeader *)msg->GetBuffer();
1944  ServerInitHandShake *hs = (ServerInitHandShake *)msg->GetBuffer(4);
1945 
1946  if( respHdr->status != kXR_ok )
1947  {
1948  log->Error( XRootDTransportMsg, "[%s] Invalid hand shake response",
1949  hsData->streamName.c_str() );
1950 
1951  return XRootDStatus( stFatal, errHandShakeFailed, 0, "Invalid hand shake response." );
1952  }
1953 
1954  info->protocolVersion = ntohl(hs->protover);
1955  info->serverFlags = ntohl(hs->msgval) == kXR_DataServer ?
1956  kXR_isServer:
1957  kXR_isManager;
1958 
1959  log->Debug( XRootDTransportMsg,
1960  "[%s] Got the server hand shake response (%s, protocol "
1961  "version %x)",
1962  hsData->streamName.c_str(),
1963  ServerFlagsToStr( info->serverFlags ).c_str(),
1964  info->protocolVersion );
1965 
1966  return XRootDStatus( stOK, suContinue );
1967  }
1968 
1969  //----------------------------------------------------------------------------
1970  // Process the protocol response
1971  //----------------------------------------------------------------------------
1972  XRootDStatus XRootDTransport::ProcessProtocolResp( HandShakeData *hsData,
1973  XRootDChannelInfo *info )
1974  {
1975  Log *log = DefaultEnv::GetLog();
1976 
1977  XRootDStatus st = UnMarshallBody( hsData->in, kXR_protocol );
1978  if( !st.IsOK() )
1979  return st;
1980 
1981  ServerResponse *rsp = (ServerResponse*)hsData->in->GetBuffer();
1982 
1983 
1984  if( rsp->hdr.status != kXR_ok )
1985  {
1986  log->Error( XRootDTransportMsg, "[%s] kXR_protocol request failed",
1987  hsData->streamName.c_str() );
1988 
1989  return XRootDStatus( stFatal, errHandShakeFailed, 0, "kXR_protocol request failed" );
1990  }
1991 
1993  int notlsok = DefaultNoTlsOK;
1994  env->GetInt( "NoTlsOK", notlsok );
1995 
1996  if( rsp->body.protocol.pval < kXR_PROTTLSVERSION && info->encrypted )
1997  {
1998  //------------------------------------------------------------------------
1999  // User requested an encrypted connection but the server is to old to
2000  // support it!
2001  //------------------------------------------------------------------------
2002  if( !notlsok ) return XRootDStatus( stFatal, errTlsError, ENOTSUP, "TLS not supported" );
2003 
2004  //------------------------------------------------------------------------
2005  // We are falling back to unencrypted data transmission, as configured
2006  // in XRD_NOTLSOK environment variable
2007  //------------------------------------------------------------------------
2008  log->Info( XRootDTransportMsg,
2009  "[%s] Falling back to unencrypted transmission, server does "
2010  "not support TLS encryption.",
2011  hsData->streamName.c_str() );
2012  info->encrypted = false;
2013  }
2014 
2015  if( rsp->body.protocol.pval >= 0x297 )
2016  info->serverFlags = rsp->body.protocol.flags;
2017 
2018  if( rsp->hdr.dlen > 8 )
2019  {
2020  info->protRespBody = new ServerResponseBody_Protocol();
2021  info->protRespBody->flags = rsp->body.protocol.flags;
2022  info->protRespBody->pval = rsp->body.protocol.pval;
2023 
2024  char* bodybuff = reinterpret_cast<char*>( &rsp->body.protocol.secreq );
2025  size_t bodysize = rsp->hdr.dlen - 8;
2026  XRootDStatus st = ProcessProtocolBody( bodybuff, bodysize, info );
2027  if( !st.IsOK() )
2028  return st;
2029  }
2030 
2031  log->Debug( XRootDTransportMsg,
2032  "[%s] kXR_protocol successful (%s, protocol version %x)",
2033  hsData->streamName.c_str(),
2034  ServerFlagsToStr( info->serverFlags ).c_str(),
2035  info->protocolVersion );
2036 
2037  if( !( info->serverFlags & kXR_haveTLS ) && info->encrypted )
2038  {
2039  //------------------------------------------------------------------------
2040  // User requested an encrypted connection but the server was not configured
2041  // to support encryption!
2042  //------------------------------------------------------------------------
2043  return XRootDStatus( stFatal, errTlsError, ECONNREFUSED,
2044  "Server was not configured to support encryption." );
2045  }
2046 
2047  //--------------------------------------------------------------------------
2048  // Now see if we have to enforce encryption in case the server does not
2049  // support PgRead/PgWrite
2050  //--------------------------------------------------------------------------
2051  int tlsOnNoPgrw = DefaultWantTlsOnNoPgrw;
2052  env->GetInt( "WantTlsOnNoPgrw", tlsOnNoPgrw );
2053  if( !( info->serverFlags & kXR_suppgrw ) && tlsOnNoPgrw )
2054  {
2055  //------------------------------------------------------------------------
2056  // If user requested encryption just make sure it is not switched off for
2057  // data
2058  //------------------------------------------------------------------------
2059  if( info->encrypted )
2060  {
2061  log->Debug( XRootDTransportMsg,
2062  "[%s] Server does not support PgRead/PgWrite and"
2063  " WantTlsOnNoPgrw is on; enforcing encryption for data.",
2064  hsData->streamName.c_str() );
2065  env->PutInt( "TlsNoData", DefaultTlsNoData );
2066  }
2067  //------------------------------------------------------------------------
2068  // Otherwise, if server is not enforcing data encryption, we will need to
2069  // redo the protocol request with kXR_wantTLS set.
2070  //------------------------------------------------------------------------
2071  else if( !( info->serverFlags & kXR_tlsData ) &&
2072  ( info->serverFlags & kXR_haveTLS ) )
2073  {
2074  info->encrypted = true;
2075  return XRootDStatus( stOK, suRetry );
2076  }
2077  }
2078 
2079  return XRootDStatus( stOK, suContinue );
2080  }
2081 
2082  XRootDStatus XRootDTransport::ProcessProtocolBody( char *bodybuff,
2083  size_t bodysize,
2084  XRootDChannelInfo *info )
2085  {
2086  //--------------------------------------------------------------------------
2087  // Parse bind preferences
2088  //--------------------------------------------------------------------------
2089  XrdProto::bifReqs *bifreq = reinterpret_cast<XrdProto::bifReqs*>( bodybuff );
2090  if( bodysize >= sizeof( XrdProto::bifReqs ) && bifreq->theTag == 'B' )
2091  {
2092  bodybuff += sizeof( XrdProto::bifReqs );
2093  bodysize -= sizeof( XrdProto::bifReqs );
2094 
2095  if( bodysize < bifreq->bifILen )
2096  return XRootDStatus( stError, errDataError, 0, "Received incomplete "
2097  "protocol response." );
2098  std::string bindprefs_str( bodybuff, bifreq->bifILen );
2099  std::vector<std::string> bindprefs;
2100  Utils::splitString( bindprefs, bindprefs_str, "," );
2101  info->bindSelector.reset( new BindPrefSelector( std::move( bindprefs ) ) );
2102  bodybuff += bifreq->bifILen;
2103  bodysize -= bifreq->bifILen;
2104  }
2105  //--------------------------------------------------------------------------
2106  // Parse security requirements
2107  //--------------------------------------------------------------------------
2108  XrdProto::secReqs *secreq = reinterpret_cast<XrdProto::secReqs*>( bodybuff );
2109  if( bodysize >= 6 /*XrdProto::secReqs*/ && secreq->theTag == 'S' )
2110  {
2111  memcpy( &info->protRespBody->secreq, secreq, bodysize );
2112  info->protRespSize = bodysize + 8 /*pval & flags*/;
2113  }
2114 
2115  return XRootDStatus();
2116  }
2117 
2118  //----------------------------------------------------------------------------
2119  // Generate the bind message
2120  //----------------------------------------------------------------------------
2121  Message *XRootDTransport::GenerateBind( HandShakeData *hsData,
2122  XRootDChannelInfo *info )
2123  {
2124  Log *log = DefaultEnv::GetLog();
2125 
2126  log->Debug( XRootDTransportMsg,
2127  "[%s] Sending out the bind request",
2128  hsData->streamName.c_str() );
2129 
2130 
2131  Message *msg = new Message( sizeof( ClientBindRequest ) );
2132  ClientBindRequest *bindReq = (ClientBindRequest *)msg->GetBuffer();
2133 
2134  bindReq->requestid = kXR_bind;
2135  memcpy( bindReq->sessid, info->sessionId, 16 );
2136  bindReq->dlen = 0;
2137  MarshallRequest( msg );
2138  return msg;
2139  }
2140 
2141  //----------------------------------------------------------------------------
2142  // Generate the bind message
2143  //----------------------------------------------------------------------------
2144  XRootDStatus XRootDTransport::ProcessBindResp( HandShakeData *hsData,
2145  XRootDChannelInfo *info )
2146  {
2147  Log *log = DefaultEnv::GetLog();
2148 
2149  XRootDStatus st = UnMarshallBody( hsData->in, kXR_bind );
2150  if( !st.IsOK() )
2151  return st;
2152 
2153  ServerResponse *rsp = (ServerResponse*)hsData->in->GetBuffer();
2154 
2155  if( rsp->hdr.status != kXR_ok )
2156  {
2157  log->Error( XRootDTransportMsg, "[%s] kXR_bind request failed",
2158  hsData->streamName.c_str() );
2159  return XRootDStatus( stFatal, errHandShakeFailed, 0, "kXR_bind request failed" );
2160  }
2161 
2162  info->stream[hsData->subStreamId].pathId = rsp->body.bind.substreamid;
2163  log->Debug( XRootDTransportMsg, "[%s] kXR_bind successful",
2164  hsData->streamName.c_str() );
2165 
2166  return XRootDStatus();
2167  }
2168 
2169  //----------------------------------------------------------------------------
2170  // Generate the login message
2171  //----------------------------------------------------------------------------
2172  Message *XRootDTransport::GenerateLogIn( HandShakeData *hsData,
2173  XRootDChannelInfo *info )
2174  {
2175  Log *log = DefaultEnv::GetLog();
2176  Env *env = DefaultEnv::GetEnv();
2177 
2178  //--------------------------------------------------------------------------
2179  // Compute the login cgi
2180  //--------------------------------------------------------------------------
2181  int timeZone = XrdSysTimer::TimeZone();
2182  char *hostName = XrdNetUtils::MyHostName();
2183  std::string countryCode = Utils::FQDNToCC( hostName );
2184  char *cgiBuffer = new char[1024 + info->logintoken.size()];
2185  std::string appName;
2186  std::string monInfo;
2187  env->GetString( "AppName", appName );
2188  env->GetString( "MonInfo", monInfo );
2189  if( info->logintoken.empty() )
2190  {
2191  snprintf( cgiBuffer, 1024,
2192  "xrd.cc=%s&xrd.tz=%d&xrd.appname=%s&xrd.info=%s&"
2193  "xrd.hostname=%s&xrd.rn=%s", countryCode.c_str(), timeZone,
2194  appName.c_str(), monInfo.c_str(), hostName, XrdVERSION );
2195  }
2196  else
2197  {
2198  snprintf( cgiBuffer, 1024,
2199  "xrd.cc=%s&xrd.tz=%d&xrd.appname=%s&xrd.info=%s&"
2200  "xrd.hostname=%s&xrd.rn=%s&%s", countryCode.c_str(), timeZone,
2201  appName.c_str(), monInfo.c_str(), hostName, XrdVERSION, info->logintoken.c_str() );
2202  }
2203  uint16_t cgiLen = strlen( cgiBuffer );
2204  free( hostName );
2205 
2206  //--------------------------------------------------------------------------
2207  // Generate the message
2208  //--------------------------------------------------------------------------
2209  Message *msg = new Message( sizeof(ClientLoginRequest) + cgiLen );
2210  ClientLoginRequest *loginReq = (ClientLoginRequest *)msg->GetBuffer();
2211 
2212  loginReq->requestid = kXR_login;
2213  loginReq->pid = ::getpid();
2214  loginReq->capver[0] = kXR_asyncap | kXR_ver005;
2215  loginReq->dlen = cgiLen;
2217 #ifdef WITH_XRDEC
2218  loginReq->ability2 = kXR_ecredir;
2219 #endif
2220 
2221  int multiProtocol = 0;
2222  env->GetInt( "MultiProtocol", multiProtocol );
2223  if(multiProtocol)
2224  loginReq->ability |= kXR_multipr;
2225 
2226  //--------------------------------------------------------------------------
2227  // Check the IP stacks
2228  //--------------------------------------------------------------------------
2230  bool dualStack = false;
2231  bool privateIPv6 = false;
2232  bool privateIPv4 = false;
2233 
2234  if( (stacks & XrdNetUtils::hasIP64) == XrdNetUtils::hasIP64 )
2235  {
2236  dualStack = true;
2237  loginReq->ability |= kXR_hasipv64;
2238  }
2239 
2240  if( (stacks & XrdNetUtils::hasIPv6) && !(stacks & XrdNetUtils::hasPub6) )
2241  {
2242  privateIPv6 = true;
2243  loginReq->ability |= kXR_onlyprv6;
2244  }
2245 
2246  if( (stacks & XrdNetUtils::hasIPv4) && !(stacks & XrdNetUtils::hasPub4) )
2247  {
2248  privateIPv4 = true;
2249  loginReq->ability |= kXR_onlyprv4;
2250  }
2251 
2252  // The following code snippet tries to overcome the problem that this host
2253  // may still be dual-stacked but we don't know it because one of the
2254  // interfaces was not registered in DNS.
2255  //
2256  if( !dualStack && hsData->serverAddr )
2257  {if ( ( ( stacks & XrdNetUtils::hasIPv4 )
2258  && hsData->serverAddr->isIPType(XrdNetAddrInfo::IPv6))
2259  || ( ( stacks & XrdNetUtils::hasIPv6 )
2260  && hsData->serverAddr->isIPType(XrdNetAddrInfo::IPv4)))
2261  {dualStack = true;
2262  loginReq->ability |= kXR_hasipv64;
2263  }
2264  }
2265 
2266  //--------------------------------------------------------------------------
2267  // Check the username
2268  //--------------------------------------------------------------------------
2269  std::string buffer( 8, 0 );
2270  if( hsData->url->GetUserName().length() )
2271  buffer = hsData->url->GetUserName();
2272  else
2273  {
2274  char *name = new char[1024];
2275  if( !XrdOucUtils::UserName( geteuid(), name, 1024 ) )
2276  buffer = name;
2277  else
2278  buffer = "_anon_";
2279  delete [] name;
2280  }
2281  buffer.resize( 8, 0 );
2282  std::copy( buffer.begin(), buffer.end(), (char*)loginReq->username );
2283 
2284  msg->Append( cgiBuffer, cgiLen, 24 );
2285 
2286  log->Debug( XRootDTransportMsg, "[%s] Sending out kXR_login request, "
2287  "username: %s, cgi: %s, dual-stack: %s, private IPv4: %s, "
2288  "private IPv6: %s", hsData->streamName.c_str(),
2289  loginReq->username, cgiBuffer, dualStack ? "true" : "false",
2290  privateIPv4 ? "true" : "false",
2291  privateIPv6 ? "true" : "false" );
2292 
2293  delete [] cgiBuffer;
2294  MarshallRequest( msg );
2295  return msg;
2296  }
2297 
2298  //----------------------------------------------------------------------------
2299  // Process the protocol response
2300  //----------------------------------------------------------------------------
2301  XRootDStatus XRootDTransport::ProcessLogInResp( HandShakeData *hsData,
2302  XRootDChannelInfo *info )
2303  {
2304  Log *log = DefaultEnv::GetLog();
2305 
2306  XRootDStatus st = UnMarshallBody( hsData->in, kXR_login );
2307  if( !st.IsOK() )
2308  return st;
2309 
2310  ServerResponse *rsp = (ServerResponse*)hsData->in->GetBuffer();
2311 
2312  if( rsp->hdr.status != kXR_ok )
2313  {
2314  log->Error( XRootDTransportMsg, "[%s] Got invalid login response",
2315  hsData->streamName.c_str() );
2316  return XRootDStatus( stFatal, errLoginFailed, 0, "Got invalid login response." );
2317  }
2318 
2319  if( !info->firstLogIn )
2320  memcpy( info->oldSessionId, info->sessionId, 16 );
2321 
2322  if( rsp->hdr.dlen == 0 && info->protocolVersion <= 0x289 )
2323  {
2324  //--------------------------------------------------------------------------
2325  // This if statement is there only to support dCache inaccurate
2326  // implementation of XRoot protocol, that in some cases returns
2327  // an empty login response for protocol version <= 2.8.9.
2328  //--------------------------------------------------------------------------
2329  memset( info->sessionId, 0, 16 );
2330  log->Warning( XRootDTransportMsg,
2331  "[%s] Logged in, accepting empty login response.",
2332  hsData->streamName.c_str() );
2333  return XRootDStatus();
2334  }
2335 
2336  if( rsp->hdr.dlen < 16 )
2337  return XRootDStatus( stError, errDataError, 0, "Login response too short." );
2338 
2339  memcpy( info->sessionId, rsp->body.login.sessid, 16 );
2340 
2341  std::string sessId = Utils::Char2Hex( rsp->body.login.sessid, 16 );
2342 
2343  log->Debug( XRootDTransportMsg, "[%s] Logged in, session: %s",
2344  hsData->streamName.c_str(), sessId.c_str() );
2345 
2346  //--------------------------------------------------------------------------
2347  // We have an authentication info to process
2348  //--------------------------------------------------------------------------
2349  if( rsp->hdr.dlen > 16 )
2350  {
2351  size_t len = rsp->hdr.dlen-16;
2352  info->authBuffer = new char[len+1];
2353  info->authBuffer[len] = 0;
2354  memcpy( info->authBuffer, rsp->body.login.sec, len );
2355  log->Debug( XRootDTransportMsg, "[%s] Authentication is required: %s",
2356  hsData->streamName.c_str(), info->authBuffer );
2357 
2358  return XRootDStatus( stOK, suContinue );
2359  }
2360 
2361  return XRootDStatus();
2362  }
2363 
2364  //----------------------------------------------------------------------------
2365  // Do the authentication
2366  //----------------------------------------------------------------------------
2367  XRootDStatus XRootDTransport::DoAuthentication( HandShakeData *hsData,
2368  XRootDChannelInfo *info )
2369  {
2370  //--------------------------------------------------------------------------
2371  // Prepare
2372  //--------------------------------------------------------------------------
2373  Log *log = DefaultEnv::GetLog();
2374  XRootDStreamInfo &sInfo = info->stream[hsData->subStreamId];
2375  XrdSecCredentials *credentials = 0;
2376  std::string protocolName;
2377 
2378  //--------------------------------------------------------------------------
2379  // We're doing this for the first time
2380  //--------------------------------------------------------------------------
2381  if( sInfo.status == XRootDStreamInfo::LoginSent )
2382  {
2383  log->Debug( XRootDTransportMsg, "[%s] Sending authentication data",
2384  hsData->streamName.c_str() );
2385 
2386  //------------------------------------------------------------------------
2387  // Set up the authentication environment
2388  //------------------------------------------------------------------------
2389  info->authEnv = new XrdOucEnv();
2390  info->authEnv->Put( "sockname", hsData->clientName.c_str() );
2391  info->authEnv->Put( "username", hsData->url->GetUserName().c_str() );
2392  info->authEnv->Put( "password", hsData->url->GetPassword().c_str() );
2393 
2394  const URL::ParamsMap &urlParams = hsData->url->GetParams();
2395  URL::ParamsMap::const_iterator it;
2396  for( it = urlParams.begin(); it != urlParams.end(); ++it )
2397  {
2398  if( it->first.compare( 0, 4, "xrd." ) == 0 ||
2399  it->first.compare( 0, 6, "xrdcl." ) == 0 )
2400  info->authEnv->Put( it->first.c_str(), it->second.c_str() );
2401  }
2402 
2403  //------------------------------------------------------------------------
2404  // Initialize some other structs
2405  //------------------------------------------------------------------------
2406  size_t authBuffLen = strlen( info->authBuffer );
2407  char *pars = (char *)malloc( authBuffLen + 1 );
2408  memcpy( pars, info->authBuffer, authBuffLen );
2409  info->authParams = new XrdSecParameters( pars, authBuffLen );
2410  sInfo.status = XRootDStreamInfo::AuthSent;
2411  delete [] info->authBuffer;
2412  info->authBuffer = 0;
2413 
2414  //------------------------------------------------------------------------
2415  // Find a protocol that gives us valid credentials
2416  //------------------------------------------------------------------------
2417  XRootDStatus st = GetCredentials( credentials, hsData, info );
2418  if( !st.IsOK() )
2419  {
2420  CleanUpAuthentication( info );
2421  return st;
2422  }
2423  protocolName = info->authProtocol->Entity.prot;
2424  }
2425 
2426  //--------------------------------------------------------------------------
2427  // We've been here already
2428  //--------------------------------------------------------------------------
2429  else
2430  {
2431  ServerResponse *rsp = (ServerResponse*)hsData->in->GetBuffer();
2432  protocolName = info->authProtocol->Entity.prot;
2433 
2434  //------------------------------------------------------------------------
2435  // We're required to send out more authentication data
2436  //------------------------------------------------------------------------
2437  if( rsp->hdr.status == kXR_authmore )
2438  {
2439  log->Debug( XRootDTransportMsg,
2440  "[%s] Sending more authentication data for %s",
2441  hsData->streamName.c_str(), protocolName.c_str() );
2442 
2443  uint32_t len = rsp->hdr.dlen;
2444  char *secTokenData = (char*)malloc( len );
2445  memcpy( secTokenData, rsp->body.authmore.data, len );
2446  XrdSecParameters *secToken = new XrdSecParameters( secTokenData, len );
2447  XrdOucErrInfo ei( "", info->authEnv);
2448  credentials = info->authProtocol->getCredentials( secToken, &ei );
2449  delete secToken;
2450 
2451  //----------------------------------------------------------------------
2452  // The protocol handler refuses to give us the data
2453  //----------------------------------------------------------------------
2454  if( !credentials )
2455  {
2456  log->Error( XRootDTransportMsg,
2457  "[%s] Auth protocol handler for %s refuses to give "
2458  "us more credentials %s",
2459  hsData->streamName.c_str(), protocolName.c_str(),
2460  ei.getErrText() );
2461  CleanUpAuthentication( info );
2462  return XRootDStatus( stFatal, errAuthFailed, 0, ei.getErrText() );
2463  }
2464  }
2465 
2466  //------------------------------------------------------------------------
2467  // We have succeeded
2468  //------------------------------------------------------------------------
2469  else if( rsp->hdr.status == kXR_ok )
2470  {
2471  info->authProtocolName = info->authProtocol->Entity.prot;
2472 
2473  //----------------------------------------------------------------------
2474  // Do we need protection?
2475  //----------------------------------------------------------------------
2476  if( info->protRespBody )
2477  {
2478  int rc = XrdSecGetProtection( info->protection, *info->authProtocol, *info->protRespBody, info->protRespSize );
2479  if( rc > 0 )
2480  {
2481  log->Debug( XRootDTransportMsg,
2482  "[%s] XrdSecProtect loaded.", hsData->streamName.c_str() );
2483  }
2484  else if( rc == 0 )
2485  {
2486  log->Debug( XRootDTransportMsg,
2487  "[%s] XrdSecProtect: no protection needed.",
2488  hsData->streamName.c_str() );
2489  }
2490  else
2491  {
2492  log->Debug( XRootDTransportMsg,
2493  "[%s] Failed to load XrdSecProtect: %s",
2494  hsData->streamName.c_str(), XrdSysE2T( -rc ) );
2495  CleanUpAuthentication( info );
2496 
2497  return XRootDStatus( stError, errAuthFailed, -rc, XrdSysE2T( -rc ) );
2498  }
2499  }
2500 
2501  if( !info->protection )
2502  CleanUpAuthentication( info );
2503  else
2504  pSecUnloadHandler->Register( info->authProtocolName );
2505 
2506  log->Debug( XRootDTransportMsg,
2507  "[%s] Authenticated with %s.", hsData->streamName.c_str(),
2508  protocolName.c_str() );
2509 
2510  //--------------------------------------------------------------------
2511  // Clear the SSL error queue of the calling thread, as there might be
2512  // some leftover from the authentication!
2513  //--------------------------------------------------------------------
2515 
2516  return XRootDStatus();
2517  }
2518  //------------------------------------------------------------------------
2519  // Failure
2520  //------------------------------------------------------------------------
2521  else if( rsp->hdr.status == kXR_error )
2522  {
2523  char *errmsg = new char[rsp->hdr.dlen-3]; errmsg[rsp->hdr.dlen-4] = 0;
2524  memcpy( errmsg, rsp->body.error.errmsg, rsp->hdr.dlen-4 );
2525  log->Error( XRootDTransportMsg,
2526  "[%s] Authentication with %s failed: %s",
2527  hsData->streamName.c_str(), protocolName.c_str(),
2528  errmsg );
2529  delete [] errmsg;
2530 
2531  info->authProtocol->Delete();
2532  info->authProtocol = 0;
2533 
2534  //----------------------------------------------------------------------
2535  // Find another protocol that gives us valid credentials
2536  //----------------------------------------------------------------------
2537  XRootDStatus st = GetCredentials( credentials, hsData, info );
2538  if( !st.IsOK() )
2539  {
2540  CleanUpAuthentication( info );
2541  return st;
2542  }
2543  protocolName = info->authProtocol->Entity.prot;
2544  }
2545  //------------------------------------------------------------------------
2546  // God knows what
2547  //------------------------------------------------------------------------
2548  else
2549  {
2550  info->authProtocolName = info->authProtocol->Entity.prot;
2551  CleanUpAuthentication( info );
2552 
2553  log->Error( XRootDTransportMsg,
2554  "[%s] Authentication with %s failed: unexpected answer",
2555  hsData->streamName.c_str(), protocolName.c_str() );
2556  return XRootDStatus( stFatal, errAuthFailed, 0, "Authentication failed: unexpected answer." );
2557  }
2558  }
2559 
2560  //--------------------------------------------------------------------------
2561  // Generate the client request
2562  //--------------------------------------------------------------------------
2563  Message *msg = new Message( sizeof(ClientAuthRequest)+credentials->size );
2564  msg->Zero();
2565  ClientRequest *req = (ClientRequest*)msg->GetBuffer();
2566  char *reqBuffer = msg->GetBuffer(sizeof(ClientAuthRequest));
2567 
2568  req->header.requestid = kXR_auth;
2569  req->auth.dlen = credentials->size;
2570  memcpy( req->auth.credtype, protocolName.c_str(),
2571  protocolName.length() > 4 ? 4 : protocolName.length() );
2572 
2573  memcpy( reqBuffer, credentials->buffer, credentials->size );
2574  hsData->out = msg;
2575  MarshallRequest( msg );
2576  delete credentials;
2577 
2578  //------------------------------------------------------------------------
2579  // Clear the SSL error queue of the calling thread, as there might be
2580  // some leftover from the authentication!
2581  //------------------------------------------------------------------------
2583 
2584  return XRootDStatus( stOK, suContinue );
2585  }
2586 
2587  //------------------------------------------------------------------------
2588  // Get the initial credentials using one of the protocols
2589  //------------------------------------------------------------------------
2590  XRootDStatus XRootDTransport::GetCredentials( XrdSecCredentials *&credentials,
2591  HandShakeData *hsData,
2592  XRootDChannelInfo *info )
2593  {
2594  //--------------------------------------------------------------------------
2595  // Set up the auth handler
2596  //--------------------------------------------------------------------------
2597  Log *log = DefaultEnv::GetLog();
2598  XrdOucErrInfo ei( "", info->authEnv);
2599  XrdSecGetProt_t authHandler = GetAuthHandler();
2600  if( !authHandler )
2601  return XRootDStatus( stFatal, errAuthFailed, 0, "Could not load authentication handler." );
2602 
2603  //--------------------------------------------------------------------------
2604  // Retrieve secuid and secgid, if available. These will override the fsuid
2605  // and fsgid of the current thread reading the credentials to prevent
2606  // security holes in case this process is running with elevated permissions.
2607  //--------------------------------------------------------------------------
2608  char *secuidc = (ei.getEnv()) ? ei.getEnv()->Get("xrdcl.secuid") : 0;
2609  char *secgidc = (ei.getEnv()) ? ei.getEnv()->Get("xrdcl.secgid") : 0;
2610 
2611  int secuid = -1;
2612  int secgid = -1;
2613 
2614  if(secuidc) secuid = atoi(secuidc);
2615  if(secgidc) secgid = atoi(secgidc);
2616 
2617 #ifdef __linux__
2618  ScopedFsUidSetter uidSetter(secuid, secgid, hsData->streamName);
2619  if(!uidSetter.IsOk()) {
2620  log->Error( XRootDTransportMsg, "[%s] Error while setting (fsuid, fsgid) to (%d, %d)",
2621  hsData->streamName.c_str(), secuid, secgid );
2622  return XRootDStatus( stFatal, errAuthFailed, 0, "Error while setting (fsuid, fsgid)." );
2623  }
2624 #else
2625  if(secuid >= 0 || secgid >= 0) {
2626  log->Error( XRootDTransportMsg, "[%s] xrdcl.secuid and xrdcl.secgid only supported on Linux.",
2627  hsData->streamName.c_str() );
2628  return XRootDStatus( stFatal, errAuthFailed, 0, "xrdcl.secuid and xrdcl.secgid"
2629  " only supported on Linux" );
2630  }
2631 #endif
2632 
2633  //--------------------------------------------------------------------------
2634  // Loop over the possible protocols to find one that gives us valid
2635  // credentials
2636  //--------------------------------------------------------------------------
2637  XrdNetAddr &srvAddrInfo = *const_cast<XrdNetAddr *>(hsData->serverAddr);
2638  srvAddrInfo.SetTLS( info->encrypted );
2639  while(1)
2640  {
2641  //------------------------------------------------------------------------
2642  // Get the protocol
2643  //------------------------------------------------------------------------
2644  info->authProtocol = (*authHandler)( hsData->url->GetHostName().c_str(),
2645  srvAddrInfo,
2646  *info->authParams,
2647  &ei );
2648  if( !info->authProtocol )
2649  {
2650  log->Error( XRootDTransportMsg, "[%s] No protocols left to try",
2651  hsData->streamName.c_str() );
2652  return XRootDStatus( stFatal, errAuthFailed, 0, "No protocols left to try" );
2653  }
2654 
2655  std::string protocolName = info->authProtocol->Entity.prot;
2656  log->Debug( XRootDTransportMsg, "[%s] Trying to authenticate using %s",
2657  hsData->streamName.c_str(), protocolName.c_str() );
2658 
2659  //------------------------------------------------------------------------
2660  // Get the credentials from the current protocol
2661  //------------------------------------------------------------------------
2662  credentials = info->authProtocol->getCredentials( 0, &ei );
2663  if( !credentials )
2664  {
2665  log->Debug( XRootDTransportMsg,
2666  "[%s] Cannot get credentials for protocol %s: %s",
2667  hsData->streamName.c_str(), protocolName.c_str(),
2668  ei.getErrText() );
2669  info->authProtocol->Delete();
2670  continue;
2671  }
2672  return XRootDStatus( stOK, suContinue );
2673  }
2674  }
2675 
2676  //------------------------------------------------------------------------
2677  // Clean up the data structures created for the authentication process
2678  //------------------------------------------------------------------------
2679  Status XRootDTransport::CleanUpAuthentication( XRootDChannelInfo *info )
2680  {
2681  if( info->authProtocol )
2682  info->authProtocol->Delete();
2683  delete info->authParams;
2684  delete info->authEnv;
2685  info->authProtocol = 0;
2686  info->authParams = 0;
2687  info->authEnv = 0;
2689  return Status();
2690  }
2691 
2692  //------------------------------------------------------------------------
2693  // Clean up the data structures created for the protection purposes
2694  //------------------------------------------------------------------------
2695  Status XRootDTransport::CleanUpProtection( XRootDChannelInfo *info )
2696  {
2697  XrdSysRWLockHelper scope( pSecUnloadHandler->lock );
2698  if( pSecUnloadHandler->unloaded ) return Status( stError, errInvalidOp );
2699 
2700  if( info->protection )
2701  {
2702  info->protection->Delete();
2703  info->protection = 0;
2704 
2705  CleanUpAuthentication( info );
2706  }
2707 
2708  if( info->protRespBody )
2709  {
2710  delete info->protRespBody;
2711  info->protRespBody = 0;
2712  info->protRespSize = 0;
2713  }
2714 
2715  return Status();
2716  }
2717 
2718  //----------------------------------------------------------------------------
2719  // Get the authentication function handle
2720  //----------------------------------------------------------------------------
2721  XrdSecGetProt_t XRootDTransport::GetAuthHandler()
2722  {
2723  Log *log = DefaultEnv::GetLog();
2724  char errorBuff[1024];
2725 
2726  // the static constructor is invoked only once and it is guaranteed that this
2727  // is thread safe
2728  static std::atomic<XrdSecGetProt_t> authHandler( XrdSecLoadSecFactory( errorBuff, 1024 ) );
2729  auto ret = authHandler.load( std::memory_order_relaxed );
2730  if( ret ) return ret;
2731 
2732  // if we are here it means we failed to load the security library for the
2733  // first time and we hope the environment changed
2734 
2735  // obtain a lock
2736  static XrdSysMutex mtx;
2737  XrdSysMutexHelper lck( mtx );
2738  // check if in the meanwhile some else didn't load the library
2739  ret = authHandler.load( std::memory_order_relaxed );
2740  if( ret ) return ret;
2741 
2742  // load the library
2743  ret = XrdSecLoadSecFactory( errorBuff, 1024 );
2744  authHandler.store( ret, std::memory_order_relaxed );
2745  // if we failed report an error
2746  if( !ret )
2747  {
2748  log->Error( XRootDTransportMsg,
2749  "Unable to get the security framework: %s", errorBuff );
2750  return 0;
2751  }
2752  return ret;
2753  }
2754 
2755  //----------------------------------------------------------------------------
2756  // Generate the end session message
2757  //----------------------------------------------------------------------------
2758  Message *XRootDTransport::GenerateEndSession( HandShakeData *hsData,
2759  XRootDChannelInfo *info )
2760  {
2761  Log *log = DefaultEnv::GetLog();
2762 
2763  //--------------------------------------------------------------------------
2764  // Generate the message
2765  //--------------------------------------------------------------------------
2766  Message *msg = new Message( sizeof(ClientEndsessRequest) );
2767  ClientEndsessRequest *endsessReq = (ClientEndsessRequest *)msg->GetBuffer();
2768 
2769  endsessReq->requestid = kXR_endsess;
2770  memcpy( endsessReq->sessid, info->oldSessionId, 16 );
2771  std::string sessId = Utils::Char2Hex( endsessReq->sessid, 16 );
2772 
2773  log->Debug( XRootDTransportMsg, "[%s] Sending out kXR_endsess for session:"
2774  " %s", hsData->streamName.c_str(), sessId.c_str() );
2775 
2776  MarshallRequest( msg );
2777 
2778  Message *sign = 0;
2779  GetSignature( msg, sign, info );
2780  if( sign )
2781  {
2782  //------------------------------------------------------------------------
2783  // Now place both the signature and the request in a single buffer
2784  //------------------------------------------------------------------------
2785  uint32_t size = sign->GetSize();
2786  sign->ReAllocate( size + msg->GetSize() );
2787  char* buffer = sign->GetBuffer( size );
2788  memcpy( buffer, msg->GetBuffer(), msg->GetSize() );
2789  msg->Grab( sign->GetBuffer(), sign->GetSize() );
2790  }
2791 
2792  return msg;
2793  }
2794 
2795  //----------------------------------------------------------------------------
2796  // Process the protocol response
2797  //----------------------------------------------------------------------------
2798  Status XRootDTransport::ProcessEndSessionResp( HandShakeData *hsData,
2799  XRootDChannelInfo *info )
2800  {
2801  Log *log = DefaultEnv::GetLog();
2802 
2803  Status st = UnMarshallBody( hsData->in, kXR_endsess );
2804  if( !st.IsOK() )
2805  return st;
2806 
2807  ServerResponse *rsp = (ServerResponse*)hsData->in->GetBuffer();
2808 
2809  // If we're good, we're good!
2810  if( rsp->hdr.status == kXR_ok )
2811  return Status();
2812 
2813  // we ignore not found errors as such an error means the connection
2814  // has been already terminated
2815  if( rsp->hdr.status == kXR_error && rsp->body.error.errnum == kXR_NotFound )
2816  return Status();
2817 
2818  // other errors
2819  if( rsp->hdr.status == kXR_error )
2820  {
2821  std::string errorMsg( rsp->body.error.errmsg, rsp->hdr.dlen - 4 );
2822  log->Error( XRootDTransportMsg, "[%s] Got error response to "
2823  "kXR_endsess: %s", hsData->streamName.c_str(),
2824  errorMsg.c_str() );
2825  return Status( stFatal, errHandShakeFailed );
2826  }
2827 
2828  // Wait Response.
2829  if( rsp->hdr.status == kXR_wait )
2830  {
2831  std::string msg( rsp->body.wait.infomsg, rsp->hdr.dlen - 4 );
2832  log->Info( XRootDTransportMsg, "[%s] Got wait response to "
2833  "kXR_endsess: %s", hsData->streamName.c_str(),
2834  msg.c_str() );
2835  hsData->out = GenerateEndSession( hsData, info );
2836  return Status( stOK, suRetry );
2837  }
2838 
2839  // Any other response is protocol violation
2840  return Status( stError, errDataError );
2841  }
2842 
2843  //----------------------------------------------------------------------------
2844  // Get a string representation of the server flags
2845  //----------------------------------------------------------------------------
2846  std::string XRootDTransport::ServerFlagsToStr( uint32_t flags )
2847  {
2848  std::string repr = "type: ";
2849  if( flags & kXR_isManager )
2850  repr += "manager ";
2851 
2852  else if( flags & kXR_isServer )
2853  repr += "server ";
2854 
2855  repr += "[";
2856 
2857  if( flags & kXR_attrMeta )
2858  repr += "meta ";
2859 
2860  else if( flags & kXR_attrCache )
2861  repr += "cache ";
2862 
2863  else if( flags & kXR_attrProxy )
2864  repr += "proxy ";
2865 
2866  else if( flags & kXR_attrSuper )
2867  repr += "super ";
2868 
2869  else
2870  repr += " ";
2871 
2872  repr.erase( repr.length()-1, 1 );
2873 
2874  repr += "]";
2875  return repr;
2876  }
2877 }
2878 
2879 namespace
2880 {
2881  // Extract file name from a request
2882  //----------------------------------------------------------------------------
2883  char *GetDataAsString( char *msg )
2884  {
2885  ClientRequestHdr *req = (ClientRequestHdr*)msg;
2886  char *fn = new char[req->dlen+1];
2887  memcpy( fn, msg + 24, req->dlen );
2888  fn[req->dlen] = 0;
2889  return fn;
2890  }
2891 }
2892 
2893 namespace XrdCl
2894 {
2895  //----------------------------------------------------------------------------
2896  // Get the description of a message
2897  //----------------------------------------------------------------------------
2898  void XRootDTransport::GenerateDescription( char *msg, std::ostringstream &o )
2899  {
2900  Log *log = DefaultEnv::GetLog();
2901  if( log->GetLevel() < Log::ErrorMsg )
2902  return;
2903 
2904  ClientRequestHdr *req = (ClientRequestHdr *)msg;
2905  switch( req->requestid )
2906  {
2907  //------------------------------------------------------------------------
2908  // kXR_open
2909  //------------------------------------------------------------------------
2910  case kXR_open:
2911  {
2912  ClientOpenRequest *sreq = (ClientOpenRequest *)msg;
2913  o << "kXR_open (";
2914  char *fn = GetDataAsString( msg );
2915  o << "file: " << fn << ", ";
2916  delete [] fn;
2917  o << "mode: 0" << std::setbase(8) << sreq->mode << ", ";
2918  o << std::setbase(10);
2919  o << "flags: ";
2920  if( sreq->options == 0 )
2921  o << "none";
2922  else
2923  {
2924  if( sreq->options & kXR_delete )
2925  o << "kXR_delete ";
2926  if( sreq->options & kXR_force )
2927  o << "kXR_force ";
2928  if( sreq->options & kXR_mkpath )
2929  o << "kXR_mkpath ";
2930  if( sreq->options & kXR_new )
2931  o << "kXR_new ";
2932  if( sreq->options & kXR_nowait )
2933  o << "kXR_delete ";
2934  if( sreq->options & kXR_open_apnd )
2935  o << "kXR_open_apnd ";
2936  if( sreq->options & kXR_open_read )
2937  o << "kXR_open_read ";
2938  if( sreq->options & kXR_open_updt )
2939  o << "kXR_open_updt ";
2940  if( sreq->options & kXR_posc )
2941  o << "kXR_posc ";
2942  if( sreq->options & kXR_refresh )
2943  o << "kXR_refresh ";
2944  if( sreq->options & kXR_replica )
2945  o << "kXR_replica ";
2946  if( sreq->options & kXR_seqio )
2947  o << "kXR_seqio ";
2948  if( sreq->options & kXR_async )
2949  o << "kXR_async ";
2950  if( sreq->options & kXR_retstat )
2951  o << "kXR_retstat ";
2952  }
2953  o << ")";
2954  break;
2955  }
2956 
2957  //------------------------------------------------------------------------
2958  // kXR_close
2959  //------------------------------------------------------------------------
2960  case kXR_close:
2961  {
2962  ClientCloseRequest *sreq = (ClientCloseRequest *)msg;
2963  o << "kXR_close (";
2964  o << "handle: " << FileHandleToStr( sreq->fhandle );
2965  o << ")";
2966  break;
2967  }
2968 
2969  //------------------------------------------------------------------------
2970  // kXR_stat
2971  //------------------------------------------------------------------------
2972  case kXR_stat:
2973  {
2974  ClientStatRequest *sreq = (ClientStatRequest *)msg;
2975  o << "kXR_stat (";
2976  if( sreq->dlen )
2977  {
2978  char *fn = GetDataAsString( msg );;
2979  o << "path: " << fn << ", ";
2980  delete [] fn;
2981  }
2982  else
2983  {
2984  o << "handle: " << FileHandleToStr( sreq->fhandle );
2985  o << ", ";
2986  }
2987  o << "flags: ";
2988  if( sreq->options == 0 )
2989  o << "none";
2990  else
2991  {
2992  if( sreq->options & kXR_vfs )
2993  o << "kXR_vfs";
2994  }
2995  o << ")";
2996  break;
2997  }
2998 
2999  //------------------------------------------------------------------------
3000  // kXR_read
3001  //------------------------------------------------------------------------
3002  case kXR_read:
3003  {
3004  ClientReadRequest *sreq = (ClientReadRequest *)msg;
3005  o << "kXR_read (";
3006  o << "handle: " << FileHandleToStr( sreq->fhandle );
3007  o << std::setbase(10);
3008  o << ", ";
3009  o << "offset: " << sreq->offset << ", ";
3010  o << "size: " << sreq->rlen << ")";
3011  break;
3012  }
3013 
3014  //------------------------------------------------------------------------
3015  // kXR_pgread
3016  //------------------------------------------------------------------------
3017  case kXR_pgread:
3018  {
3020  o << "kXR_pgread (";
3021  o << "handle: " << FileHandleToStr( sreq->fhandle );
3022  o << std::setbase(10);
3023  o << ", ";
3024  o << "offset: " << sreq->offset << ", ";
3025  o << "size: " << sreq->rlen << ")";
3026  break;
3027  }
3028 
3029  //------------------------------------------------------------------------
3030  // kXR_write
3031  //------------------------------------------------------------------------
3032  case kXR_write:
3033  {
3034  ClientWriteRequest *sreq = (ClientWriteRequest *)msg;
3035  o << "kXR_write (";
3036  o << "handle: " << FileHandleToStr( sreq->fhandle );
3037  o << std::setbase(10);
3038  o << ", ";
3039  o << "offset: " << sreq->offset << ", ";
3040  o << "size: " << sreq->dlen << ")";
3041  break;
3042  }
3043 
3044  //------------------------------------------------------------------------
3045  // kXR_pgwrite
3046  //------------------------------------------------------------------------
3047  case kXR_pgwrite:
3048  {
3050  o << "kXR_pgwrite (";
3051  o << "handle: " << FileHandleToStr( sreq->fhandle );
3052  o << std::setbase(10);
3053  o << ", ";
3054  o << "offset: " << sreq->offset << ", ";
3055  o << "size: " << sreq->dlen << ")";
3056  break;
3057  }
3058 
3059  //------------------------------------------------------------------------
3060  // kXR_sync
3061  //------------------------------------------------------------------------
3062  case kXR_sync:
3063  {
3064  ClientSyncRequest *sreq = (ClientSyncRequest *)msg;
3065  o << "kXR_sync (";
3066  o << "handle: " << FileHandleToStr( sreq->fhandle );
3067  o << ")";
3068  break;
3069  }
3070 
3071  //------------------------------------------------------------------------
3072  // kXR_truncate
3073  //------------------------------------------------------------------------
3074  case kXR_truncate:
3075  {
3077  o << "kXR_truncate (";
3078  if( !sreq->dlen )
3079  o << "handle: " << FileHandleToStr( sreq->fhandle );
3080  else
3081  {
3082  char *fn = GetDataAsString( msg );
3083  o << "file: " << fn;
3084  delete [] fn;
3085  }
3086  o << std::setbase(10);
3087  o << ", ";
3088  o << "offset: " << sreq->offset;
3089  o << ")";
3090  break;
3091  }
3092 
3093  //------------------------------------------------------------------------
3094  // kXR_readv
3095  //------------------------------------------------------------------------
3096  case kXR_readv:
3097  {
3098  unsigned char *fhandle = 0;
3099  o << "kXR_readv (";
3100 
3101  o << "handle: ";
3102  readahead_list *dataChunk = (readahead_list*)(msg + 24 );
3103  fhandle = dataChunk[0].fhandle;
3104  if( fhandle )
3105  o << FileHandleToStr( fhandle );
3106  else
3107  o << "unknown";
3108  o << ", ";
3109  o << std::setbase(10);
3110  o << "chunks: [";
3111  uint64_t size = 0;
3112  for( size_t i = 0; i < req->dlen/sizeof(readahead_list); ++i )
3113  {
3114  size += dataChunk[i].rlen;
3115  o << "(offset: " << dataChunk[i].offset;
3116  o << ", size: " << dataChunk[i].rlen << "); ";
3117  }
3118  o << "], ";
3119  o << "total size: " << size << ")";
3120  break;
3121  }
3122 
3123  //------------------------------------------------------------------------
3124  // kXR_writev
3125  //------------------------------------------------------------------------
3126  case kXR_writev:
3127  {
3128  unsigned char *fhandle = 0;
3129  o << "kXR_writev (";
3130 
3131  XrdProto::write_list *wrtList =
3132  reinterpret_cast<XrdProto::write_list*>( msg + 24 );
3133  uint64_t size = 0;
3134  uint32_t numChunks = 0;
3135  for( size_t i = 0; i < req->dlen/sizeof(XrdProto::write_list); ++i )
3136  {
3137  fhandle = wrtList[i].fhandle;
3138  size += wrtList[i].wlen;
3139  ++numChunks;
3140  }
3141  o << "handle: ";
3142  if( fhandle )
3143  o << FileHandleToStr( fhandle );
3144  else
3145  o << "unknown";
3146  o << ", ";
3147  o << std::setbase(10);
3148  o << "chunks: " << numChunks << ", ";
3149  o << "total size: " << size << ")";
3150  break;
3151  }
3152 
3153  //------------------------------------------------------------------------
3154  // kXR_locate
3155  //------------------------------------------------------------------------
3156  case kXR_locate:
3157  {
3159  char *fn = GetDataAsString( msg );;
3160  o << "kXR_locate (";
3161  o << "path: " << fn << ", ";
3162  delete [] fn;
3163  o << "flags: ";
3164  if( sreq->options == 0 )
3165  o << "none";
3166  else
3167  {
3168  if( sreq->options & kXR_refresh )
3169  o << "kXR_refresh ";
3170  if( sreq->options & kXR_prefname )
3171  o << "kXR_prefname ";
3172  if( sreq->options & kXR_nowait )
3173  o << "kXR_nowait ";
3174  if( sreq->options & kXR_force )
3175  o << "kXR_force ";
3176  if( sreq->options & kXR_compress )
3177  o << "kXR_compress ";
3178  }
3179  o << ")";
3180  break;
3181  }
3182 
3183  //------------------------------------------------------------------------
3184  // kXR_mv
3185  //------------------------------------------------------------------------
3186  case kXR_mv:
3187  {
3188  ClientMvRequest *sreq = (ClientMvRequest *)msg;
3189  o << "kXR_mv (";
3190  o << "source: ";
3191  o.write( msg + sizeof( ClientMvRequest ), sreq->arg1len );
3192  o << ", ";
3193  o << "destination: ";
3194  o.write( msg + sizeof( ClientMvRequest ) + sreq->arg1len + 1, sreq->dlen - sreq->arg1len - 1 );
3195  o << ")";
3196  break;
3197  }
3198 
3199  //------------------------------------------------------------------------
3200  // kXR_query
3201  //------------------------------------------------------------------------
3202  case kXR_query:
3203  {
3204  ClientQueryRequest *sreq = (ClientQueryRequest *)msg;
3205  o << "kXR_query (";
3206  o << "code: ";
3207  switch( sreq->infotype )
3208  {
3209  case kXR_Qconfig: o << "kXR_Qconfig"; break;
3210  case kXR_Qckscan: o << "kXR_Qckscan"; break;
3211  case kXR_Qcksum: o << "kXR_Qcksum"; break;
3212  case kXR_Qopaque: o << "kXR_Qopaque"; break;
3213  case kXR_Qopaquf: o << "kXR_Qopaquf"; break;
3214  case kXR_Qopaqug: o << "kXR_Qopaqug"; break;
3215  case kXR_QPrep: o << "kXR_QPrep"; break;
3216  case kXR_Qspace: o << "kXR_Qspace"; break;
3217  case kXR_QStats: o << "kXR_QStats"; break;
3218  case kXR_Qvisa: o << "kXR_Qvisa"; break;
3219  case kXR_Qxattr: o << "kXR_Qxattr"; break;
3220  default: o << sreq->infotype; break;
3221  }
3222  o << ", ";
3223 
3224  if( sreq->infotype == kXR_Qopaqug || sreq->infotype == kXR_Qvisa )
3225  {
3226  o << "handle: " << FileHandleToStr( sreq->fhandle );
3227  o << ", ";
3228  }
3229 
3230  o << "arg length: " << sreq->dlen << ")";
3231  break;
3232  }
3233 
3234  //------------------------------------------------------------------------
3235  // kXR_rm
3236  //------------------------------------------------------------------------
3237  case kXR_rm:
3238  {
3239  o << "kXR_rm (";
3240  char *fn = GetDataAsString( msg );;
3241  o << "path: " << fn << ")";
3242  delete [] fn;
3243  break;
3244  }
3245 
3246  //------------------------------------------------------------------------
3247  // kXR_mkdir
3248  //------------------------------------------------------------------------
3249  case kXR_mkdir:
3250  {
3251  ClientMkdirRequest *sreq = (ClientMkdirRequest *)msg;
3252  o << "kXR_mkdir (";
3253  char *fn = GetDataAsString( msg );
3254  o << "path: " << fn << ", ";
3255  delete [] fn;
3256  o << "mode: 0" << std::setbase(8) << sreq->mode << ", ";
3257  o << std::setbase(10);
3258  o << "flags: ";
3259  if( sreq->options[0] == 0 )
3260  o << "none";
3261  else
3262  {
3263  if( sreq->options[0] & kXR_mkdirpath )
3264  o << "kXR_mkdirpath";
3265  }
3266  o << ")";
3267  break;
3268  }
3269 
3270  //------------------------------------------------------------------------
3271  // kXR_rmdir
3272  //------------------------------------------------------------------------
3273  case kXR_rmdir:
3274  {
3275  o << "kXR_rmdir (";
3276  char *fn = GetDataAsString( msg );
3277  o << "path: " << fn << ")";
3278  delete [] fn;
3279  break;
3280  }
3281 
3282  //------------------------------------------------------------------------
3283  // kXR_chmod
3284  //------------------------------------------------------------------------
3285  case kXR_chmod:
3286  {
3287  ClientChmodRequest *sreq = (ClientChmodRequest *)msg;
3288  o << "kXR_chmod (";
3289  char *fn = GetDataAsString( msg );
3290  o << "path: " << fn << ", ";
3291  delete [] fn;
3292  o << "mode: 0" << std::setbase(8) << sreq->mode << ")";
3293  break;
3294  }
3295 
3296  //------------------------------------------------------------------------
3297  // kXR_ping
3298  //------------------------------------------------------------------------
3299  case kXR_ping:
3300  {
3301  o << "kXR_ping ()";
3302  break;
3303  }
3304 
3305  //------------------------------------------------------------------------
3306  // kXR_protocol
3307  //------------------------------------------------------------------------
3308  case kXR_protocol:
3309  {
3311  o << "kXR_protocol (";
3312  o << "clientpv: 0x" << std::setbase(16) << sreq->clientpv << ")";
3313  break;
3314  }
3315 
3316  //------------------------------------------------------------------------
3317  // kXR_dirlist
3318  //------------------------------------------------------------------------
3319  case kXR_dirlist:
3320  {
3321  o << "kXR_dirlist (";
3322  char *fn = GetDataAsString( msg );;
3323  o << "path: " << fn << ")";
3324  delete [] fn;
3325  break;
3326  }
3327 
3328  //------------------------------------------------------------------------
3329  // kXR_set
3330  //------------------------------------------------------------------------
3331  case kXR_set:
3332  {
3333  o << "kXR_set (";
3334  char *fn = GetDataAsString( msg );;
3335  o << "data: " << fn << ")";
3336  delete [] fn;
3337  break;
3338  }
3339 
3340  //------------------------------------------------------------------------
3341  // kXR_prepare
3342  //------------------------------------------------------------------------
3343  case kXR_prepare:
3344  {
3346  o << "kXR_prepare (";
3347  o << "flags: ";
3348 
3349  if( sreq->options == 0 )
3350  o << "none";
3351  else
3352  {
3353  if( sreq->options & kXR_stage )
3354  o << "kXR_stage ";
3355  if( sreq->options & kXR_wmode )
3356  o << "kXR_wmode ";
3357  if( sreq->options & kXR_coloc )
3358  o << "kXR_coloc ";
3359  if( sreq->options & kXR_fresh )
3360  o << "kXR_fresh ";
3361  }
3362 
3363  o << ", priority: " << (int) sreq->prty << ", ";
3364 
3365  char *fn = GetDataAsString( msg );
3366  char *cursor;
3367  for( cursor = fn; *cursor; ++cursor )
3368  if( *cursor == '\n' ) *cursor = ' ';
3369 
3370  o << "paths: " << fn << ")";
3371  delete [] fn;
3372  break;
3373  }
3374 
3375  case kXR_chkpoint:
3376  {
3378  o << "kXR_chkpoint (";
3379  o << "opcode: ";
3380  if( sreq->opcode == kXR_ckpBegin ) o << "kXR_ckpBegin)";
3381  else if( sreq->opcode == kXR_ckpCommit ) o << "kXR_ckpCommit)";
3382  else if( sreq->opcode == kXR_ckpQuery ) o << "kXR_ckpQuery)";
3383  else if( sreq->opcode == kXR_ckpRollback ) o << "kXR_ckpRollback)";
3384  else if( sreq->opcode == kXR_ckpXeq )
3385  {
3386  o << "kXR_ckpXeq) ";
3387  // In this case our request body will be one of kXR_pgwrite,
3388  // kXR_truncate, kXR_write, or kXR_writev request.
3389  GenerateDescription( msg + sizeof( ClientChkPointRequest ), o );
3390  }
3391 
3392  break;
3393  }
3394 
3395  //------------------------------------------------------------------------
3396  // Default
3397  //------------------------------------------------------------------------
3398  default:
3399  {
3400  o << "kXR_unknown (length: " << req->dlen << ")";
3401  break;
3402  }
3403  };
3404  }
3405 
3406  //----------------------------------------------------------------------------
3407  // Get a string representation of file handle
3408  //----------------------------------------------------------------------------
3409  std::string XRootDTransport::FileHandleToStr( const unsigned char handle[4] )
3410  {
3411  std::ostringstream o;
3412  o << "0x";
3413  for( uint8_t i = 0; i < 4; ++i )
3414  {
3415  o << std::setbase(16) << std::setfill('0') << std::setw(2);
3416  o << (int)handle[i];
3417  }
3418  return o.str();
3419  }
3420 }
kXR_int32 dlen
Definition: XProtocol.hh:171
static const int kXR_ckpRollback
Definition: XProtocol.hh:215
@ kXR_NotFound
Definition: XProtocol.hh:1001
kXR_int16 arg1len
Definition: XProtocol.hh:430
#define kXR_isManager
Definition: XProtocol.hh:1156
struct ClientTruncateRequest truncate
Definition: XProtocol.hh:875
union ServerResponse::@0 body
@ kXR_ecredir
Definition: XProtocol.hh:371
#define kXR_tlsLogin
Definition: XProtocol.hh:1184
#define kXR_suppgrw
Definition: XProtocol.hh:1174
kXR_int32 dlen
Definition: XProtocol.hh:182
kXR_char fhandle[4]
Definition: XProtocol.hh:531
kXR_unt16 requestid
Definition: XProtocol.hh:394
ServerResponseStatus status
Definition: XProtocol.hh:1309
kXR_char fhandle[4]
Definition: XProtocol.hh:782
#define kXR_gotoTLS
Definition: XProtocol.hh:1180
#define kXR_attrMeta
Definition: XProtocol.hh:1159
struct ClientPgReadRequest pgread
Definition: XProtocol.hh:861
kXR_char fhandle[4]
Definition: XProtocol.hh:807
#define kXR_haveTLS
Definition: XProtocol.hh:1179
kXR_char streamid[2]
Definition: XProtocol.hh:156
kXR_char fhandle[4]
Definition: XProtocol.hh:771
struct ClientMkdirRequest mkdir
Definition: XProtocol.hh:858
kXR_int32 dlen
Definition: XProtocol.hh:431
struct ClientAuthRequest auth
Definition: XProtocol.hh:847
kXR_int64 offset
Definition: XProtocol.hh:646
kXR_char streamid[2]
Definition: XProtocol.hh:914
kXR_unt16 options
Definition: XProtocol.hh:481
static const int kXR_ckpXeq
Definition: XProtocol.hh:216
struct ClientPgWriteRequest pgwrite
Definition: XProtocol.hh:862
#define kXR_attrSuper
Definition: XProtocol.hh:1161
struct ClientReadVRequest readv
Definition: XProtocol.hh:868
kXR_char pathid
Definition: XProtocol.hh:653
kXR_char credtype[4]
Definition: XProtocol.hh:170
kXR_char username[8]
Definition: XProtocol.hh:396
@ kXR_compress
Definition: XProtocol.hh:452
@ kXR_async
Definition: XProtocol.hh:458
@ kXR_delete
Definition: XProtocol.hh:453
@ kXR_prefname
Definition: XProtocol.hh:461
@ kXR_nowait
Definition: XProtocol.hh:467
@ kXR_open_read
Definition: XProtocol.hh:456
@ kXR_open_updt
Definition: XProtocol.hh:457
@ kXR_mkpath
Definition: XProtocol.hh:460
@ kXR_seqio
Definition: XProtocol.hh:468
@ kXR_replica
Definition: XProtocol.hh:465
@ kXR_posc
Definition: XProtocol.hh:466
@ kXR_refresh
Definition: XProtocol.hh:459
@ kXR_new
Definition: XProtocol.hh:455
@ kXR_force
Definition: XProtocol.hh:454
@ kXR_open_apnd
Definition: XProtocol.hh:462
@ kXR_retstat
Definition: XProtocol.hh:463
struct ClientOpenRequest open
Definition: XProtocol.hh:860
@ kXR_waitresp
Definition: XProtocol.hh:906
@ kXR_redirect
Definition: XProtocol.hh:904
@ kXR_status
Definition: XProtocol.hh:907
@ kXR_ok
Definition: XProtocol.hh:899
@ kXR_authmore
Definition: XProtocol.hh:902
@ kXR_attn
Definition: XProtocol.hh:901
@ kXR_wait
Definition: XProtocol.hh:905
@ kXR_error
Definition: XProtocol.hh:903
struct ServerResponseBody_Status bdy
Definition: XProtocol.hh:1261
struct ClientRequestHdr header
Definition: XProtocol.hh:846
kXR_char fhandle[4]
Definition: XProtocol.hh:509
kXR_unt16 infotype
Definition: XProtocol.hh:631
kXR_int32 fourth
Definition: XProtocol.hh:87
kXR_char fhandle[4]
Definition: XProtocol.hh:645
kXR_char fhandle[4]
Definition: XProtocol.hh:659
struct ClientWriteVRequest writev
Definition: XProtocol.hh:877
kXR_char fhandle[4]
Definition: XProtocol.hh:229
struct ClientLoginRequest login
Definition: XProtocol.hh:857
kXR_unt16 requestid
Definition: XProtocol.hh:157
kXR_char fhandle[4]
Definition: XProtocol.hh:633
kXR_char sessid[16]
Definition: XProtocol.hh:181
@ kXR_read
Definition: XProtocol.hh:125
@ kXR_open
Definition: XProtocol.hh:122
@ kXR_writev
Definition: XProtocol.hh:143
@ kXR_readv
Definition: XProtocol.hh:137
@ kXR_mkdir
Definition: XProtocol.hh:120
@ kXR_sync
Definition: XProtocol.hh:128
@ kXR_chmod
Definition: XProtocol.hh:114
@ kXR_bind
Definition: XProtocol.hh:136
@ kXR_dirlist
Definition: XProtocol.hh:116
@ kXR_rm
Definition: XProtocol.hh:126
@ kXR_query
Definition: XProtocol.hh:113
@ kXR_write
Definition: XProtocol.hh:131
@ kXR_login
Definition: XProtocol.hh:119
@ kXR_auth
Definition: XProtocol.hh:112
@ kXR_endsess
Definition: XProtocol.hh:135
@ kXR_set
Definition: XProtocol.hh:130
@ kXR_rmdir
Definition: XProtocol.hh:127
@ kXR_1stRequest
Definition: XProtocol.hh:111
@ kXR_truncate
Definition: XProtocol.hh:140
@ kXR_protocol
Definition: XProtocol.hh:118
@ kXR_mv
Definition: XProtocol.hh:121
@ kXR_ping
Definition: XProtocol.hh:123
@ kXR_stat
Definition: XProtocol.hh:129
@ kXR_pgread
Definition: XProtocol.hh:142
@ kXR_chkpoint
Definition: XProtocol.hh:124
@ kXR_locate
Definition: XProtocol.hh:139
@ kXR_close
Definition: XProtocol.hh:115
@ kXR_pgwrite
Definition: XProtocol.hh:138
@ kXR_prepare
Definition: XProtocol.hh:133
struct ClientChmodRequest chmod
Definition: XProtocol.hh:850
#define kXR_isServer
Definition: XProtocol.hh:1157
#define kXR_attrCache
Definition: XProtocol.hh:1158
kXR_int32 protover
Definition: XProtocol.hh:95
struct ClientQueryRequest query
Definition: XProtocol.hh:866
kXR_int32 dlen
Definition: XProtocol.hh:648
struct ClientReadRequest read
Definition: XProtocol.hh:867
struct ClientMvRequest mv
Definition: XProtocol.hh:859
kXR_int32 rlen
Definition: XProtocol.hh:660
kXR_unt16 requestid
Definition: XProtocol.hh:180
kXR_char sessid[16]
Definition: XProtocol.hh:259
struct ClientChkPointRequest chkpoint
Definition: XProtocol.hh:849
kXR_char fhandle[4]
Definition: XProtocol.hh:794
struct ServerResponseHeader hdr
Definition: XProtocol.hh:1260
kXR_unt16 mode
Definition: XProtocol.hh:480
@ kXR_asyncap
Definition: XProtocol.hh:378
#define kXR_attrProxy
Definition: XProtocol.hh:1160
kXR_char options[1]
Definition: XProtocol.hh:416
#define kXR_PROTOCOLVERSION
Definition: XProtocol.hh:70
static const int kXR_ckpCommit
Definition: XProtocol.hh:213
kXR_int64 offset
Definition: XProtocol.hh:661
@ kXR_vfs
Definition: XProtocol.hh:763
struct ClientPrepareRequest prepare
Definition: XProtocol.hh:864
@ kXR_mkdirpath
Definition: XProtocol.hh:410
@ kXR_wmode
Definition: XProtocol.hh:591
@ kXR_fresh
Definition: XProtocol.hh:593
@ kXR_coloc
Definition: XProtocol.hh:592
@ kXR_stage
Definition: XProtocol.hh:590
static const int kXR_ckpQuery
Definition: XProtocol.hh:214
#define kXR_tlsSess
Definition: XProtocol.hh:1185
#define kXR_DataServer
Definition: XProtocol.hh:1150
kXR_int64 offset
Definition: XProtocol.hh:808
struct ClientWriteRequest write
Definition: XProtocol.hh:876
#define kXR_PROTTLSVERSION
Definition: XProtocol.hh:72
kXR_int32 dlen
Definition: XProtocol.hh:772
kXR_char options
Definition: XProtocol.hh:769
kXR_char capver[1]
Definition: XProtocol.hh:399
kXR_int32 rlen
Definition: XProtocol.hh:647
struct ClientProtocolRequest protocol
Definition: XProtocol.hh:865
@ kXR_QPrep
Definition: XProtocol.hh:616
@ kXR_Qopaqug
Definition: XProtocol.hh:625
@ kXR_Qconfig
Definition: XProtocol.hh:621
@ kXR_Qopaquf
Definition: XProtocol.hh:624
@ kXR_Qckscan
Definition: XProtocol.hh:620
@ kXR_Qxattr
Definition: XProtocol.hh:618
@ kXR_Qspace
Definition: XProtocol.hh:619
@ kXR_Qvisa
Definition: XProtocol.hh:622
@ kXR_QStats
Definition: XProtocol.hh:615
@ kXR_Qcksum
Definition: XProtocol.hh:617
@ kXR_Qopaque
Definition: XProtocol.hh:623
struct ClientLocateRequest locate
Definition: XProtocol.hh:856
@ kXR_ver005
Definition: XProtocol.hh:389
kXR_int32 msgval
Definition: XProtocol.hh:96
#define kXR_tlsData
Definition: XProtocol.hh:1182
@ kXR_readrdok
Definition: XProtocol.hh:360
@ kXR_fullurl
Definition: XProtocol.hh:358
@ kXR_onlyprv4
Definition: XProtocol.hh:362
@ kXR_lclfile
Definition: XProtocol.hh:364
@ kXR_multipr
Definition: XProtocol.hh:359
@ kXR_redirflags
Definition: XProtocol.hh:365
@ kXR_hasipv64
Definition: XProtocol.hh:361
@ kXR_onlyprv6
Definition: XProtocol.hh:363
kXR_int32 dlen
Definition: XProtocol.hh:159
ServerResponseHeader hdr
Definition: XProtocol.hh:1287
static const int kXR_ckpBegin
Definition: XProtocol.hh:212
long long kXR_int64
Definition: XPtypes.hh:98
unsigned char kXR_char
Definition: XPtypes.hh:65
XrdVERSIONINFOREF(XrdCl)
XrdSecBuffer XrdSecParameters
XrdSecProtocol *(* XrdSecGetProt_t)(const char *hostname, XrdNetAddrInfo &endPoint, XrdSecParameters &sectoken, XrdOucErrInfo *einfo)
Typedef to simplify the encoding of methods returning XrdSecProtocol.
XrdSecGetProt_t XrdSecLoadSecFactory(char *eBuff, int eBlen, const char *seclib)
int XrdSecGetProtection(XrdSecProtect *&protP, XrdSecProtocol &aprot, ServerResponseBody_Protocol &resp, unsigned int resplen)
#define NEED2SECURE(protP)
This class implements the XRootD protocol security protection.
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
void Set(Type object, bool own=true)
void Get(Type &object)
Retrieve the object being held.
void AdvanceCursor(uint32_t delta)
Advance the cursor.
Definition: XrdClBuffer.hh:156
void Grab(char *buffer, uint32_t size)
Grab a buffer allocated outside.
Definition: XrdClBuffer.hh:228
void Zero()
Zero.
Definition: XrdClBuffer.hh:124
const char * GetBuffer(uint32_t offset=0) const
Get the message buffer.
Definition: XrdClBuffer.hh:72
void ReAllocate(uint32_t size)
Reallocate the buffer to a new location of a given size.
Definition: XrdClBuffer.hh:88
void Allocate(uint32_t size)
Allocate the buffer.
Definition: XrdClBuffer.hh:110
uint32_t GetCursor() const
Get append cursor.
Definition: XrdClBuffer.hh:140
uint32_t GetSize() const
Get the size of the message.
Definition: XrdClBuffer.hh:132
char * GetBufferAtCursor()
Get the buffer pointer at the append cursor.
Definition: XrdClBuffer.hh:189
static TransportManager * GetTransportManager()
Get transport manager.
static Log * GetLog()
Get default log.
static Env * GetEnv()
Get default client environment.
bool PutInt(const std::string &key, int value)
Definition: XrdClEnv.cc:110
bool GetInt(const std::string &key, int &value)
Definition: XrdClEnv.cc:89
Handle diagnostics.
Definition: XrdClLog.hh:101
@ ErrorMsg
report errors
Definition: XrdClLog.hh:109
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
LogLevel GetLevel() const
Get the log level.
Definition: XrdClLog.hh:258
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
Definition: XrdClLog.cc:299
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition: XrdClLog.cc:282
The message representation used throughout the system.
Definition: XrdClMessage.hh:32
void SetIsMarshalled(bool isMarshalled)
Set the marshalling status.
Definition: XrdClMessage.hh:81
bool IsMarshalled() const
Check if the message is marshalled.
Definition: XrdClMessage.hh:73
static SIDMgrPool & Instance()
std::shared_ptr< SIDManager > GetSIDMgr(const URL &url)
A network socket.
Definition: XrdClSocket.hh:43
virtual XRootDStatus Read(char *buffer, size_t size, int &bytesRead)
Definition: XrdClSocket.cc:740
static void ClearErrorQueue()
Clear the error queue for the calling thread.
Definition: XrdClTls.cc:422
Perform the handshake and the authentication for each physical stream.
@ RequestClose
Send a close request.
virtual void WaitBeforeExit()=0
Wait before exit.
Manage transport handler objects.
TransportHandler * GetHandler(const std::string &protocol)
Get a transport handler object for a given protocol.
URL representation.
Definition: XrdClURL.hh:31
std::string GetChannelId() const
Definition: XrdClURL.cc:505
std::map< std::string, std::string > ParamsMap
Definition: XrdClURL.hh:33
bool IsSecure() const
Does the protocol indicate encryption.
Definition: XrdClURL.cc:475
bool IsTPC() const
Is the URL used in TPC context.
Definition: XrdClURL.cc:483
std::string GetLoginToken() const
Get the login token if present in the opaque info.
Definition: XrdClURL.cc:360
static std::string TimeToString(time_t timestamp)
Convert timestamp to a string.
Definition: XrdClUtils.cc:256
static std::string FQDNToCC(const std::string &fqdn)
Convert the fully qualified host name to country code.
Definition: XrdClUtils.cc:490
static std::string Char2Hex(uint8_t *array, uint16_t size)
Print a char array as hex.
Definition: XrdClUtils.cc:635
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
Definition: XrdClUtils.hh:56
const std::string & GetErrorMessage() const
Get error message.
static uint16_t NbConnectedStrm(AnyObject &channelData)
Number of currently connected data streams.
virtual bool IsStreamTTLElapsed(time_t time, AnyObject &channelData)
Check if the stream should be disconnected.
virtual void Disconnect(AnyObject &channelData, uint16_t subStreamId)
The stream has been disconnected, do the cleanups.
virtual uint32_t MessageReceived(Message &msg, uint16_t subStream, AnyObject &channelData)
Check if the message invokes a stream action.
virtual void WaitBeforeExit()
Wait until the program can safely exit.
static XRootDStatus UnMarshallBody(Message *msg, uint16_t reqType)
Unmarshall the body of the incoming message.
virtual XRootDStatus GetBody(Message &message, Socket *socket)
virtual XRootDStatus GetHeader(Message &message, Socket *socket)
virtual uint16_t SubStreamNumber(AnyObject &channelData)
Return a number of substreams per stream that should be created.
virtual void FinalizeChannel(AnyObject &channelData)
Finalize channel.
virtual bool HandShakeDone(HandShakeData *handShakeData, AnyObject &channelData)
virtual Status GetSignature(Message *toSign, Message *&sign, AnyObject &channelData)
Get signature for given message.
virtual void MessageSent(Message *msg, uint16_t subStream, uint32_t bytesSent, AnyObject &channelData)
Notify the transport about a message having been sent.
virtual XRootDStatus HandShake(HandShakeData *handShakeData, AnyObject &channelData)
HandShake.
virtual XRootDStatus GetMore(Message &message, Socket *socket)
static void GenerateDescription(char *msg, std::ostringstream &o)
Get the description of a message.
static XRootDStatus UnMarshallRequest(Message *msg)
static XRootDStatus UnMarchalStatusMore(Message &msg)
Unmarshall the correction-segment of the status response for pgwrite.
static void LogErrorResponse(const Message &msg)
Log server error response.
virtual void DecFileInstCnt(AnyObject &channelData)
Decrement file object instance count bound to this channel.
virtual PathID Multiplex(Message *msg, AnyObject &channelData, PathID *hint=0)
virtual void InitializeChannel(const URL &url, AnyObject &channelData)
Initialize channel.
virtual Status Query(uint16_t query, AnyObject &result, AnyObject &channelData)
Query the channel.
static void UnMarshallHeader(Message &msg)
Unmarshall the header incoming message.
static XRootDStatus UnMarshalStatusBody(Message &msg, uint16_t reqType)
Unmarshall the body of the status response.
static XRootDStatus MarshallRequest(Message *msg)
Marshal the outgoing message.
virtual URL GetBindPreference(const URL &url, AnyObject &channelData)
Get bind preference for the next data stream.
virtual PathID MultiplexSubStream(Message *msg, AnyObject &channelData, PathID *hint=0)
virtual bool NeedEncryption(HandShakeData *handShakeData, AnyObject &channelData)
virtual Status IsStreamBroken(time_t inactiveTime, AnyObject &channelData)
void SetTLS(bool val)
Definition: XrdNetAddr.cc:590
static char * MyHostName(const char *eName="*unknown*", const char **eText=0)
Definition: XrdNetUtils.cc:667
static NetProt NetConfig(NetType netquery=qryINET, const char **eText=0)
Definition: XrdNetUtils.cc:681
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
Definition: XrdOucCRC.cc:190
static int UserName(uid_t uID, char *uName, int uNsz)
virtual int Secure(SecurityRequest *&newreq, ClientRequest &thereq, const char *thedata)
static int TimeZone()
Definition: XrdSysTimer.cc:210
const uint16_t suRetry
Definition: XrdClStatus.hh:40
const uint16_t errQueryNotSupported
Definition: XrdClStatus.hh:89
const int DefaultLoadBalancerTTL
const uint64_t XRootDTransportMsg
const uint16_t errTlsError
Definition: XrdClStatus.hh:80
const uint16_t stFatal
Fatal error, it's still an error.
Definition: XrdClStatus.hh:33
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
const uint16_t errLoginFailed
Definition: XrdClStatus.hh:87
const int DefaultWantTlsOnNoPgrw
const uint16_t errSocketTimeout
Definition: XrdClStatus.hh:73
const uint64_t XRootDMsg
const uint16_t errDataError
data is corrupted
Definition: XrdClStatus.hh:63
const uint16_t errInternal
Internal error.
Definition: XrdClStatus.hh:56
const uint16_t stOK
Everything went OK.
Definition: XrdClStatus.hh:31
const int DefaultSubStreamsPerChannel
const uint16_t errInvalidOp
Definition: XrdClStatus.hh:51
const int DefaultDataServerTTL
const uint16_t errHandShakeFailed
Definition: XrdClStatus.hh:86
const int DefaultStreamTimeout
const uint16_t suAlreadyDone
Definition: XrdClStatus.hh:42
const uint16_t errNotSupported
Definition: XrdClStatus.hh:62
const uint16_t suDone
Definition: XrdClStatus.hh:38
const uint16_t suContinue
Definition: XrdClStatus.hh:39
bool InitTLS()
Definition: XrdClTls.cc:96
const int DefaultTlsNoData
const int DefaultNoTlsOK
const uint16_t errAuthFailed
Definition: XrdClStatus.hh:88
const uint16_t errInvalidMessage
Definition: XrdClStatus.hh:85
XrdSysError Log
Definition: XrdConfig.cc:112
kXR_char fhandle[4]
Definition: XProtocol.hh:832
struct ServerResponseBifs_Protocol bifReqs
Definition: XProtocol.hh:1120
BindPrefSelector(std::vector< std::string > &&bindprefs)
const std::string & Get()
Data structure that carries the handshake information.
std::string streamName
Name of the stream.
uint16_t subStreamId
Sub-stream id.
Message * out
Message to be sent out.
static void UnloadHandler(const std::string &trProt)
void Register(const std::string &protocol)
std::set< std::string > protocols
Procedure execution status.
Definition: XrdClStatus.hh:115
uint16_t code
Error type, or additional hints on what to do.
Definition: XrdClStatus.hh:147
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124
Selects less loaded stream for read operation over multiple streams.
void AdjustQueues(uint16_t size)
void MsgReceived(uint16_t substrm)
uint16_t Select(const std::vector< bool > &connected)
static const uint16_t Name
Transport name, returns const char *.
static const uint16_t Auth
Transport name, returns std::string *.
Information holder for xrootd channels.
std::vector< XRootDStreamInfo > StreamInfoVector
std::set< uint16_t > sentCloses
std::unique_ptr< StreamSelector > strmSelector
std::unique_ptr< BindPrefSelector > bindSelector
std::atomic< uint32_t > finstcnt
ServerResponseBody_Protocol * protRespBody
std::set< uint16_t > sentOpens
std::shared_ptr< SIDManager > sidManager
static const uint16_t ServerFlags
returns server flags
static const uint16_t ProtocolVersion
returns the protocol version
static const uint16_t IsEncrypted
returns true if the channel is encrypted
Information holder for XRootDStreams.
Generic structure to pass security information back and forth.
char * buffer
Pointer to the buffer.
int size
Size of the buffer or length of data in the buffer.