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