aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llhttpclient.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/llhttpclient.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp297
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
38static const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
39
40static std::string gCABundle;
41
42
43
44
45LLHTTPClient::Responder::Responder()
46 : mReferenceCount(0)
47{
48}
49
50LLHTTPClient::Responder::~Responder()
51{
52}
53
54// virtual
55void LLHTTPClient::Responder::error(U32 status, const std::string& reason)
56{
57 llinfos << "LLHTTPClient::Responder::error "
58 << status << ": " << reason << llendl;
59}
60
61// virtual
62void LLHTTPClient::Responder::result(const LLSD& content)
63{
64}
65
66// virtual
67void 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
80namespace
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
210static 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
239void LLHTTPClient::get(const std::string& url, ResponderPtr responder)
240{
241 request(url, LLURLRequest::HTTP_GET, NULL, responder);
242}
243
244void LLHTTPClient::put(const std::string& url, const LLSD& body, ResponderPtr responder)
245{
246 request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder);
247}
248
249void 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
255void 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
260void 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
267void LLHTTPClient::setPump(LLPumpIO& pump)
268{
269 theClientPump = &pump;
270}
271
272bool LLHTTPClient::hasPump()
273{
274 return theClientPump != NULL;
275}
276
277void LLHTTPClient::setCABundle(const std::string& caBundle)
278{
279 gCABundle = caBundle;
280}
281
282namespace 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