diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/llhttpclient.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llmessage/llhttpclient.cpp | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llhttpclient.cpp b/linden/indra/llmessage/llhttpclient.cpp new file mode 100644 index 0000000..5f75e59 --- /dev/null +++ b/linden/indra/llmessage/llhttpclient.cpp | |||
@@ -0,0 +1,297 @@ | |||
1 | /** | ||
2 | * @file llhttpclient.cpp | ||
3 | * @brief Implementation of classes for making HTTP requests. | ||
4 | * | ||
5 | * Copyright (c) 2006-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "linden_common.h" | ||
29 | #include "llassetstorage.h" | ||
30 | #include "llhttpclient.h" | ||
31 | #include "lliopipe.h" | ||
32 | #include "llurlrequest.h" | ||
33 | #include "llbufferstream.h" | ||
34 | #include "llsdserialize.h" | ||
35 | #include "llvfile.h" | ||
36 | #include "llvfs.h" | ||
37 | |||
38 | static const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; | ||
39 | |||
40 | static std::string gCABundle; | ||
41 | |||
42 | |||
43 | |||
44 | |||
45 | LLHTTPClient::Responder::Responder() | ||
46 | : mReferenceCount(0) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | LLHTTPClient::Responder::~Responder() | ||
51 | { | ||
52 | } | ||
53 | |||
54 | // virtual | ||
55 | void LLHTTPClient::Responder::error(U32 status, const std::string& reason) | ||
56 | { | ||
57 | llinfos << "LLHTTPClient::Responder::error " | ||
58 | << status << ": " << reason << llendl; | ||
59 | } | ||
60 | |||
61 | // virtual | ||
62 | void LLHTTPClient::Responder::result(const LLSD& content) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | // virtual | ||
67 | void LLHTTPClient::Responder::completed(U32 status, const std::string& reason, const LLSD& content) | ||
68 | { | ||
69 | if (200 <= status && status < 300) | ||
70 | { | ||
71 | result(content); | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | error(status, reason); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | |||
80 | namespace | ||
81 | { | ||
82 | class LLHTTPClientURLAdaptor : public LLURLRequestComplete | ||
83 | { | ||
84 | public: | ||
85 | LLHTTPClientURLAdaptor(LLHTTPClient::ResponderPtr responder) | ||
86 | : mResponder(responder), | ||
87 | mStatus(499), mReason("LLURLRequest complete w/no status") | ||
88 | { | ||
89 | } | ||
90 | |||
91 | ~LLHTTPClientURLAdaptor() | ||
92 | { | ||
93 | } | ||
94 | |||
95 | virtual void httpStatus(U32 status, const std::string& reason) | ||
96 | { | ||
97 | mStatus = status; | ||
98 | mReason = reason; | ||
99 | } | ||
100 | |||
101 | virtual void complete(const LLChannelDescriptors& channels, | ||
102 | const buffer_ptr_t& buffer) | ||
103 | { | ||
104 | LLBufferStream istr(channels, buffer.get()); | ||
105 | LLSD content; | ||
106 | |||
107 | if (200 <= mStatus && mStatus < 300) | ||
108 | { | ||
109 | LLSDSerialize::fromXML(content, istr); | ||
110 | } | ||
111 | |||
112 | if (mResponder.get()) | ||
113 | { | ||
114 | mResponder->completed(mStatus, mReason, content); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | private: | ||
119 | LLHTTPClient::ResponderPtr mResponder; | ||
120 | U32 mStatus; | ||
121 | std::string mReason; | ||
122 | }; | ||
123 | |||
124 | class Injector : public LLIOPipe | ||
125 | { | ||
126 | public: | ||
127 | virtual const char* contentType() = 0; | ||
128 | }; | ||
129 | |||
130 | class LLSDInjector : public Injector | ||
131 | { | ||
132 | public: | ||
133 | LLSDInjector(const LLSD& sd) : mSD(sd) {} | ||
134 | virtual ~LLSDInjector() {} | ||
135 | |||
136 | const char* contentType() { return "application/xml"; } | ||
137 | |||
138 | virtual EStatus process_impl(const LLChannelDescriptors& channels, | ||
139 | buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) | ||
140 | { | ||
141 | LLBufferStream ostream(channels, buffer.get()); | ||
142 | LLSDSerialize::toXML(mSD, ostream); | ||
143 | eos = true; | ||
144 | return STATUS_DONE; | ||
145 | } | ||
146 | |||
147 | const LLSD mSD; | ||
148 | }; | ||
149 | |||
150 | class FileInjector : public Injector | ||
151 | { | ||
152 | public: | ||
153 | FileInjector(const std::string& filename) : mFilename(filename) {} | ||
154 | virtual ~FileInjector() {} | ||
155 | |||
156 | const char* contentType() { return "application/octet-stream"; } | ||
157 | |||
158 | virtual EStatus process_impl(const LLChannelDescriptors& channels, | ||
159 | buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) | ||
160 | { | ||
161 | LLBufferStream ostream(channels, buffer.get()); | ||
162 | |||
163 | llifstream fstream(mFilename.c_str(), std::iostream::binary | std::iostream::out); | ||
164 | fstream.seekg(0, std::ios::end); | ||
165 | U32 fileSize = fstream.tellg(); | ||
166 | fstream.seekg(0, std::ios::beg); | ||
167 | char* fileBuffer; | ||
168 | fileBuffer = new char [fileSize]; | ||
169 | fstream.read(fileBuffer, fileSize); | ||
170 | ostream.write(fileBuffer, fileSize); | ||
171 | fstream.close(); | ||
172 | eos = true; | ||
173 | return STATUS_DONE; | ||
174 | } | ||
175 | |||
176 | const std::string mFilename; | ||
177 | }; | ||
178 | |||
179 | class VFileInjector : public Injector | ||
180 | { | ||
181 | public: | ||
182 | VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {} | ||
183 | virtual ~VFileInjector() {} | ||
184 | |||
185 | const char* contentType() { return "application/octet-stream"; } | ||
186 | |||
187 | virtual EStatus process_impl(const LLChannelDescriptors& channels, | ||
188 | buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump) | ||
189 | { | ||
190 | LLBufferStream ostream(channels, buffer.get()); | ||
191 | |||
192 | LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ); | ||
193 | S32 fileSize = vfile.getSize(); | ||
194 | U8* fileBuffer; | ||
195 | fileBuffer = new U8 [fileSize]; | ||
196 | vfile.read(fileBuffer, fileSize); | ||
197 | ostream.write((char*)fileBuffer, fileSize); | ||
198 | eos = true; | ||
199 | return STATUS_DONE; | ||
200 | } | ||
201 | |||
202 | const LLUUID mUUID; | ||
203 | LLAssetType::EType mAssetType; | ||
204 | }; | ||
205 | |||
206 | |||
207 | LLPumpIO* theClientPump = NULL; | ||
208 | } | ||
209 | |||
210 | static void request(const std::string& url, LLURLRequest::ERequestAction method, | ||
211 | Injector* body_injector, LLHTTPClient::ResponderPtr responder) | ||
212 | { | ||
213 | if (!LLHTTPClient::hasPump()) | ||
214 | { | ||
215 | responder->completed(U32_MAX, "No pump", LLSD()); | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | LLPumpIO::chain_t chain; | ||
220 | |||
221 | LLURLRequest *req = new LLURLRequest(method, url); | ||
222 | req->requestEncoding(""); | ||
223 | if (!gCABundle.empty()) | ||
224 | { | ||
225 | req->checkRootCertificate(true, gCABundle.c_str()); | ||
226 | } | ||
227 | req->setCallback(new LLHTTPClientURLAdaptor(responder)); | ||
228 | |||
229 | if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST) | ||
230 | { | ||
231 | req->addHeader(llformat("Content-Type: %s", body_injector->contentType()).c_str()); | ||
232 | chain.push_back(LLIOPipe::ptr_t(body_injector)); | ||
233 | } | ||
234 | chain.push_back(LLIOPipe::ptr_t(req)); | ||
235 | |||
236 | theClientPump->addChain(chain, HTTP_REQUEST_EXPIRY_SECS); | ||
237 | } | ||
238 | |||
239 | void LLHTTPClient::get(const std::string& url, ResponderPtr responder) | ||
240 | { | ||
241 | request(url, LLURLRequest::HTTP_GET, NULL, responder); | ||
242 | } | ||
243 | |||
244 | void LLHTTPClient::put(const std::string& url, const LLSD& body, ResponderPtr responder) | ||
245 | { | ||
246 | request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder); | ||
247 | } | ||
248 | |||
249 | void LLHTTPClient::post(const std::string& url, const LLSD& body, ResponderPtr responder) | ||
250 | { | ||
251 | request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder); | ||
252 | } | ||
253 | |||
254 | #if 1 | ||
255 | void LLHTTPClient::postFile(const std::string& url, const std::string& filename, ResponderPtr responder) | ||
256 | { | ||
257 | request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder); | ||
258 | } | ||
259 | |||
260 | void LLHTTPClient::postFile(const std::string& url, const LLUUID& uuid, | ||
261 | LLAssetType::EType asset_type, ResponderPtr responder) | ||
262 | { | ||
263 | request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder); | ||
264 | } | ||
265 | #endif | ||
266 | |||
267 | void LLHTTPClient::setPump(LLPumpIO& pump) | ||
268 | { | ||
269 | theClientPump = &pump; | ||
270 | } | ||
271 | |||
272 | bool LLHTTPClient::hasPump() | ||
273 | { | ||
274 | return theClientPump != NULL; | ||
275 | } | ||
276 | |||
277 | void LLHTTPClient::setCABundle(const std::string& caBundle) | ||
278 | { | ||
279 | gCABundle = caBundle; | ||
280 | } | ||
281 | |||
282 | namespace boost | ||
283 | { | ||
284 | void intrusive_ptr_add_ref(LLHTTPClient::Responder* p) | ||
285 | { | ||
286 | ++p->mReferenceCount; | ||
287 | } | ||
288 | |||
289 | void intrusive_ptr_release(LLHTTPClient::Responder* p) | ||
290 | { | ||
291 | if(0 == --p->mReferenceCount) | ||
292 | { | ||
293 | delete p; | ||
294 | } | ||
295 | } | ||
296 | }; | ||
297 | |||