summaryrefslogtreecommitdiff
path: root/indra/llmessage/llhttpclient.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llmessage/llhttpclient.cpp
Print done when done.
Diffstat (limited to 'indra/llmessage/llhttpclient.cpp')
-rw-r--r--indra/llmessage/llhttpclient.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
new file mode 100644
index 0000000000..38dee26723
--- /dev/null
+++ b/indra/llmessage/llhttpclient.cpp
@@ -0,0 +1,278 @@
+/**
+ * @file llhttpclient.cpp
+ * @brief Implementation of classes for making HTTP requests.
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+#include "llassetstorage.h"
+#include "llhttpclient.h"
+#include "lliopipe.h"
+#include "llurlrequest.h"
+#include "llbufferstream.h"
+#include "llsdserialize.h"
+#include "llvfile.h"
+#include "llvfs.h"
+
+static const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f;
+
+static std::string gCABundle;
+
+
+
+
+LLHTTPClient::Responder::Responder()
+ : mReferenceCount(0)
+{
+}
+
+LLHTTPClient::Responder::~Responder()
+{
+}
+
+// virtual
+void LLHTTPClient::Responder::error(U32 status, const std::string& reason)
+{
+ llinfos << "LLHTTPClient::Responder::error "
+ << status << ": " << reason << llendl;
+}
+
+// virtual
+void LLHTTPClient::Responder::result(const LLSD& content)
+{
+}
+
+// virtual
+void LLHTTPClient::Responder::completed(U32 status, const std::string& reason, const LLSD& content)
+{
+ if (200 <= status && status < 300)
+ {
+ result(content);
+ }
+ else
+ {
+ error(status, reason);
+ }
+}
+
+
+namespace
+{
+ class LLHTTPClientURLAdaptor : public LLURLRequestComplete
+ {
+ public:
+ LLHTTPClientURLAdaptor(LLHTTPClient::ResponderPtr responder)
+ : mResponder(responder),
+ mStatus(499), mReason("LLURLRequest complete w/no status")
+ {
+ }
+
+ ~LLHTTPClientURLAdaptor()
+ {
+ }
+
+ virtual void httpStatus(U32 status, const std::string& reason)
+ {
+ mStatus = status;
+ mReason = reason;
+ }
+
+ virtual void complete(const LLChannelDescriptors& channels,
+ const buffer_ptr_t& buffer)
+ {
+ LLBufferStream istr(channels, buffer.get());
+ LLSD content;
+
+ if (200 <= mStatus && mStatus < 300)
+ {
+ LLSDSerialize::fromXML(content, istr);
+ }
+
+ if (mResponder.get())
+ {
+ mResponder->completed(mStatus, mReason, content);
+ }
+ }
+
+ private:
+ LLHTTPClient::ResponderPtr mResponder;
+ U32 mStatus;
+ std::string mReason;
+ };
+
+ class Injector : public LLIOPipe
+ {
+ public:
+ virtual const char* contentType() = 0;
+ };
+
+ class LLSDInjector : public Injector
+ {
+ public:
+ LLSDInjector(const LLSD& sd) : mSD(sd) {}
+ virtual ~LLSDInjector() {}
+
+ const char* contentType() { return "application/xml"; }
+
+ virtual EStatus process_impl(const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
+ {
+ LLBufferStream ostream(channels, buffer.get());
+ LLSDSerialize::toXML(mSD, ostream);
+ eos = true;
+ return STATUS_DONE;
+ }
+
+ const LLSD mSD;
+ };
+
+ class FileInjector : public Injector
+ {
+ public:
+ FileInjector(const std::string& filename) : mFilename(filename) {}
+ virtual ~FileInjector() {}
+
+ const char* contentType() { return "application/octet-stream"; }
+
+ virtual EStatus process_impl(const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
+ {
+ LLBufferStream ostream(channels, buffer.get());
+
+ llifstream fstream(mFilename.c_str(), std::iostream::binary | std::iostream::out);
+ fstream.seekg(0, std::ios::end);
+ U32 fileSize = fstream.tellg();
+ fstream.seekg(0, std::ios::beg);
+ char* fileBuffer;
+ fileBuffer = new char [fileSize];
+ fstream.read(fileBuffer, fileSize);
+ ostream.write(fileBuffer, fileSize);
+ fstream.close();
+ eos = true;
+ return STATUS_DONE;
+ }
+
+ const std::string mFilename;
+ };
+
+ class VFileInjector : public Injector
+ {
+ public:
+ VFileInjector(const LLUUID& uuid, LLAssetType::EType asset_type) : mUUID(uuid), mAssetType(asset_type) {}
+ virtual ~VFileInjector() {}
+
+ const char* contentType() { return "application/octet-stream"; }
+
+ virtual EStatus process_impl(const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer, bool& eos, LLSD& context, LLPumpIO* pump)
+ {
+ LLBufferStream ostream(channels, buffer.get());
+
+ LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ);
+ S32 fileSize = vfile.getSize();
+ U8* fileBuffer;
+ fileBuffer = new U8 [fileSize];
+ vfile.read(fileBuffer, fileSize);
+ ostream.write((char*)fileBuffer, fileSize);
+ eos = true;
+ return STATUS_DONE;
+ }
+
+ const LLUUID mUUID;
+ LLAssetType::EType mAssetType;
+ };
+
+
+ LLPumpIO* theClientPump = NULL;
+}
+
+static void request(const std::string& url, LLURLRequest::ERequestAction method,
+ Injector* body_injector, LLHTTPClient::ResponderPtr responder)
+{
+ if (!LLHTTPClient::hasPump())
+ {
+ responder->completed(U32_MAX, "No pump", LLSD());
+ return;
+ }
+
+ LLPumpIO::chain_t chain;
+
+ LLURLRequest *req = new LLURLRequest(method, url);
+ req->requestEncoding("");
+ if (!gCABundle.empty())
+ {
+ req->checkRootCertificate(true, gCABundle.c_str());
+ }
+ req->setCallback(new LLHTTPClientURLAdaptor(responder));
+
+ if (method == LLURLRequest::HTTP_PUT || method == LLURLRequest::HTTP_POST)
+ {
+ req->addHeader(llformat("Content-Type: %s", body_injector->contentType()).c_str());
+ chain.push_back(LLIOPipe::ptr_t(body_injector));
+ }
+ chain.push_back(LLIOPipe::ptr_t(req));
+
+ theClientPump->addChain(chain, HTTP_REQUEST_EXPIRY_SECS);
+}
+
+void LLHTTPClient::get(const std::string& url, ResponderPtr responder)
+{
+ request(url, LLURLRequest::HTTP_GET, NULL, responder);
+}
+
+void LLHTTPClient::put(const std::string& url, const LLSD& body, ResponderPtr responder)
+{
+ request(url, LLURLRequest::HTTP_PUT, new LLSDInjector(body), responder);
+}
+
+void LLHTTPClient::post(const std::string& url, const LLSD& body, ResponderPtr responder)
+{
+ request(url, LLURLRequest::HTTP_POST, new LLSDInjector(body), responder);
+}
+
+#if 1
+void LLHTTPClient::postFile(const std::string& url, const std::string& filename, ResponderPtr responder)
+{
+ request(url, LLURLRequest::HTTP_POST, new FileInjector(filename), responder);
+}
+
+void LLHTTPClient::postFile(const std::string& url, const LLUUID& uuid,
+ LLAssetType::EType asset_type, ResponderPtr responder)
+{
+ request(url, LLURLRequest::HTTP_POST, new VFileInjector(uuid, asset_type), responder);
+}
+#endif
+
+void LLHTTPClient::setPump(LLPumpIO& pump)
+{
+ theClientPump = &pump;
+}
+
+bool LLHTTPClient::hasPump()
+{
+ return theClientPump != NULL;
+}
+
+void LLHTTPClient::setCABundle(const std::string& caBundle)
+{
+ gCABundle = caBundle;
+}
+
+namespace boost
+{
+ void intrusive_ptr_add_ref(LLHTTPClient::Responder* p)
+ {
+ ++p->mReferenceCount;
+ }
+
+ void intrusive_ptr_release(LLHTTPClient::Responder* p)
+ {
+ if(0 == --p->mReferenceCount)
+ {
+ delete p;
+ }
+ }
+};
+