XRootD
XrdClSocket.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // XRootD is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // XRootD is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
17 //------------------------------------------------------------------------------
18 
19 #include "XrdCl/XrdClSocket.hh"
20 #include "XrdCl/XrdClUtils.hh"
21 #include "XrdCl/XrdClConstants.hh"
22 #include "XrdCl/XrdClMessage.hh"
23 #include "XrdCl/XrdClDefaultEnv.hh"
24 #include "XrdCl/XrdClTls.hh"
25 #include "XrdNet/XrdNetConnect.hh"
26 #include "XrdSys/XrdSysFD.hh"
27 
28 #include <arpa/inet.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <poll.h>
32 #include <ctime>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <signal.h>
36 #include <cstdlib>
37 #include <cstring>
38 #include <sys/uio.h>
39 #include <netinet/tcp.h>
40 #include <stdexcept>
41 
42 namespace XrdCl
43 {
44  Socket::Socket( int socket, SocketStatus status ):
45  pSocket(socket), pStatus( status ),
46  pProtocolFamily( AF_INET ),
47  pChannelID( 0 ),
48  pCorked( false )
49  {
50  };
51 
52  //------------------------------------------------------------------------
53  // Desctuctor
54  //------------------------------------------------------------------------
56  {
57  Close();
58  };
59 
60  //----------------------------------------------------------------------------
61  // Initialize
62  //----------------------------------------------------------------------------
64  {
65  if( pSocket != -1 )
67 
68  pSocket = XrdSysFD_Socket( family, SOCK_STREAM, 0 );
69  if( pSocket < 0 )
70  {
71  pSocket = -1;
73  }
74 
75  pProtocolFamily = family;
76 
77  //--------------------------------------------------------------------------
78  // Make the socket non blocking and disable the Nagle algorithm since
79  // we will be using this for transmitting messages not handling streams
80  //--------------------------------------------------------------------------
81  int flags;
82  if( (flags = ::fcntl( pSocket, F_GETFL, 0 )) == -1 )
83  flags = 0;
84  if( ::fcntl( pSocket, F_SETFL, flags | O_NONBLOCK | O_NDELAY ) == -1 )
85  {
86  Close();
87  return XRootDStatus( stError, errFcntl, errno );
88  }
89 
91  flags = DefaultNoDelay;
92  env->GetInt( "NoDelay", flags );
93  if( setsockopt( pSocket, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof( int ) ) < 0 )
94  {
95  Close();
96  return XRootDStatus( stError, errFcntl, errno );
97  }
98 
99  //--------------------------------------------------------------------------
100  // We use send with MSG_NOSIGNAL to avoid SIGPIPEs on Linux, on MacOSX
101  // we set SO_NOSIGPIPE option, on Solaris we ignore the SIGPIPE
102  //--------------------------------------------------------------------------
103 #ifdef __APPLE__
104  int set = 1;
105  XRootDStatus st = SetSockOpt( SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(int) );
106  if( !st.IsOK() )
107  {
108  Close();
109  return st;
110  }
111 #elif __solaris__
112  struct sigaction act;
113  act.sa_handler = SIG_IGN;
114  sigaction( SIGPIPE, &act, NULL );
115 #endif
116 
117  return XRootDStatus();
118  }
119 
120  //----------------------------------------------------------------------------
121  // Set the socket flags
122  //----------------------------------------------------------------------------
124  {
125  if( pSocket == -1 )
126  return XRootDStatus( stError, errInvalidOp );
127 
128  int st = ::fcntl( pSocket, F_SETFL, flags );
129  if( st == -1 )
130  return XRootDStatus( stError, errSocketError, errno );
131  return XRootDStatus();
132  }
133 
134  //----------------------------------------------------------------------------
135  // Get the socket flags
136  //----------------------------------------------------------------------------
138  {
139  if( pSocket == -1 )
140  return XRootDStatus( stError, errInvalidOp );
141 
142  int st = ::fcntl( pSocket, F_GETFL, 0 );
143  if( st == -1 )
144  return XRootDStatus( stError, errSocketError, errno );
145  flags = st;
146  return XRootDStatus();
147  }
148 
149  //----------------------------------------------------------------------------
150  // Get socket options
151  //----------------------------------------------------------------------------
152  XRootDStatus Socket::GetSockOpt( int level, int optname, void *optval,
153  socklen_t *optlen )
154  {
155  if( pSocket == -1 )
156  return XRootDStatus( stError, errInvalidOp );
157 
158  if( ::getsockopt( pSocket, level, optname, optval, optlen ) != 0 )
159  return XRootDStatus( stError, errSocketOptError, errno );
160 
161  return XRootDStatus();
162  }
163 
164  //------------------------------------------------------------------------
165  // Set socket options
166  //------------------------------------------------------------------------
167  XRootDStatus Socket::SetSockOpt( int level, int optname, const void *optval,
168  socklen_t optlen )
169  {
170  if( pSocket == -1 )
171  return XRootDStatus( stError, errInvalidOp );
172 
173  if( ::setsockopt( pSocket, level, optname, optval, optlen ) != 0 )
174  return XRootDStatus( stError, errSocketOptError, errno );
175 
176  return XRootDStatus();
177  }
178 
179 
180  //----------------------------------------------------------------------------
181  // Connect to the given host name
182  //----------------------------------------------------------------------------
183  XRootDStatus Socket::Connect( const std::string &host,
184  uint16_t port,
185  uint16_t timeout )
186  {
187  if( pSocket == -1 || pStatus == Connected || pStatus == Connecting )
188  return XRootDStatus( stError, errInvalidOp );
189 
190  std::vector<XrdNetAddr> addrs;
191  std::ostringstream o; o << host << ":" << port;
192  XRootDStatus st;
193 
194  if( pProtocolFamily == AF_INET6 )
195  st = Utils::GetHostAddresses( addrs, URL( o.str() ), Utils::IPAll );
196  else
197  st = Utils::GetHostAddresses( addrs, URL( o.str() ), Utils::IPv4 );
198 
199  if( !st.IsOK() )
200  return st;
201 
203  addrs );
204 
205 
206  return ConnectToAddress( addrs[0], timeout );
207  }
208 
209  //----------------------------------------------------------------------------
210  // Connect to the given host
211  //----------------------------------------------------------------------------
213  uint16_t timeout )
214  {
215  if( pSocket == -1 || pStatus == Connected || pStatus == Connecting )
216  return XRootDStatus( stError, errInvalidOp );
217 
218  pServerAddr.reset( new XrdNetAddr( addr ) );;
219 
220  //--------------------------------------------------------------------------
221  // Make sure TLS is off when the physical connection is newly established
222  //--------------------------------------------------------------------------
223  pTls.reset();
224 
225  //--------------------------------------------------------------------------
226  // Connect
227  //--------------------------------------------------------------------------
228  int status = XrdNetConnect::Connect( pSocket, pServerAddr->SockAddr(),
229  pServerAddr->SockSize(), timeout );
230  if( status != 0 )
231  {
232  XRootDStatus st( stError );
233 
234  //------------------------------------------------------------------------
235  // If we connect asynchronously this is not really an error
236  //------------------------------------------------------------------------
237  if( !timeout && status == EINPROGRESS )
238  {
240  return XRootDStatus();
241  }
242 
243  //------------------------------------------------------------------------
244  // Errors
245  //------------------------------------------------------------------------
246  else if( status == ETIMEDOUT )
247  st.code = errSocketTimeout;
248  else
249  st.code = errSocketError;
250  st.errNo = status;
251 
252  Close();
253  return st;
254  }
255  pStatus = Connected;
256  return XRootDStatus();
257  }
258 
259  //----------------------------------------------------------------------------
260  // Disconnect
261  //----------------------------------------------------------------------------
263  {
264  if( pTls ) pTls->Shutdown();
265 
266  if( pSocket != -1 )
267  {
268  close( pSocket );
270  pSocket = -1;
271  pSockName = "";
272  pPeerName = "";
273  pName = "";
274  }
275  }
276 
277  //----------------------------------------------------------------------------
279  //----------------------------------------------------------------------------
280  XRootDStatus Socket::ReadRaw( void *buffer, uint32_t size, int32_t timeout,
281  uint32_t &bytesRead )
282  {
283  //--------------------------------------------------------------------------
284  // Check if we're connected
285  //--------------------------------------------------------------------------
286  if( pStatus != Connected )
287  return XRootDStatus( stError, errInvalidOp );
288 
289  //--------------------------------------------------------------------------
290  // Some useful variables
291  //--------------------------------------------------------------------------
292  bytesRead = 0;
293 
294  char *current = (char *)buffer;
295  bool useTimeout = (timeout!=-1);
296  time_t now = 0;
297  time_t newNow = 0;
298  XRootDStatus sc;
299 
300  if( useTimeout )
301  now = ::time(0);
302 
303  //--------------------------------------------------------------------------
304  // Repeat the following until we have read all the requested data
305  //--------------------------------------------------------------------------
306  while ( bytesRead < size )
307  {
308  //------------------------------------------------------------------------
309  // Check if we can read something
310  //------------------------------------------------------------------------
311  sc = Poll( true, false, useTimeout ? timeout : -1 );
312 
313  //------------------------------------------------------------------------
314  // It looks like we've got an event. Let's check if we can read something.
315  //------------------------------------------------------------------------
316  if( sc.status == stOK )
317  {
318  ssize_t n = ::read( pSocket, current, (size-bytesRead) );
319 
320  if( n > 0 )
321  {
322  bytesRead += n;
323  current += n;
324  }
325 
326  //----------------------------------------------------------------------
327  // We got a close here - this means that there is no more data in
328  // the buffer so we disconnect
329  //----------------------------------------------------------------------
330  if( n == 0 )
331  {
332  Close();
334  }
335 
336  //----------------------------------------------------------------------
337  // Error
338  //----------------------------------------------------------------------
339  if( (n < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) )
340  {
341  Close();
342  return XRootDStatus( stError, errSocketError, errno );
343  }
344  }
345  else
346  {
347  Close();
348  return sc;
349  }
350 
351  //------------------------------------------------------------------------
352  // Do we still have time to wait for data?
353  //------------------------------------------------------------------------
354  if( useTimeout )
355  {
356  newNow = ::time(0);
357  timeout -= (newNow-now);
358  now = newNow;
359  if( timeout < 0 )
360  break;
361  }
362  }
363 
364  //--------------------------------------------------------------------------
365  // Have we managed to read everything?
366  //--------------------------------------------------------------------------
367  if( bytesRead < size )
369  return XRootDStatus( stOK );
370  }
371 
372  //----------------------------------------------------------------------------
373  // Write raw bytes to the socket
374  //----------------------------------------------------------------------------
375  XRootDStatus Socket::WriteRaw( void *buffer, uint32_t size, int32_t timeout,
376  uint32_t &bytesWritten )
377  {
378  //--------------------------------------------------------------------------
379  // Check if we're connected
380  //--------------------------------------------------------------------------
381  if( pStatus != Connected )
382  return XRootDStatus( stError, errInvalidOp );
383 
384  //--------------------------------------------------------------------------
385  // Some useful variables
386  //--------------------------------------------------------------------------
387  bytesWritten = 0;
388 
389  char *current = (char *)buffer;
390  bool useTimeout = (timeout!=-1);
391  time_t now = 0;
392  time_t newNow = 0;
393  XRootDStatus sc;
394 
395  if( useTimeout )
396  now = ::time(0);
397 
398  //--------------------------------------------------------------------------
399  // Repeat the following until we have written everything
400  //--------------------------------------------------------------------------
401  while ( bytesWritten < size )
402  {
403  //------------------------------------------------------------------------
404  // Check if we can read something
405  //------------------------------------------------------------------------
406  sc = Poll( false, true, useTimeout ? timeout : -1 );
407 
408  //------------------------------------------------------------------------
409  // Let's write
410  //------------------------------------------------------------------------
411  if( sc.status == stOK )
412  {
413  ssize_t n = ::write( pSocket, current, (size-bytesWritten) );
414 
415  if( n > 0 )
416  {
417  bytesWritten += n;
418  current += n;
419  }
420 
421  //----------------------------------------------------------------------
422  // Error
423  //----------------------------------------------------------------------
424  if( (n <= 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) )
425  {
426  Close();
427  return XRootDStatus( stError, errSocketError, errno );
428  }
429  }
430  else
431  {
432  Close();
433  return sc;
434  }
435 
436  //------------------------------------------------------------------------
437  // Do we still have time to wait for data?
438  //------------------------------------------------------------------------
439  if( useTimeout )
440  {
441  newNow = ::time(0);
442  timeout -= (newNow-now);
443  now = newNow;
444  if( timeout < 0 )
445  break;
446  }
447  }
448 
449  //--------------------------------------------------------------------------
450  // Have we managed to read everything?
451  //--------------------------------------------------------------------------
452  if( bytesWritten < size )
454 
455  return XRootDStatus( stOK );
456  }
457 
458  //------------------------------------------------------------------------
459  // Portable wrapper around SIGPIPE free send
460  //----------------------------------------------------------------------------
461  XRootDStatus Socket::Send( const char *buffer, size_t size, int &bytesWritten )
462  {
463  if( pTls ) return pTls->Send( buffer, size, bytesWritten );
464 
465  //--------------------------------------------------------------------------
466  // We use send with MSG_NOSIGNAL to avoid SIGPIPEs on Linux
467  //--------------------------------------------------------------------------
468 #if defined(__linux__) || defined(__GNU__) || (defined(__FreeBSD_kernel__) && defined(__GLIBC__))
469  int status = ::send( pSocket, buffer, size, MSG_NOSIGNAL );
470 #else
471  int status = ::write( pSocket, buffer, size );
472 #endif
473 
474  if( status <= 0 )
475  return ClassifyErrno( errno );
476 
477  bytesWritten = status;
478  return XRootDStatus();
479  }
480 
481  //------------------------------------------------------------------------
486  //------------------------------------------------------------------------
487  XRootDStatus Socket::Send( XrdSys::KernelBuffer &kbuff, int &bytesWritten )
488  {
489  if( pTls ) return XRootDStatus( stError, errNotSupported, 0,
490  "Cannot send a kernel-buffer over TLS." );
491 
492  ssize_t status = XrdSys::Send( pSocket, kbuff );
493 
494  if( status <= 0 )
495  return ClassifyErrno( errno );
496  bytesWritten += status;
497  return XRootDStatus();
498  }
499 
500  //------------------------------------------------------------------------
501  // Write message to the socket
502  //------------------------------------------------------------------------
503  XRootDStatus Socket::Send( Message &msg, const std::string &strmname )
504  {
505  //----------------------------------------------------------------------
506  // Try to write down the current message
507  //----------------------------------------------------------------------
508  size_t btsleft = msg.GetSize() - msg.GetCursor();
509  if( !btsleft ) return XRootDStatus();
510 
511  while( btsleft )
512  {
513  int wrtcnt = 0;
514  XRootDStatus st = Send( msg.GetBufferAtCursor(), btsleft, wrtcnt );
515 
516  if( !st.IsOK() )
517  {
518  msg.SetCursor( 0 );
519  return st;
520  }
521 
522  if( st.code == suRetry ) return st;
523 
524  msg.AdvanceCursor( wrtcnt );
525  btsleft -= wrtcnt;
526  }
527 
528  //----------------------------------------------------------------------
529  // We have written the message successfully
530  //----------------------------------------------------------------------
531  Log *log = DefaultEnv::GetLog();
532  log->Dump( AsyncSockMsg, "[%s] Wrote a message: %s (%p), %d bytes",
533  strmname.c_str(), msg.GetObfuscatedDescription().c_str(),
534  &msg, msg.GetSize() );
535  return XRootDStatus();
536  }
537 
538  //----------------------------------------------------------------------------
539  // Poll the descriptor
540  //----------------------------------------------------------------------------
541  XRootDStatus Socket::Poll( bool readyForReading, bool readyForWriting,
542  int32_t timeout )
543  {
544  //--------------------------------------------------------------------------
545  // Check if we're connected
546  //--------------------------------------------------------------------------
547  if( pStatus != Connected )
548  return XRootDStatus( stError, errInvalidOp );
549 
550  //--------------------------------------------------------------------------
551  // Prepare the stuff
552  //--------------------------------------------------------------------------
553  pollfd pollDesc;
554  int pollRet;
555  bool useTimeout = (timeout!=-1);
556  time_t now = 0;
557  time_t newNow = 0;
558  short hupEvents = POLLHUP;
559 
560 #ifdef __linux__
561  hupEvents |= POLLRDHUP;
562 #endif
563 
564  if( useTimeout )
565  now = ::time(0);
566 
567  pollDesc.fd = pSocket;
568  pollDesc.events = POLLERR | POLLNVAL | hupEvents;
569 
570  if( readyForReading )
571  pollDesc.events |= (POLLIN | POLLPRI);
572 
573  if( readyForWriting )
574  pollDesc.events |= POLLOUT;
575 
576  //--------------------------------------------------------------------------
577  // We loop on poll because it may return -1 even thought no fatal error
578  // has occurred, these may be:
579  // * a signal interrupting the execution (errno == EINTR)
580  // * a failure to initialize some internal structures (Solaris only)
581  // (errno == EAGAIN)
582  //--------------------------------------------------------------------------
583  do
584  {
585  pollRet = poll( &pollDesc, 1, (useTimeout ? timeout*1000 : -1) );
586  if( (pollRet < 0) && (errno != EINTR) && (errno != EAGAIN) )
587  return XRootDStatus( stError, errPoll, errno );
588 
589  //------------------------------------------------------------------------
590  // Check if we did not time out in the case where we are not supposed
591  // to wait indefinitely
592  //------------------------------------------------------------------------
593  if( useTimeout )
594  {
595  newNow = time(0);
596  timeout -= (newNow-now);
597  now = newNow;
598  if( timeout < 0 )
600  }
601  }
602  while( pollRet == -1 );
603 
604  //--------------------------------------------------------------------------
605  // Check if we have timed out
606  //--------------------------------------------------------------------------
607  if( pollRet == 0 )
609 
610  //--------------------------------------------------------------------------
611  // We have some events
612  //--------------------------------------------------------------------------
613  if( pollDesc.revents & (POLLIN | POLLPRI | POLLOUT) )
614  return XRootDStatus( stOK );
615 
616  //--------------------------------------------------------------------------
617  // We've been hang up on
618  //--------------------------------------------------------------------------
619  if( pollDesc.revents & hupEvents )
621 
622  //--------------------------------------------------------------------------
623  // We're messed up, either because we messed up ourselves (POLLNVAL) or
624  // got messed up by the network (POLLERR)
625  //--------------------------------------------------------------------------
627  }
628 
629  //----------------------------------------------------------------------------
630  // Get the name of the socket
631  //----------------------------------------------------------------------------
632  std::string Socket::GetSockName() const
633  {
634  if( pStatus != Connected )
635  return "";
636 
637  if( pSockName.length() )
638  return pSockName;
639 
640  char nameBuff[256];
641  int len = XrdNetUtils::IPFormat( -pSocket, nameBuff, sizeof(nameBuff) );
642  if( len == 0 )
643  return "";
644 
645  pSockName = nameBuff;
646  return pSockName;
647  }
648 
649  //----------------------------------------------------------------------------
650  // Get the name of the remote peer
651  //----------------------------------------------------------------------------
652  std::string Socket::GetPeerName() const
653  {
654  if( pStatus != Connected )
655  return "";
656 
657  if( pPeerName.length() )
658  return pPeerName;
659 
660  char nameBuff[256];
661  int len = XrdNetUtils::IPFormat( pSocket, nameBuff, sizeof(nameBuff) );
662  if( len == 0 )
663  return "";
664 
665  pPeerName = nameBuff;
666  return pPeerName;
667  }
668 
669  //----------------------------------------------------------------------------
670  // Get the string representation of the socket
671  //----------------------------------------------------------------------------
672  std::string Socket::GetName() const
673  {
674  if( pStatus != Connected )
675  return "<x><--><x>";
676 
677  if( pName.length() )
678  return pName;
679 
680  pName = "<";
681  pName += GetSockName();
682  pName += "><--><";
683  pName += GetPeerName();
684  pName += ">";
685  return pName;
686  }
687 
688 
689  //------------------------------------------------------------------------
690  // Classify errno while reading/writing
691  //------------------------------------------------------------------------
693  {
694  switch( errno )
695  {
696 
697  case EAGAIN:
698 #if EAGAIN != EWOULDBLOCK
699  case EWOULDBLOCK:
700 #endif
701  {
702  //------------------------------------------------------------------
703  // Reading/writing operation would block! So we are done for now,
704  // but we will be back ;-)
705  //------------------------------------------------------------------
706  return XRootDStatus( stOK, suRetry );
707  }
708  case ECONNRESET:
709  case EDESTADDRREQ:
710  case EMSGSIZE:
711  case ENOTCONN:
712  case ENOTSOCK:
713  {
714  //------------------------------------------------------------------
715  // Actual socket error error!
716  //------------------------------------------------------------------
717  return XRootDStatus( stError, errSocketError, errno );
718  }
719  case EFAULT:
720  {
721  //------------------------------------------------------------------
722  // The buffer provided by the user for reading/writing is invalid
723  //------------------------------------------------------------------
725  }
726  default:
727  {
728  //------------------------------------------------------------------
729  // Not a socket error
730  //------------------------------------------------------------------
731  return XRootDStatus( stError, errInternal, errno );
732  }
733  }
734  }
735 
736 
737  //----------------------------------------------------------------------------
738  // Read helper from raw socket helper
739  //----------------------------------------------------------------------------
740  XRootDStatus Socket::Read( char *buffer, size_t size, int &bytesRead )
741  {
742  if( pTls ) return pTls->Read( buffer, size, bytesRead );
743 
744  int status = ::read( pSocket, buffer, size );
745 
746  // if the server shut down the socket declare a socket error (it
747  // will trigger a re-connect)
748  if( status == 0 )
749  return XRootDStatus( stError, errSocketError, errno );
750 
751  if( status < 0 )
752  return ClassifyErrno( errno );
753 
754  bytesRead = status;
755  return XRootDStatus();
756  }
757 
758  //----------------------------------------------------------------------------
759  // ReadV helper for raw socket
760  //----------------------------------------------------------------------------
761  XRootDStatus Socket::ReadV( iovec *iov, int iovcnt, int &bytesRead )
762  {
763  if( pTls ) return pTls->ReadV( iov, iovcnt, bytesRead );
764 
765  int status = ::readv( pSocket, iov, iovcnt );
766 
767  // if the server shut down the socket declare a socket error (it
768  // will trigger a re-connect)
769  if( status == 0 )
770  return XRootDStatus( stError, errSocketError, errno );
771 
772  if( status < 0 )
773  return ClassifyErrno( errno );
774 
775  bytesRead = status;
776  return XRootDStatus();
777  }
778 
779  //------------------------------------------------------------------------
780  // Cork the underlying socket
781  //------------------------------------------------------------------------
783  {
784 #if defined(TCP_CORK) && !defined(__GNU__)
785  // it's not defined on mac, we might want explore the possibility of using TCP_NOPUSH
786  if( pCorked ) return XRootDStatus();
787 
788  int state = 1;
789  int rc = setsockopt( pSocket, IPPROTO_TCP, TCP_CORK, &state, sizeof( state ) );
790  if( rc != 0 )
791  return XRootDStatus( stFatal, errSocketOptError, errno );
792 #endif
793  pCorked = true;
794  return XRootDStatus();
795  }
796 
797  //------------------------------------------------------------------------
798  // Uncork the underlying socket
799  //------------------------------------------------------------------------
801  {
802 #if defined(TCP_CORK) && !defined(__GNU__)
803  // it's not defined on mac, we might want explore the possibility of using TCP_NOPUSH
804  if( !pCorked ) return XRootDStatus();
805 
806  int state = 0;
807  int rc = setsockopt( pSocket, IPPROTO_TCP, TCP_CORK, &state, sizeof( state ) );
808  if( rc != 0 )
809  return XRootDStatus( stFatal, errSocketOptError, errno );
810 #endif
811  pCorked = false;
812  return XRootDStatus();
813  }
814 
815  //------------------------------------------------------------------------
816  // Flash the underlying socket
817  //------------------------------------------------------------------------
819  {
820  //----------------------------------------------------------------------
821  // Uncork the socket in order to flash the socket
822  //----------------------------------------------------------------------
823  XRootDStatus st = Uncork();
824  if( !st.IsOK() ) return st;
825 
826  //----------------------------------------------------------------------
827  // Once the data has been flashed we can cork the socket back
828  //----------------------------------------------------------------------
829  return Cork();
830  }
831 
832  //------------------------------------------------------------------------
833  // Do special event mapping if applicable
834  //------------------------------------------------------------------------
835  uint8_t Socket::MapEvent( uint8_t event )
836  {
837  if( pTls ) return pTls->MapEvent( event );
838  return event;
839  }
840 
841  //------------------------------------------------------------------------
842  // Enable encryption
843  //------------------------------------------------------------------------
845  const std::string &thehost )
846  {
847  try
848  {
849  if( !pServerAddr ) return XRootDStatus( stError, errInvalidOp );
850  if( !pTls ) pTls.reset( new Tls( this, socketHandler ) );
851  return pTls->Connect( thehost, pServerAddr.get() );
852  }
853  catch( std::exception& ex )
854  {
855  // the exception has been thrown when we tried to create
856  // the TLS context
857  return XRootDStatus( stFatal, errTlsError, 0, ex.what() );
858  }
859 
860  return XRootDStatus();
861  }
862 
863  //------------------------------------------------------------------------
864  // @return : true if socket is using TLS layer for encryption,
865  // false otherwise
866  //------------------------------------------------------------------------
868  {
869  return bool( pTls.get() );
870  }
871 
872 }
873 
874 
#define IPPROTO_TCP
Definition: XrdNetUtils.cc:800
int fcntl(int fd, int cmd,...)
ssize_t readv(int fildes, const struct iovec *iov, int iovcnt)
ssize_t write(int fildes, const void *buf, size_t nbyte)
ssize_t read(int fildes, void *buf, size_t nbyte)
#define close(a)
Definition: XrdPosix.hh:43
void AdvanceCursor(uint32_t delta)
Advance the cursor.
Definition: XrdClBuffer.hh:156
void SetCursor(uint32_t cursor)
Set the cursor.
Definition: XrdClBuffer.hh:148
uint32_t GetCursor() const
Get append cursor.
Definition: XrdClBuffer.hh:140
uint32_t GetSize() const
Get the size of the message.
Definition: XrdClBuffer.hh:132
char * GetBufferAtCursor()
Get the buffer pointer at the append cursor.
Definition: XrdClBuffer.hh:189
static Log * GetLog()
Get default log.
static Env * GetEnv()
Get default client environment.
bool GetInt(const std::string &key, int &value)
Definition: XrdClEnv.cc:89
Handle diagnostics.
Definition: XrdClLog.hh:101
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
Definition: XrdClLog.cc:299
The message representation used throughout the system.
Definition: XrdClMessage.hh:32
const std::string & GetObfuscatedDescription() const
Get the description of the message with authz parameter obfuscated.
std::string GetSockName() const
Get the name of the socket.
Definition: XrdClSocket.cc:632
std::string pSockName
Definition: XrdClSocket.hh:330
std::string GetName() const
Get the string representation of the socket.
Definition: XrdClSocket.cc:672
virtual XRootDStatus Send(const char *buffer, size_t size, int &bytesWritten)
Definition: XrdClSocket.cc:461
XRootDStatus Initialize(int family=AF_INET)
Initialize the socket.
Definition: XrdClSocket.cc:63
static XRootDStatus ClassifyErrno(int error)
Definition: XrdClSocket.cc:692
Socket(int socket=-1, SocketStatus status=Disconnected)
Definition: XrdClSocket.cc:44
SocketStatus
Status of the socket.
Definition: XrdClSocket.hh:49
@ Disconnected
The socket is disconnected.
Definition: XrdClSocket.hh:50
@ Connected
The socket is connected.
Definition: XrdClSocket.hh:51
@ Connecting
The connection process is in progress.
Definition: XrdClSocket.hh:52
bool IsEncrypted()
Definition: XrdClSocket.cc:867
XRootDStatus Flash()
Definition: XrdClSocket.cc:818
SocketStatus pStatus
Definition: XrdClSocket.hh:328
XRootDStatus Uncork()
Definition: XrdClSocket.cc:800
virtual XRootDStatus Read(char *buffer, size_t size, int &bytesRead)
Definition: XrdClSocket.cc:740
std::unique_ptr< Tls > pTls
Definition: XrdClSocket.hh:337
XRootDStatus ConnectToAddress(const XrdNetAddr &addr, uint16_t timout=10)
Definition: XrdClSocket.cc:212
void Close()
Disconnect.
Definition: XrdClSocket.cc:262
XRootDStatus SetSockOpt(int level, int optname, const void *optval, socklen_t optlen)
Set socket options.
Definition: XrdClSocket.cc:167
XRootDStatus ReadV(iovec *iov, int iocnt, int &bytesRead)
Definition: XrdClSocket.cc:761
XRootDStatus TlsHandShake(AsyncSocketHandler *socketHandler, const std::string &thehost=std::string())
Definition: XrdClSocket.cc:844
XRootDStatus GetFlags(int &flags)
Get the socket flags (man fcntl)
Definition: XrdClSocket.cc:137
uint8_t MapEvent(uint8_t event)
Definition: XrdClSocket.cc:835
std::string pName
Definition: XrdClSocket.hh:332
XRootDStatus Connect(const std::string &host, uint16_t port, uint16_t timout=10)
Definition: XrdClSocket.cc:183
XRootDStatus Cork()
Definition: XrdClSocket.cc:782
XRootDStatus GetSockOpt(int level, int optname, void *optval, socklen_t *optlen)
Get socket options.
Definition: XrdClSocket.cc:152
XRootDStatus WriteRaw(void *buffer, uint32_t size, int32_t timeout, uint32_t &bytesWritten)
Definition: XrdClSocket.cc:375
std::string pPeerName
Definition: XrdClSocket.hh:331
XRootDStatus ReadRaw(void *buffer, uint32_t size, int32_t timeout, uint32_t &bytesRead)
Read raw bytes from the socket.
Definition: XrdClSocket.cc:280
XRootDStatus Poll(bool readyForReading, bool readyForWriting, int32_t timeout)
Definition: XrdClSocket.cc:541
virtual ~Socket()
Desctuctor.
Definition: XrdClSocket.cc:55
std::unique_ptr< XrdNetAddr > pServerAddr
Definition: XrdClSocket.hh:329
XRootDStatus SetFlags(int flags)
Set the socket flags (man fcntl)
Definition: XrdClSocket.cc:123
std::string GetPeerName() const
Get the name of the remote peer.
Definition: XrdClSocket.cc:652
TLS layer for socket connection.
Definition: XrdClTls.hh:40
URL representation.
Definition: XrdClURL.hh:31
static void LogHostAddresses(Log *log, uint64_t type, const std::string &hostId, std::vector< XrdNetAddr > &addresses)
Log all the addresses on the list.
Definition: XrdClUtils.cc:234
static Status GetHostAddresses(std::vector< XrdNetAddr > &addresses, const URL &url, AddressType type)
Resolve IP addresses.
Definition: XrdClUtils.cc:140
static int Connect(int fd, const struct sockaddr *name, int namelen, int tsec=-1)
static int IPFormat(const struct sockaddr *sAddr, char *bP, int bL, int opts=0)
Definition: XrdNetUtils.cc:584
const uint16_t errPoll
error while polling descriptors
Definition: XrdClStatus.hh:54
const uint16_t suRetry
Definition: XrdClStatus.hh:40
const uint16_t errSocketOptError
Definition: XrdClStatus.hh:76
const uint16_t errTlsError
Definition: XrdClStatus.hh:80
const uint16_t stFatal
Fatal error, it's still an error.
Definition: XrdClStatus.hh:33
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
const uint64_t PostMasterMsg
const uint16_t errSocketTimeout
Definition: XrdClStatus.hh:73
const uint16_t errInternal
Internal error.
Definition: XrdClStatus.hh:56
const uint16_t stOK
Everything went OK.
Definition: XrdClStatus.hh:31
const uint16_t errInvalidOp
Definition: XrdClStatus.hh:51
const uint64_t AsyncSockMsg
const uint16_t errInvalidArgs
Definition: XrdClStatus.hh:58
const uint16_t errNotSupported
Definition: XrdClStatus.hh:62
const uint16_t errSocketError
Definition: XrdClStatus.hh:72
const uint16_t errFcntl
failed manipulate file descriptor
Definition: XrdClStatus.hh:53
const int DefaultNoDelay
const uint16_t errSocketDisconnected
Definition: XrdClStatus.hh:74
ssize_t Send(int fd, KernelBuffer &buffer)
uint16_t code
Error type, or additional hints on what to do.
Definition: XrdClStatus.hh:147
uint16_t status
Status of the execution.
Definition: XrdClStatus.hh:146
bool IsOK() const
We're fine.
Definition: XrdClStatus.hh:124
uint32_t errNo
Errno, if any.
Definition: XrdClStatus.hh:148