Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:27:57

0001 #ifndef __XRDXROOTDBRIDGE_HH_
0002 #define __XRDXROOTDBRIDGE_HH_
0003 /******************************************************************************/
0004 /*                                                                            */
0005 /*                    X r d X r o o t d B r i d g e . h h                     */
0006 /*                                                                            */
0007 /* (c) 2012 by the Board of Trustees of the Leland Stanford, Jr., University  */
0008 /*                            All Rights Reserved                             */
0009 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
0010 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
0011 /*                                                                            */
0012 /* This file is part of the XRootD software suite.                            */
0013 /*                                                                            */
0014 /* XRootD is free software: you can redistribute it and/or modify it under    */
0015 /* the terms of the GNU Lesser General Public License as published by the     */
0016 /* Free Software Foundation, either version 3 of the License, or (at your     */
0017 /* option) any later version.                                                 */
0018 /*                                                                            */
0019 /* XRootD is distributed in the hope that it will be useful, but WITHOUT      */
0020 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      */
0021 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public       */
0022 /* License for more details.                                                  */
0023 /*                                                                            */
0024 /* You should have received a copy of the GNU Lesser General Public License   */
0025 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file  */
0026 /* COPYING (GPL license).  If not, see <http://www.gnu.org/licenses/>.        */
0027 /*                                                                            */
0028 /* The copyright holder's institutional names and contributor's names may not */
0029 /* be used to endorse or promote products derived from this software without  */
0030 /* specific prior written permission of the institution or contributor.       */
0031 /******************************************************************************/
0032 
0033 #include <cstring>
0034 
0035 #include "XProtocol/XPtypes.hh"
0036 
0037 //-----------------------------------------------------------------------------
0038 //! Bridge
0039 //!
0040 //! The Bridge object allows other protocols to gain access to the xrootd
0041 //! protocol stack. Almost any kind of request/response protocol can use this
0042 //! class to convert its request to an xroot protocol request and rewrite the
0043 //! xroot protocol response to adhere to its protocol specification. Callers
0044 //! of these methods must be thread-safe and must not rely on thread-local
0045 //! storage as bridge requests and responses may or may not be executed using
0046 //! the initiating thread. Also, see the Result object class below.
0047 //-----------------------------------------------------------------------------
0048 
0049 struct iovec;
0050 class  XrdLink;
0051 class  XrdSecEntity;
0052 class  XrdXrootdProtocol;
0053 
0054 namespace XrdXrootd
0055 {
0056 
0057 /******************************************************************************/
0058 /*                     X r d X r o o t d : : B r i d g e                      */
0059 /******************************************************************************/
0060   
0061 class Bridge
0062 {
0063 public:
0064 class Result;
0065 
0066 //-----------------------------------------------------------------------------
0067 //! Create a Bridge object.
0068 //!
0069 //! The first step is to create a Bridge object via a Login() call. The object
0070 //! should correspond to a session (i.e. tied to a particular client) real or
0071 //! not. The returned object must be used to inject xrootd requests into the
0072 //! protocol stack. Response rewrites are handled by the Result object passed as
0073 //! an argument. A successful Login() takes control of the connection. You can
0074 //! still write using the Link object but reads may only occur when your
0075 //! protocol's Process() method is called. Use Disc() to disband the bridge and
0076 //! free its storage. The bridge is automatically disbanded when your protocol's
0077 //! Recycle() method is called. This happens when you explicitly close the link
0078 //! or implicitly when the Process() method returns a negative error code or
0079 //! a callback method returns false.
0080 //!
0081 //! @param  rsltP   a pointer to the result object. This object is used to
0082 //!                 to rewrite xrootd responses to protocol specific responses.
0083 //!                 It must be allocated by the caller. One such object can be
0084 //!                 created for each session or, if the protocol allows, be
0085 //!                 shared by all sessions. It cannot be deleted until all
0086 //!                 references to the object disappear (see the Result class).
0087 //! @param  linkP   a pointer to the link object that the protocol driver
0088 //!                 created to the client connection.
0089 //! @param  seceP   a pointer to the XrdSecEntity object that describes the
0090 //!                 client's identity.
0091 //! @param  nameP   An arbitrary 1-to-8 character client name. The Bridge will
0092 //!                 uniquefy this name so that log file messages will track the
0093 //!                 the associated client. The link's identity is set to
0094 //!                 correspond to this name with additional information.
0095 //! @param  protP   a 1-to-7 character name of the protocol using this bridge
0096 //!                 (e.g. "http").
0097 //!
0098 //! @return bridgeP a pointer to a new instance of this class if a bridge
0099 //!                 could be created, null otherwise. If null is returned, the
0100 //!                 retc variable holds the errno indicating why it failed.
0101 //-----------------------------------------------------------------------------
0102 
0103 static
0104 Bridge       *Login(Result       *rsltP, //!< The result callback object
0105                     XrdLink      *linkP, //!< Client's network connection
0106                     XrdSecEntity *seceP, //!< Client's identity
0107                     const char   *nameP, //!< Client's name for tracking
0108                     const char   *protP  //!< Protocol name for tracking
0109                    );
0110 
0111 //-----------------------------------------------------------------------------
0112 //! Inject an xrootd request into the protocol stack.
0113 //!
0114 //! The Run() method allows you to inject an xrootd-style request into the
0115 //! stack. It must use the same format as a real xrootd client would use across
0116 //! the network. The xroot protocol reference describes these requests. The
0117 //! Run() method handles the request as if it came through the network with
0118 //! some notable exceptions (see the xdataP and xdataL arguments).
0119 //!
0120 //! @param  xreqP   pointer to the xrootd request. This is the standard 24-byte
0121 //!                 request header common to all xrootd requests in network
0122 //!                 format. The contents of the buffer may be modified by the
0123 //!                 this method. The buffer must not be modified by the caller
0124 //!                 before a response is solicited via the Result object.
0125 //!
0126 //! @param  xdataP  the associated data for this request. Full or partial data
0127 //!                 may be supplied as indicated by the xdataL argument. See
0128 //!                 explanation of xdataL. For write requests, this buffer may
0129 //!                 not be altered or deleted until the Result Free() callback
0130 //!                 is invoked. For other requests, it doesn't matter.
0131 //!
0132 //!                 If the pointer is zero but the "dlen" field is not zero,
0133 //!                 dlen's worth of data is read from the network using the
0134 //!                 associated XdLink object to complete the request.
0135 //!
0136 //! @param  xdataL  specifies the length of data in the buffer pointed to by
0137 //!                 xdataP. Depending on the value and the value in the "dlen"
0138 //!                 field, additional data may be read from the network.
0139 //!
0140 //!                 xdataL  < "dlen": dlen-xdataL additional bytes will be read
0141 //!                                   from the network to complete the request.
0142 //!                 xdataL >= "dlen": no additional bytes will be read from the
0143 //!                                   network. The request data is complete.
0144 //!
0145 //! @return true    the request has been accepted. Processing will start when
0146 //!                 the caller returns from the Process() method.
0147 //!                 A response will come via a Result object callback.
0148 //!         false   the request has been rejected because the bridge is still
0149 //!                 processing a previous request.
0150 //-----------------------------------------------------------------------------
0151 
0152 virtual bool  Run(const char *xreqP,       //!< xrootd request header
0153                         char *xdataP=0,    //!< xrootd request data (optional)
0154                         int   xdataL=0     //!< xrootd request data length
0155                  ) = 0;
0156 
0157 //-----------------------------------------------------------------------------
0158 //! Disconnect the session from the bridge.
0159 //!
0160 //! The Disc() method allows you to disconnect the session from the bridge and
0161 //! free the storage associated with this object. It may be called when you want
0162 //! to regain control of the connection and delete the Bridge object (note that
0163 //! you cannot use delete on Bridge). The Disc() method must not be called in
0164 //! your protocol Recycle() method as protocol object recycling already implies
0165 //! a Disc() call (i.e. the connection is disbanding the associated protocol).
0166 //!
0167 //! @return true    the bridge has been  dismantled.
0168 //!         false   the bridge cannot be dismantled because it is still
0169 //!                 processing a previous request.
0170 //-----------------------------------------------------------------------------
0171 
0172 virtual bool  Disc() = 0;
0173 
0174 //-----------------------------------------------------------------------------
0175 //! Set file's sendfile capability.
0176 //!
0177 //! The setSF() method allows you to turn on or off the ability of an open
0178 //! file to be used with the sendfile() system call. This is useful when you
0179 //! must see the data prior to sending to the client (e.g. for encryption).
0180 //!
0181 //! @param  fhandle the filehandle as returned by kXR_open.
0182 //! @param  seton   When true, enables sendfile() otherwise it is disabled.
0183 //!
0184 //! @return =0      Sucessful.
0185 //! @return <0      Call failed. The return code is -errno and usually will
0186 //!                 indicate that the filehandle is not valid.
0187 //-----------------------------------------------------------------------------
0188 
0189 virtual int   setSF(kXR_char *fhandle, bool seton=false) = 0;
0190 
0191 //-----------------------------------------------------------------------------
0192 //! Set the maximum delay.
0193 //!
0194 //! The setWait() method allows you to specify the maximum amount of time a
0195 //! request may be delayed (i.e. via kXR_wait result) before it generates a
0196 //! kXR_Cancelled error with the associated Error() result callback. The default
0197 //! maximum time is 1 hour. If you specify a time less than or equal to zero,
0198 //! wait requests are reflected back via the Wait() result callback method and
0199 //! you are responsible for handling them. You can request wait notification
0200 //! while still having the wait internally handled using the second parameter.
0201 //! Maximum delays are bridge specific. There is no global value. If you desire
0202 //! something other than the default you must call SetWait for each Login().
0203 //!
0204 //! @param  wtime   the maximum wait time in seconds.
0205 //! @param  notify  When true, issues a Wait callback whenever a wait occurs.
0206 //!                 This is the default when wtime is <= 0.
0207 //!
0208 //-----------------------------------------------------------------------------
0209 
0210 virtual void  SetWait(int wtime, bool notify=false) = 0;
0211 
0212 /******************************************************************************/
0213 /*            X r d X r o o t d : : B r i d g e : : C o n t e x t             */
0214 /******************************************************************************/
0215   
0216 //-----------------------------------------------------------------------------
0217 //! Provide callback context.
0218 //!
0219 //! The Context object is passed in all Result object callbacks and contains
0220 //! information describing the result context. No public members should be
0221 //! changed by any result callback method. The context object also includes a
0222 //! method that must be used to complete a pending sendfile() result.
0223 //-----------------------------------------------------------------------------
0224   
0225 class Context
0226 {
0227 public:
0228 
0229       XrdLink   *linkP; //!< -> associated session link object (i.e. connection)
0230       kXR_unt16  rCode; //!< associated "kXR" request code in host byte order
0231 union{kXR_unt16  num;   //!< associated stream ID as a short
0232       kXR_char   chr[2];//!< associated stream ID as the original char[2]
0233      }           sID;   //!< associated request stream ID
0234 
0235 //-----------------------------------------------------------------------------
0236 //! Complete a File() callback.
0237 //!
0238 //! The Send() method must be called after the File() callback is invoked to
0239 //! complete data transmission using sendfile(). If Send() is not called the
0240 //! pending sendfile() call is not made and no data is sent to the client.
0241 //!
0242 //! @param  headP   a pointer to the iovec structure containing the data that
0243 //!                 must be sent before the sendfile() data. If there is none,
0244 //!                 the pointer can be null.
0245 //! @param  headN   the number of elements in the headP iovec structure array.
0246 //! @param  tailP   a pointer to the iovec structure containing the data that
0247 //!                 must be sent after the sendfile() data. If there is none,
0248 //!                 the pointer can be null.
0249 //! @param  tailN   the number of elements in the tailP iovec structure array.
0250 //!
0251 //! @return < 0     transmission error has occurred. This can be due to either
0252 //!                 connection failure or data source error (i.e. I/O error).
0253 //!         = 0     data has been successfully sent.
0254 //!         > 0     the supplied context was not generated by a valid File()
0255 //!                 callback. No data has been sent.
0256 //-----------------------------------------------------------------------------
0257 
0258 virtual int   Send(const
0259                    struct iovec *headP, //!< pointer to leading  data array
0260                    int           headN, //!< array count
0261                    const
0262                    struct iovec *tailP, //!< pointer to trailing data array
0263                    int           tailN  //!< array count
0264                   )
0265 {
0266   (void)headP; (void)headN; (void)tailP; (void)tailN;
0267   return 1;
0268 }
0269 
0270 //-----------------------------------------------------------------------------
0271 //! Constructor and Destructor
0272 //-----------------------------------------------------------------------------
0273 
0274               Context(XrdLink *lP, kXR_char *sid, kXR_unt16 req)
0275                      : linkP(lP), rCode(req)
0276                        {memcpy(sID.chr, sid, sizeof(sID.chr));}
0277 virtual      ~Context() {}
0278 };
0279 
0280 /******************************************************************************/
0281 /*             X r d X r o o t d : : B r i d g e : : R e s u l t              */
0282 /******************************************************************************/
0283 
0284 //-----------------------------------------------------------------------------
0285 //! Handle xroot protocol execution results.
0286 //!
0287 //! The Result object is an abstract class that defines the interface used
0288 //! by the xroot protocol stack to effect a client response using whatever
0289 //! alternate protocol is needed. You must define an implementation and pass it
0290 //! as an argument to the Login() Bridge method.
0291 //-----------------------------------------------------------------------------
0292 
0293 class Result
0294 {
0295 public:
0296 
0297 //-----------------------------------------------------------------------------
0298 //! Effect a client data response.
0299 //!
0300 //! The Data() method is called when Run() resulted in a successful data
0301 //! response. The method should rewrite the data and send it to the client using
0302 //! the associated XrdLink object. As an example,
0303 //! 1) Result::Data(info, iovP, iovN, iovL) is called.
0304 //! 2) Inspect iovP, rewrite the data.
0305 //! 3) Send the response: info->linkP->Send(new_iovP, new_iovN, new_iovL);
0306 //! 4) Handle send errors and cleanup(e.g. deallocate storage).
0307 //! 5) Return, the exchange is now complete.
0308 //!
0309 //! @param  info    the context associated with the result.
0310 //! @param  iovP    a pointer to the iovec structure containing the xrootd data
0311 //!                 response about to be sent to the client. The request header
0312 //!                 is not included in the iovec structure. The elements of this
0313 //!                 structure must not be modified by the method.
0314 //! @param  iovN    the number of elements in the iovec structure array.
0315 //! @param  iovL    total number of data bytes that would be sent to the client.
0316 //!                 This is simply the sum of all the lengths in the iovec.
0317 //! @param  final   True is this is the final result. Otherwise, this is a
0318 //!                 partial result (i.e. kXR_oksofar) and more data will result
0319 //!                 causing additional callbacks. For write requests, any
0320 //!                 supplied data buffer may now be reused or freed.
0321 //!
0322 //! @return true    continue normal processing.
0323 //!         false   terminate the bridge and close the link.
0324 //-----------------------------------------------------------------------------
0325 
0326 virtual bool  Data(Bridge::Context &info,   //!< the result context
0327                    const
0328                    struct iovec    *iovP,   //!< pointer to data array
0329                    int              iovN,   //!< array count
0330                    int              iovL,   //!< byte  count
0331                    bool             final   //!< true -> final result
0332                   ) = 0;
0333 
0334 //-----------------------------------------------------------------------------
0335 //! Effect a client acknowledgement.
0336 //!
0337 //! The Done() method is called when Run() resulted in success and there is no
0338 //! associated data for the client (equivalent to a simple kXR_ok response).
0339 //!
0340 //! @param  info    the context associated with the result.
0341 //!
0342 //! @return true    continue normal processing.
0343 //!         false   terminate the bridge and close the link.
0344 //-----------------------------------------------------------------------------
0345 
0346 virtual bool  Done(Bridge::Context &info)=0;//!< the result context
0347 
0348 //-----------------------------------------------------------------------------
0349 //! Effect a client error response.
0350 //!
0351 //! The Error() method is called when an error was encountered while processing
0352 //! the Run() request. The error should be reflected to the client.
0353 //!
0354 //! @param  info    the context associated with the result.
0355 //! @param  ecode   the "kXR" error code describing the nature of the error.
0356 //!                 The code is in host byte format.
0357 //! @param  etext   a null terminated string describing the error in human terms
0358 //!
0359 //! @return true    continue normal processing.
0360 //!         false   terminate the bridge and close the link.
0361 //-----------------------------------------------------------------------------
0362 
0363 virtual bool  Error(Bridge::Context &info,   //!< the result context
0364                     int              ecode,  //!< the "kXR" error code
0365                     const char      *etext   //!< associated error message
0366                    ) = 0;
0367 
0368 //-----------------------------------------------------------------------------
0369 //! Notify callback that a sendfile() request is pending.
0370 //!
0371 //! The File() method is called when Run() resulted in a sendfile response (i.e.
0372 //! sendfile() would have been used to send data to the client). This allows
0373 //! the callback to reframe the sendfile() data using the Send() method in the
0374 //! passed context object (see class Context above).
0375 //!
0376 //! @param  info    the context associated with the result.
0377 //! @param  dlen    total number of data bytes that would be sent to the client.
0378 //!
0379 //! @return true    continue normal processing.
0380 //!         false   terminate the bridge and close the link.
0381 //-----------------------------------------------------------------------------
0382 
0383 virtual int   File(Bridge::Context &info,  //!< the result context
0384                    int              dlen   //!< byte  count
0385                   ) = 0;
0386 
0387 //-----------------------------------------------------------------------------
0388 //! Notify callback that a write buffer is now available for reuse.
0389 //!
0390 //! The Free() method is called when Run() was called to write data and a buffer
0391 //! was supplied. Normally, he buffer is pinned and cannot be reused until the
0392 //! write completes. This callback provides the notification that the buffer is
0393 //! no longer in use. The callback is invoked prior to any other callbacks and
0394 //! is only invoked if a buffer was supplied.
0395 //!
0396 //! @param  info    the context associated with this call.
0397 //! @param  buffP   pointer to the buffer.
0398 //! @param  buffL   the length originally supplied in the Run() call.
0399 //-----------------------------------------------------------------------------
0400 
0401 virtual void  Free(Bridge::Context &info,  //!< the result context
0402                    char            *buffP, //!< pointer to the buffer
0403                    int              buffL  //!< original length to Run()
0404                   )
0405 {
0406   (void)info; (void)buffP; (void)buffL;
0407 }
0408 
0409 //-----------------------------------------------------------------------------
0410 //! Redirect the client to another host:port.
0411 //!
0412 //! The Redir() method is called when the client must be redirected to another
0413 //! host.
0414 //!
0415 //! @param  info    the context associated with the result.
0416 //! @param  port    the port number in host byte format.
0417 //! @param  hname   the DNS name of the host or IP address is IPV4 or IPV6
0418 //!                 format (i.e. "n.n.n.n" or "[ipv6_addr]").
0419 //!
0420 //! @return true    continue normal processing.
0421 //!         false   terminate the bridge and close the link.
0422 //-----------------------------------------------------------------------------
0423 
0424 virtual bool  Redir(Bridge::Context &info,   //!< the result context
0425                     int              port,   //!< the port number
0426                     const char      *hname   //!< the destination host
0427                    ) = 0;
0428 
0429 //-----------------------------------------------------------------------------
0430 //! Effect a client wait.
0431 //!
0432 //! The Wait() method is called when Run() needs to delay a request. Normally,
0433 //! delays are internally handled. However, you can request that delays be
0434 //! reflected via a callback using the Bridge SetWait() method.
0435 //!
0436 //! @param  info    the context associated with the result.
0437 //! @param  wtime   the number of seconds to delay the request.
0438 //! @param  wtext   a null terminated string describing the wait in human terms
0439 //!
0440 //! @return true    continue normal processing.
0441 //!         false   terminate the bridge and close the link.
0442 //-----------------------------------------------------------------------------
0443 
0444 virtual bool  Wait(Bridge::Context &info,   //!< the result context
0445                    int              wtime,  //!< the wait time
0446                    const char      *wtext   //!< associated message
0447                    )
0448 {
0449   (void)info; (void)wtime; (void)wtext;
0450   return false;
0451 }
0452 
0453 //-----------------------------------------------------------------------------
0454 //! Effect a client wait response (waitresp) NOT CURRENTLY IMPLEMENTED!
0455 //!
0456 //! The WaitResp() method is called when an operation ended with a wait for
0457 //! response (waitresp) condition. The wait for response condition indicates
0458 //! that the actual response will be delivered at a later time. You can use
0459 //! context object to determine the operation being delayed. This callback
0460 //! provides you the opportunity to say how the waitresp is to be handled.
0461 //!
0462 //! @param  info    the context associated with the result.
0463 //! @param  wtime   the number of seconds in which a response is expected.
0464 //! @param  wtext   a null terminated string describing the delay in human terms
0465 //!
0466 //! @return !0      pointer to the callback object whose appropriate method
0467 //!                 should be called when the actual response is generated.
0468 //! @return 0       the waitresp will be handled by the bridge application. The
0469 //!                 application is responsible for re-issuing the request when
0470 //!                 the final response is a wait.
0471 //-----------------------------------------------------------------------------
0472 virtual
0473 Bridge::Result *WaitResp(Bridge::Context &info,   //!< the result context
0474                          int              wtime,  //!< the wait time
0475                          const char      *wtext   //!< associated message
0476                         )
0477 {
0478   (void)info; (void)wtime; (void)wtext;
0479   return 0;
0480 }
0481 
0482 //-----------------------------------------------------------------------------
0483 //! Constructor & Destructor
0484 //-----------------------------------------------------------------------------
0485 
0486               Result() {}
0487 virtual      ~Result() {}
0488 };
0489 
0490 //-----------------------------------------------------------------------------
0491 //! Constructor & Destructor
0492 //-----------------------------------------------------------------------------
0493 
0494               Bridge() {}
0495 protected:
0496 virtual      ~Bridge() {}
0497 };
0498 }
0499 #endif