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