summaryrefslogtreecommitdiff
path: root/indra/llmessage/llurlrequest.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llurlrequest.h')
-rw-r--r--indra/llmessage/llurlrequest.h395
1 files changed, 395 insertions, 0 deletions
diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h
new file mode 100644
index 0000000000..38c801cb10
--- /dev/null
+++ b/indra/llmessage/llurlrequest.h
@@ -0,0 +1,395 @@
+/**
+ * @file llurlrequest.h
+ * @author Phoenix
+ * @date 2005-04-21
+ * @brief Declaration of url based requests on pipes.
+ *
+ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLURLREQUEST_H
+#define LL_LLURLREQUEST_H
+
+/**
+ * This file holds the declaration of useful classes for dealing with
+ * url based client requests.
+ */
+
+#include <string>
+#include "lliopipe.h"
+#include "llchainio.h"
+
+class LLURLRequestDetail;
+
+class LLURLRequestComplete;
+
+/**
+ * @class LLURLRequest
+ * @brief Class to handle url based requests.
+ * @see LLIOPipe
+ *
+ * Currently, this class is implemented on top of curl. From the
+ * vantage of a programmer using this class, you do not care so much,
+ * but it's useful to know since in order to accomplish 'non-blocking'
+ * behavior, we have to use a more expensive curl interface which can
+ * still block if the server enters a half-accepted state. It would be
+ * worth the time and effort to eventually port this to a raw client
+ * socket.
+ */
+class LLURLRequest : public LLIOPipe
+{
+public:
+ /**
+ * @brief This enumeration is for specifying the type of request.
+ */
+ enum ERequestAction
+ {
+ INVALID,
+ HTTP_GET,
+ HTTP_PUT,
+ HTTP_POST,
+ HTTP_DELETE,
+ REQUEST_ACTION_COUNT
+ };
+
+ /**
+ * @brief Constructor.
+ *
+ * @param action One of the ERequestAction enumerations.
+ */
+ LLURLRequest(ERequestAction action);
+
+ /**
+ * @brief Constructor.
+ *
+ * @param action One of the ERequestAction enumerations.
+ * @param url The url of the request. It should already be encoded.
+ */
+ LLURLRequest(ERequestAction action, const std::string& url);
+
+ /**
+ * @brief Destructor.
+ */
+ virtual ~LLURLRequest();
+
+ /* @name Instance methods
+ */
+ //@{
+ /**
+ * @brief Set the url for the request
+ *
+ * This method assumes the url is encoded appropriately for the
+ * request.
+ * The url must be set somehow before the first call to process(),
+ * or the url will not be set correctly.
+ *
+ */
+ void setURL(const std::string& url);
+
+ /**
+ * @brief Add a header to the http post.
+ *
+ * The header must be correctly formatted for HTTP requests. This
+ * provides a raw interface if you know what kind of request you
+ * will be making during construction of this instance. All
+ * required headers will be automatically constructed, so this is
+ * usually useful for encoding parameters.
+ */
+ void addHeader(const char* header);
+
+ /**
+ * @brief Check remote server certificate signed by a known root CA.
+ *
+ * Set whether request will check that remote server
+ * certificates are signed by a known root CA when using HTTPS.
+ * Use the supplied root certificate bundle if supplied, else use
+ * the standard bundle as found by libcurl and openssl.
+ */
+ void checkRootCertificate(bool check, const char* caBundle = NULL);
+
+ /**
+ * @brief Request a particular response encoding if available.
+ *
+ * This call is a shortcut for requesting a particular encoding
+ * from the server, eg, 'gzip'.
+ */
+ void requestEncoding(const char* encoding);
+
+ /**
+ * @brief Return at most size bytes of body.
+ *
+ * If the body had more bytes than this limit, they will not be
+ * returned and the connection closed. In this case, STATUS_STOP
+ * will be passed to responseStatus();
+ */
+ void setBodyLimit(U32 size);
+
+ /**
+ * @brief Set a completion callback for this URLRequest.
+ *
+ * The callback is added to this URLRequet's pump when either the
+ * entire buffer is known or an error like timeout or connection
+ * refused has happened. In the case of a complete transfer, this
+ * object builds a response chain such that the callback and the
+ * next process consumer get to read the output.
+ *
+ * This setup is a little fragile since the url request consumer
+ * might not just read the data - it may do a channel change,
+ * which invalidates the input to the callback, but it works well
+ * in practice.
+ */
+ void setCallback(LLURLRequestComplete* callback);
+ //@}
+
+ /**
+ * @ brief Set certificate authority file used to verify HTTPS certs.
+ */
+ static void setCertificateAuthorityFile(const std::string& file_name);
+
+ /**
+ * @ brief Set certificate authority path used to verify HTTPS certs.
+ */
+ static void setCertificateAuthorityPath(const std::string& path);
+
+ /* @name LLIOPipe virtual implementations
+ */
+public:
+ /**
+ * @brief Give this pipe a chance to handle a generated error
+ */
+ virtual EStatus handleError(EStatus status, LLPumpIO* pump);
+
+protected:
+ /**
+ * @brief Process the data in buffer
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
+
+protected:
+ enum EState
+ {
+ STATE_INITIALIZED,
+ STATE_WAITING_FOR_RESPONSE,
+ STATE_PROCESSING_RESPONSE,
+ STATE_HAVE_RESPONSE,
+ };
+ EState mState;
+ ERequestAction mAction;
+ LLURLRequestDetail* mDetail;
+ LLIOPipe::ptr_t mCompletionCallback;
+
+private:
+ /**
+ * @brief Initialize the object. Called during construction.
+ */
+ void initialize();
+
+ /**
+ * @brief Handle action specific url request configuration.
+ *
+ * @return Returns true if this is configured.
+ */
+ bool configure();
+
+ /**
+ * @brief Download callback method.
+ */
+ static size_t downCallback(
+ void* data,
+ size_t size,
+ size_t nmemb,
+ void* user);
+
+ /**
+ * @brief Upload callback method.
+ */
+ static size_t upCallback(
+ void* data,
+ size_t size,
+ size_t nmemb,
+ void* user);
+
+ /**
+ * @brief Declaration of unimplemented method to prevent copy
+ * construction.
+ */
+ LLURLRequest(const LLURLRequest&);
+};
+
+
+/**
+ * @class LLContextURLExtractor
+ * @brief This class unpacks the url out of a agent usher service so
+ * it can be packed into a LLURLRequest object.
+ * @see LLIOPipe
+ *
+ * This class assumes that the context is a map that contains an entry
+ * named CONTEXT_DEST_URI_SD_LABEL.
+ */
+class LLContextURLExtractor : public LLIOPipe
+{
+public:
+ LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
+ ~LLContextURLExtractor() {}
+
+protected:
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
+
+protected:
+ LLURLRequest* mRequest;
+};
+
+
+/**
+ * @class LLURLRequestComplete
+ * @brief Class which can optionally be used with an LLURLRequest to
+ * get notification when the url request is complete.
+ */
+class LLURLRequestComplete : public LLIOPipe
+{
+public:
+
+ virtual void header(const std::string& header, const std::string& value);
+ ///< Called once for each header received, prior to httpStatus
+
+ virtual void httpStatus(U32 status, const std::string& reason);
+ ///< Always called on request completion, prior to complete
+
+ virtual void complete(
+ const LLChannelDescriptors& channels,
+ const buffer_ptr_t& buffer);
+
+ /**
+ * @brief This method is called when we got a valid response.
+ *
+ * It is up to class implementers to do something useful here.
+ */
+ virtual void response(
+ const LLChannelDescriptors& channels,
+ const buffer_ptr_t& buffer);
+
+ /**
+ * @brief This method is called if there was no response.
+ *
+ * It is up to class implementers to do something useful here.
+ */
+ virtual void noResponse();
+
+ /**
+ * @brief This method will be called by the LLURLRequest object.
+ *
+ * If this is set to STATUS_OK or STATUS_STOP, then the transfer
+ * is asssumed to have worked. This will lead to calling response()
+ * on the next call to process(). Otherwise, this object will call
+ * noResponse() on the next call to process.
+ * @param status The status of the URLRequest.
+ */
+ void responseStatus(EStatus status);
+
+ // constructor & destructor.
+ LLURLRequestComplete();
+ virtual ~LLURLRequestComplete();
+
+protected:
+ /* @name LLIOPipe virtual implementations
+ */
+ //@{
+ /**
+ * @brief Process the data in buffer
+ */
+ virtual EStatus process_impl(
+ const LLChannelDescriptors& channels,
+ buffer_ptr_t& buffer,
+ bool& eos,
+ LLSD& context,
+ LLPumpIO* pump);
+ //@}
+
+ // value to note if we actually got the response. This value
+ // depends on correct useage from the LLURLRequest instance.
+ EStatus mRequestStatus;
+};
+
+
+/**
+ * @class LLURLRequestClientFactory
+ * @brief Template class to build url request based client chains
+ *
+ * This class eases construction of a basic sd rpc client. Here is an
+ * example of it's use:
+ * <code>
+ * class LLUsefulService : public LLService { ... }<br>
+ * LLService::registerCreator(<br>
+ * "useful",<br>
+ * LLService::creator_t(new LLURLRequestClientFactory<LLUsefulService>))<br>
+ * </code>
+ *
+ * This class should work, but I never got around to using/testing it.
+ *
+ */
+#if 0
+template<class Client>
+class LLURLRequestClientFactory : public LLChainIOFactory
+{
+public:
+ LLURLRequestClientFactory(LLURLRequest::ERequestAction action) {}
+ LLURLRequestClientFactory(
+ LLURLRequest::ERequestAction action,
+ const std::string& fixed_url) :
+ mAction(action),
+ mURL(fixed_url)
+ {
+ }
+ virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
+ {
+ lldebugs << "LLURLRequestClientFactory::build" << llendl;
+ LLIOPipe::ptr_t service(new Client);
+ chain.push_back(service);
+ LLURLRequest* http(new LLURLRequest(mAction));
+ LLIOPipe::ptr_t http_pipe(http);
+ // *FIX: how do we know the content type?
+ //http->addHeader("Content-Type: text/llsd");
+ if(mURL.empty())
+ {
+ chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
+ }
+ else
+ {
+ http->setURL(mURL);
+ }
+ chain.push_back(http_pipe);
+ chain.push_back(service);
+ return true;
+ }
+
+protected:
+ LLURLRequest::ERequestAction mAction;
+ std::string mURL;
+};
+#endif
+
+/**
+ * External constants
+ */
+extern const std::string CONTEXT_DEST_URI_SD_LABEL;
+
+#endif // LL_LLURLREQUEST_H