#ifndef __XRD_LINK_H__ #define __XRD_LINK_H__ /******************************************************************************/ /* */ /* X r d L i n k . h h */ /* */ /* (c) 2018 by the Board of Trustees of the Leland Stanford, Jr., University */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include "XrdNet/XrdNetAddr.hh" #include "XrdOuc/XrdOucSFVec.hh" #include "XrdSys/XrdSysPthread.hh" #include "Xrd/XrdJob.hh" /******************************************************************************/ /* C l a s s D e f i n i t i o n */ /******************************************************************************/ class XrdLinkMatch; class XrdLinkXeq; class XrdPollInfo; class XrdProtocol; class XrdTlsPeerCerts; class XrdTlsContext; class XrdLink : public XrdJob { public: //----------------------------------------------------------------------------- //! Activate a link by attaching it to a poller object. //! //! @return True if activation succeeded and false otherwise. //----------------------------------------------------------------------------- bool Activate(); //----------------------------------------------------------------------------- //! Obtain the address information for this link. //! //! @return Pointer to the XrdAddrInfo object. The pointer is valid while the //! end-point is connected. //----------------------------------------------------------------------------- XrdNetAddrInfo *AddrInfo(); //----------------------------------------------------------------------------- //! Obtain the number of queued async requests. //! //! @return The number of async requests queued. //----------------------------------------------------------------------------- int Backlog(); //----------------------------------------------------------------------------- //! Get a copy of the client's name as known by the link. //! //! @param buff Pointer to buffer to hold the name. //! @param blen Length of the buffer. //! //! @return !0 The length of the name in gthe buffer. //! =0 The name could not be returned. //----------------------------------------------------------------------------- int Client(char *buff, int blen); //----------------------------------------------------------------------------- //! Close the link. //! //! @param defer If true, the link is made unaccessible but the link //! object not the file descriptor is released. //! //! @return !0 An error occurred, the return value is the errno. //! =0 Action successfully completed. //----------------------------------------------------------------------------- int Close(bool defer=false); //----------------------------------------------------------------------------- //! Enable the link to field interrupts. //----------------------------------------------------------------------------- void Enable(); //----------------------------------------------------------------------------- //! Get the associated file descriptor. //! //! @return The file descriptor number. //----------------------------------------------------------------------------- int FDnum(); //----------------------------------------------------------------------------- //! Find the next link matching certain attributes. //! //! @param curr Is an internal tracking value that allows repeated calls. //! It must be set to a value of 0 or less on the initial call //! and not touched therafter unless a null pointer is returned. //! @param who If the object use to check if the link matches the wanted //! criterea (typically, client name and host name). If the //! pointer is nil, the next link is always returned. //! //! @return !0 Pointer to the link object that matches the criterea. The //! link's reference counter is increased to prevent it from //! being reused. A subsequent call will reduce the number. //! =0 No more links exist with the specified criterea. //----------------------------------------------------------------------------- static XrdLink *Find(int &curr, XrdLinkMatch *who=0); //----------------------------------------------------------------------------- //! Get I/O statistics. //! //! @param inbytes The number of bytes read. //! @param outbytes The number of bytes written. //! @param numstall The number of times the link was rescheduled due to //! unavailability. //! @param numtardy The number of times the link was delayed due to //! unavailability. //! //! @return The link's reference count. The parameters will hold the //! indicated statistic. //----------------------------------------------------------------------------- int getIOStats(long long &inbytes, long long &outbytes, int &numstall, int &numtardy); //----------------------------------------------------------------------------- //! Find the next client name matching certain attributes. //! //! @param curr Is an internal tracking value that allows repeated calls. //! It must be set to a value of 0 or less on the initial call //! and not touched therafter unless zero is returned. //! @param bname Pointer to a buffer where the name is to be returned. //! @param blen The length of the buffer. //! @param who If the object use to check if the link matches the wanted //! criterea (typically, client name and host name). If the //! pointer is nil, a match always occurs. //! //! @return !0 The length of the name placed in the buffer. //! =0 No more links exist with the specified criterea. //----------------------------------------------------------------------------- static int getName(int &curr, char *bname, int blen, XrdLinkMatch *who=0); //----------------------------------------------------------------------------- //! Get the x509 certificate information for this TLS enabled link. //! //! @return A pointer to the XrdTlsCerts object holding verified certificates //! if such certificates exist. Otherwise a nil pointer is returned. //! //! @note Used by various protocols, so XrdTlsPeerCerts is a private header. //----------------------------------------------------------------------------- XrdTlsPeerCerts *getPeerCerts(); //----------------------------------------------------------------------------- //! Obtain current protocol object pointer. //----------------------------------------------------------------------------- XrdProtocol *getProtocol(); //----------------------------------------------------------------------------- //! Lock or unlock the mutex used for control operations. //! //! @param lk When true, a lock is obtained. Otherwise it is released. //! The caller is responsible for consistency. //----------------------------------------------------------------------------- void Hold(bool lk); //----------------------------------------------------------------------------- //! Get the fully qualified name of the endpoint. //! //! @return Pointer to fully qualified host name. The contents are valid //! while the endpoint is connected. //----------------------------------------------------------------------------- const char *Host() const {return (const char *)HostName;} //----------------------------------------------------------------------------- //! Pointer to the client's link identity. //----------------------------------------------------------------------------- char *ID; // This is referenced a lot (should have been const). //----------------------------------------------------------------------------- //! Obtain the link's instance number. //! //! @return The link's instance number. //----------------------------------------------------------------------------- unsigned int Inst() const {return Instance;} //----------------------------------------------------------------------------- //! Indicate whether or not the link has an outstanding error. //! //! @return True the link has an outstanding error. //! the link has no outstanding error. //----------------------------------------------------------------------------- bool isFlawed() const; //----------------------------------------------------------------------------- //! Indicate whether or not this link is of a particular instance. //! only be used for display and not for security purposes. //! //! @param inst the expected instance number. //! //! @return true the link matches the instance number. //! false the link differs the instance number. //----------------------------------------------------------------------------- bool isInstance(unsigned int inst) const; //----------------------------------------------------------------------------- //! Obtain the domain trimmed name of the end-point. The returned value should //! only be used for display and not for security purposes. //! //! @return Pointer to the name that remains valid during the link's lifetime. //----------------------------------------------------------------------------- const char *Name() const; //----------------------------------------------------------------------------- //! Obtain the network address object for this link. The returned value is //! valid as long as the end-point is connected. Otherwise, it may change. //! //! @return Pointer to the object and remains valid during the link's lifetime. //----------------------------------------------------------------------------- const XrdNetAddr *NetAddr() const; //----------------------------------------------------------------------------- //! Issue a socket peek() and return result (do not use for TLS connections). //! //! @param buff pointer to buffer to hold data. //! @param blen length of buffer. //! @param timeout milliseconds to wait for data. A negative value waits //! forever. //! //! @return >=0 buffer holds data equal to the returned value. //! < 0 an error or timeout occurred. //----------------------------------------------------------------------------- int Peek(char *buff, int blen, int timeout=-1); //----------------------------------------------------------------------------- //! Read data from a link. Note that this call blocks until some data is //! available. Use Recv() with a timeout to avoid blocking. //! //! @param buff pointer to buffer to hold data. //! @param blen length of buffer (implies the maximum bytes wanted). //! //! @return >=0 buffer holds data equal to the returned value. //! < 0 an error occurred. //----------------------------------------------------------------------------- int Recv(char *buff, int blen); //----------------------------------------------------------------------------- //! Read data from a link. Note that this call either reads all the data wanted //! or no data if the passed timeout occurs before any data is present. //! //! @param buff pointer to buffer to hold data. //! @param blen length of buffer (implies the actual bytes wanted). //! @param timeout milliseconds to wait for data. A negative value waits //! forever. //! //! @return >=0 buffer holds data equal to the returned value. //! < 0 an error occurred. Note that a special error -ENOMSG //! is returned if poll() indicated data was present but //! no bytes were actually read. //----------------------------------------------------------------------------- int Recv(char *buff, int blen, int timeout); //----------------------------------------------------------------------------- //! Read data on a link. Note that this call either reads all the data wanted //! or no data if the passed timeout occurs before any data is present. //! //! @param iov pointer to the message vector. //! @param iocnt number of iov elements in the vector. //! @param timeout milliseconds to wait for data. A negative value waits //! forever. //! //! @return >=0 number of bytes read. //! < 0 an error occurred or when -ETIMEDOUT is returned, no data //! arrived within the timeout period. -ENOMSG is returned //! when poll indicated data was present but 0 bytes were read. //----------------------------------------------------------------------------- int Recv(const struct iovec *iov, int iocnt, int timeout); //----------------------------------------------------------------------------- //! Read data from a link. Note that this call reads as much data as it can //! or until the passed timeout has occurred. //! //! @param buff pointer to buffer to hold data. //! @param blen length of buffer (implies the maximum bytes wanted). //! @param timeout milliseconds to wait for data. A negative value waits //! forever. //! //! @return >=0 buffer holds data equal to the returned value. //! < 0 an error occurred or when -ETIMEDOUT is returned, no data //! arrived within the timeout period. -ENOMSG is returned //! when poll indicated data was present but 0 bytes were read. //----------------------------------------------------------------------------- int RecvAll(char *buff, int blen, int timeout=-1); //------------------------------------------------------------------------------ //! Register a host name with this IP address. This is not MT-safe! //! //! @param hName pointer to a true host name which should be fully qualified. //! One of the IP addresses registered to this name must //! match the IP address associated with this object. //! //! @return True: Specified name is now associated with this link. //! False: Nothing changed, registration could not be verified. //------------------------------------------------------------------------------ bool Register(const char *hName); //----------------------------------------------------------------------------- //! Send data on a link. This calls may block unless the socket was marked //! nonblocking. If a block would occur, the data is copied for later sending. //! //! @param buff pointer to buffer to send. //! @param blen length of buffer. //! //! @return >=0 number of bytes sent. //! < 0 an error or occurred. //----------------------------------------------------------------------------- int Send(const char *buff, int blen); //----------------------------------------------------------------------------- //! Send data on a link. This calls may block unless the socket was marked //! nonblocking. If a block would occur, the data is copied for later sending. //! //! @param iov pointer to the message vector. //! @param iocnt number of iov elements in the vector. //! @param bytes the sum of the sizes in the vector. //! //! @return >=0 number of bytes sent. //! < 0 an error occurred. //----------------------------------------------------------------------------- int Send(const struct iovec *iov, int iocnt, int bytes=0); //----------------------------------------------------------------------------- //! Send data on a link using sendfile(). This call always blocks until all //! data is sent. It should only be called if sfOK is true (see below). //! //! @param sdP pointer to the sendfile vector. //! @param sdn number of elements in the vector. //! //! @return >=0 number of bytes sent. //! < 0 an error occurred. //----------------------------------------------------------------------------- static bool sfOK; // True if Send(sfVec) enabled typedef XrdOucSFVec sfVec; int Send(const sfVec *sdP, int sdn); // Iff sfOK is true //----------------------------------------------------------------------------- //! Wait for all outstanding requests to be completed on the link. //----------------------------------------------------------------------------- void Serialize(); //----------------------------------------------------------------------------- //! Set an error indication on he link. //! //! @param text a message describing the error. //! //! @return =0 message set, the link is considered in error. //! -1 the message pointer was nil. //----------------------------------------------------------------------------- int setEtext(const char *text); //----------------------------------------------------------------------------- //! Set the client's link identity. //! //! @param userid pointer to the client's username. //! @param procid the client's process id (i.e. pid). //----------------------------------------------------------------------------- void setID(const char *userid, int procid); //----------------------------------------------------------------------------- //! Set the client's location. //! //! @param loc reference to the location information. //----------------------------------------------------------------------------- void setLocation(XrdNetAddrInfo::LocInfo &loc); //----------------------------------------------------------------------------- //! Set the link to be non-blocking. //! //! @return true mode has been set. //! @return false mode is not supported for this operating system. //----------------------------------------------------------------------------- bool setNB(); //----------------------------------------------------------------------------- //! Set the link's protocol. //! //! @param pp pointer to the protocol object. //! @param runit if true, starts running the protocol. //! @param push if true, pushes current protocol to be the alternate one. //! //! @return pointer to the previous protocol (may be nil). //----------------------------------------------------------------------------- XrdProtocol *setProtocol(XrdProtocol *pp, bool runit=false, bool push=false); //----------------------------------------------------------------------------- //! Set the link's protocol name. //! //! @param name name of he protocol being used. The storage must be //! valid for the duration of the program. //----------------------------------------------------------------------------- void setProtName(const char *name); //----------------------------------------------------------------------------- //! Set the link's parallel usage count. //! //! @param cnt should be 1 to increased the count and -1 to decrease it. //----------------------------------------------------------------------------- void setRef(int cnt); //----------------------------------------------------------------------------- //! Enable or disable TLS on the link. // //! @param enable if true, TLS is enabled if not already enabled. Otherwise, //! TLS is disabled and the TLS logical connection torn down. //! statistics may be contradictory as they are collected async. //! @param ctx The context to use when enabling TLS. When nil, the default //! context is used. //! //! @return True if successful, false otherwise. //----------------------------------------------------------------------------- bool setTLS(bool enable, XrdTlsContext *ctx=0); //----------------------------------------------------------------------------- //! Shutdown the link but otherwise keep it intact. //! //! @param getLock if true, the operation is performed under a lock. //----------------------------------------------------------------------------- void Shutdown(bool getLock); //----------------------------------------------------------------------------- //! Obtain link statistics. //! //! @param buff pointer to the buffer for the xml statistics. //! @param blen length of the buffer. //! @param do_sync if true, the statistics self-consistent. Otherwise, the //! statistics may be contradictory as they are collected async. //! //! @return number of bytes placed in the buffer excluding the null byte. //----------------------------------------------------------------------------- static int Stats(char *buff, int blen, bool do_sync=0); //----------------------------------------------------------------------------- //! Add all local statistics to the global counters. //! //! @param ctime if not nil, return the total connect time in seconds. //----------------------------------------------------------------------------- void syncStats(int *ctime=0); //----------------------------------------------------------------------------- //! Terminate a connection. //! //! @param owner pointer to the link ID representing a client who made //! the connection to be terminated. If nil then this is a //! request for the link to terminate another link, if possible. //! @param fdnum the file descriptor number of the link to be terminated. //! @param inst the link's instance number. //! //! @return >0 caller should wait this number of seconds and try again. //! @return =0 link terminated. //! @return <0 link could not be terminated: //! -EACCES the links was not created by the passed owner. //! -EPIPE link already being terminated. //! -ESRCH fdnum does not refer to a link. //! -ETIME unsuccessful, too many tries. //----------------------------------------------------------------------------- int Terminate(const char *owner, int fdnum, unsigned int inst); //----------------------------------------------------------------------------- //! Return the time the link was made active (i.e. time of connection). //----------------------------------------------------------------------------- time_t timeCon() const; //----------------------------------------------------------------------------- //! Return link's reference count. //----------------------------------------------------------------------------- int UseCnt() const; //----------------------------------------------------------------------------- //! Mark this link as an in-memory communications bridge (internal use only). //----------------------------------------------------------------------------- void armBridge(); //----------------------------------------------------------------------------- //! Determine if this link is a bridge. //! //! @return true this link is a bridge. //! @return false this link is a plain old link. //----------------------------------------------------------------------------- bool hasBridge() const {return isBridged;} //----------------------------------------------------------------------------- //! Determine if this link is using TLS. //! //! @return true this link is using TLS. //! @return false this link not using TLS. //----------------------------------------------------------------------------- bool hasTLS() const {return isTLS;} //----------------------------------------------------------------------------- //! Return TLS protocol version being used. //! //! @return The TLS protocol version number. If the link is not using TLS, //! a null string is returned; //----------------------------------------------------------------------------- const char *verTLS(); //----------------------------------------------------------------------------- //! Constructor //! //! @param lxq Reference to the implementation. //----------------------------------------------------------------------------- XrdLink(XrdLinkXeq &lxq); protected: ~XrdLink() {} // Is never deleted! void DoIt(); // This is an override of XrdJob::DoIt. void ResetLink(); int Wait4Data(int timeout); void *rsvd1[3]; // Reserved for future use XrdLinkXeq &linkXQ; // The implementation char *HostName; // Pointer to the hostname unsigned int Instance; // Instance number of this object bool isBridged; // If true, this link is an in-memory bridge bool isTLS; // If true, this link uses TLS for all I/O char rsvd2[2]; }; #endif