XRootD
XrdHttpTpcState.hh
Go to the documentation of this file.
1 
6 #ifndef __XRD_TPC_STATE_HH__
7 #define __XRD_TPC_STATE_HH__
8 
9 #include <memory>
10 #include <vector>
11 
12 // Forward dec'ls
13 class XrdSfsFile;
14 class XrdHttpExtReq;
15 typedef void CURL;
16 struct curl_slist;
17 
18 namespace TPC {
19 class Stream;
20 
21 class State {
22 public:
23 
24  // Error codes recorded on a transfer state. They are exposed so that the
25  // TPC handler is able to tell the various failure modes apart when it
26  // composes the error sent back to the client.
27  enum ErrorCode {
28  errNone = 0,
29  errWrite = 1, // Failure while writing the received data to the local file.
30  errFlush = 2, // Failure while flushing the local file.
31  errClose = 3, // Failure while closing the local file.
32  errTimeout = 10 // The transfer did not make any progress within the timeout.
33  };
34 
35  State() :
36  m_push(true),
37  m_recv_status_line(false),
38  m_recv_all_headers(false),
39  m_offset(0),
40  m_start_offset(0),
41  m_status_code(-1),
42  m_error_code(0),
43  m_content_length(-1),
44  m_stream(NULL),
45  m_curl(NULL),
46  m_headers(NULL),
47  m_is_transfer_state(true)
48  {}
49 
56  State(CURL * curl, bool tpcForwardCreds):
57  m_push(true),
58  m_recv_status_line(false),
59  m_recv_all_headers(false),
60  m_offset(0),
61  m_start_offset(0),
62  m_status_code(-1),
63  m_error_code(0),
64  m_content_length(-1),
65  m_push_length(-1),
66  m_stream(NULL),
67  m_curl(curl),
68  m_headers(NULL),
69  m_is_transfer_state(false),
70  tpcForwardCreds(tpcForwardCreds)
71  {
72  InstallHandlers(curl);
73  }
74 
75  // Note that we are "borrowing" a reference to the curl handle;
76  // it is not owned / freed by the State object. However, we use it
77  // as if there's only one handle per State.
78  State (off_t start_offset, Stream &stream, CURL *curl, bool push, bool tpcForwardCreds) :
79  m_push(push),
80  m_recv_status_line(false),
81  m_recv_all_headers(false),
82  m_offset(0),
83  m_start_offset(start_offset),
84  m_status_code(-1),
85  m_error_code(0),
86  m_content_length(-1),
87  m_push_length(-1),
88  m_stream(&stream),
89  m_curl(curl),
90  m_headers(NULL),
91  m_is_transfer_state(true),
92  tpcForwardCreds(tpcForwardCreds)
93  {
94  InstallHandlers(curl);
95  }
96 
97  ~State();
98 
99  void SetTransferParameters(off_t offset, size_t size);
100 
101  void SetupHeaders(XrdHttpExtReq &req);
102 
104 
105  off_t BytesTransferred() const {return m_offset;}
106 
107  void SetContentLength(const off_t content_length) { m_content_length = content_length; }
108 
109  off_t GetContentLength() const {return m_content_length;}
110 
111  const std::map<std::string, std::string> & GetReprDigest() const { return m_repr_digests; }
112 
113  int GetErrorCode() const {return m_error_code;}
114 
115  void SetErrorCode(int error_code) {m_error_code = error_code;}
116 
117  int GetStatusCode() const {return m_status_code;}
118 
119  std::string GetErrorMessage() const {return m_error_buf;}
120 
121  void SetErrorMessage(const std::string &error_msg) {m_error_buf = error_msg;}
122 
123  // Error recorded while flushing and closing the local file at the end of the
124  // transfer (see Flush() and Finalize()). It is deliberately kept apart from
125  // the transfer error above: a failure to flush or close the file must not
126  // hide the reason why the transfer itself failed, e.g. a libcurl error or a
127  // stalled transfer.
128  int GetFinalizeErrorCode() const {return m_finalize_error_code;}
129 
130  std::string GetFinalizeErrorMessage() const {return m_finalize_error_buf;}
131 
132  void ResetAfterRequest();
133 
134  CURL *GetHandle() const {return m_curl;}
135 
136  int AvailableBuffers() const;
137 
138  void DumpBuffers() const;
139 
140  // Returns true if at least one byte of the response has been received,
141  // but not the entire contents of the response.
142  bool BodyTransferInProgress() const {return m_offset && (m_offset != m_content_length);}
143 
144  // Duplicate the current state; all settings are copied over, but those
145  // related to the transient state are reset as if from a constructor.
146  State *Duplicate();
147 
148  // Move the contents of a State object. To be replaced by a move
149  // constructor once C++11 is allowed in XRootD.
150  void Move (State &other);
151 
152  // Flush and finalize a transfer state. Eventually calls close() on the underlying
153  // file handle, which should hopefully synchronize the file metadata across
154  // all readers (even other load-balanced servers on the same distributed file
155  // system).
156  //
157  // Returns true on success; false otherwise. Failures can happen, for example, if
158  // not all buffers have been reordered by the underlying stream. A failure is
159  // recorded in the finalization error (GetFinalizeErrorCode()), not in the
160  // transfer error.
161  bool Finalize();
162 
163  // Flush the data in memory to disk, even if it may cause unaligned or short
164  // writes. Typically, only done while shutting down the transfer (note some
165  // backends may be unable to handle unaligned writes unless it's the last write).
166  // Returns -1 on failure, in which case the error is recorded in the
167  // finalization error (GetFinalizeErrorCode()), not in the transfer error.
168  int Flush();
169 
170  // Retrieve the description of the remote connection; is of the form:
171  // tcp:129.93.3.4:1234
172  // tcp:[2600:900:6:1301:268a:7ff:fef6:a590]:2345
173  // This is meant to facilitate the monitoring via the performance markers.
174  std::string GetConnectionDescription();
175 
176 private:
177  bool InstallHandlers(CURL *curl);
178 
179  // Record a failure that happened while flushing or closing the local file.
180  // Only the first failure is kept: the ones that follow are almost always a
181  // consequence of it.
182  void RecordFinalizeError(int error_code, const std::string &error_msg);
183 
184  State(const State&);
185  // Add back once C++11 is available
186  //State(State &&) noexcept;
187 
188  // libcurl callback functions, along with the corresponding class methods.
189  static size_t HeaderCB(char *buffer, size_t size, size_t nitems,
190  void *userdata);
191  int Header(const std::string &header);
192  static size_t WriteCB(void *buffer, size_t size, size_t nitems, void *userdata);
193  ssize_t Write(char *buffer, size_t size);
198  static size_t PushRespCB(void *buffer, size_t size, size_t nitems, void *userdata);
199  static size_t ReadCB(void *buffer, size_t size, size_t nitems, void *userdata);
200  int Read(char *buffer, size_t size);
201 
202  bool m_push; // whether we are transferring in "push-mode"
203  bool m_recv_status_line; // whether we have received a status line in the response from the remote host.
204  bool m_recv_all_headers; // true if we have seen the end of headers.
205  off_t m_offset; // number of bytes we have received.
206  off_t m_start_offset; // offset where we started in the file.
207  int m_status_code; // status code from HTTP response.
208  int m_error_code; // error code from underlying stream operations.
209  off_t m_content_length; // value of Content-Length header, if we received one.
210  off_t m_push_length; // For push transfers, the size of the file on our server.
211  Stream *m_stream; // stream corresponding to this transfer.
212  CURL *m_curl; // libcurl handle
213  struct curl_slist *m_headers; // any headers we set as part of the libcurl request.
214  std::vector<std::string> m_headers_copy; // Copies of custom headers.
215  std::string m_resp_protocol; // Response protocol in the HTTP status line.
216  std::string m_error_buf; // Any error associated with a response.
217  int m_finalize_error_code = 0; // error code from flushing / closing the local file.
218  std::string m_finalize_error_buf; // error message from flushing / closing the local file.
219  bool m_is_transfer_state; // If set to true, this state will be used to perform some transfers
220  bool tpcForwardCreds = false; // if set to true, the redirection will send user credentials to the redirection host
221  std::map<std::string, std::string> m_repr_digests; // Repr-Digest values received from the passive server (PULL)
222 };
223 
224 };
225 
226 #endif
void CURL
void CURL
State(off_t start_offset, Stream &stream, CURL *curl, bool push, bool tpcForwardCreds)
int GetFinalizeErrorCode() const
State * Duplicate()
void Move(State &other)
int GetStatusCode() const
CURL * GetHandle() const
void DumpBuffers() const
off_t BytesTransferred() const
bool BodyTransferInProgress() const
void SetErrorMessage(const std::string &error_msg)
void ResetAfterRequest()
int GetErrorCode() const
void SetTransferParameters(off_t offset, size_t size)
std::string GetFinalizeErrorMessage() const
std::string GetErrorMessage() const
std::string GetConnectionDescription()
void SetupHeaders(XrdHttpExtReq &req)
void SetContentLength(const off_t content_length)
off_t GetContentLength() const
void SetErrorCode(int error_code)
State(CURL *curl, bool tpcForwardCreds)
const std::map< std::string, std::string > & GetReprDigest() const
void SetupHeadersForHEAD(XrdHttpExtReq &req)
int AvailableBuffers() const