diff options
author | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2007-01-02 08:33:20 +0000 |
commit | 420b91db29485df39fd6e724e782c449158811cb (patch) | |
tree | b471a94563af914d3ed3edd3e856d21cb1b69945 /indra/llmessage/llsdrpcclient.h |
Print done when done.
Diffstat (limited to 'indra/llmessage/llsdrpcclient.h')
-rw-r--r-- | indra/llmessage/llsdrpcclient.h | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h new file mode 100644 index 0000000000..173a0d1dbb --- /dev/null +++ b/indra/llmessage/llsdrpcclient.h @@ -0,0 +1,291 @@ +/** + * @file llsdrpcclient.h + * @author Phoenix + * @date 2005-11-05 + * @brief Implementation and helpers for structure data RPC clients. + * + * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#ifndef LL_LLSDRPCCLIENT_H +#define LL_LLSDRPCCLIENT_H + +/** + * This file declares classes to encapsulate a basic structured data + * remote procedure client. + */ + +#include "llchainio.h" +#include "llfiltersd2xmlrpc.h" +#include "lliopipe.h" +#include "llurlrequest.h" + +/** + * @class LLSDRPCClientResponse + * @brief Abstract base class to represent a response from an SD server. + * + * This is used as a base class for callbacks generated from an + * structured data remote procedure call. The + * <code>extractResponse</code> method will deal with the llsdrpc method + * call overhead, and keep track of what to call during the next call + * into <code>process</code>. If you use this as a base class, you + * need to implement <code>response</code>, <code>fault</code>, and + * <code>error</code> to do something useful. When in those methods, + * you can parse and utilize the mReturnValue member data. + */ +class LLSDRPCResponse : public LLIOPipe +{ +public: + LLSDRPCResponse(); + virtual ~LLSDRPCResponse(); + + /** + * @brief This method extracts the response out of the sd passed in + * + * Any appropriate data found in the sd passed in will be + * extracted and managed by this object - not copied or cloned. It + * will still be up to the caller to delete the pointer passed in. + * @param sd The raw structured data response from the remote server. + * @return Returns true if this was able to parse the structured data. + */ + bool extractResponse(const LLSD& sd); + +protected: + /** + * @brief Method called when the response is ready. + */ + virtual bool response(LLPumpIO* pump) = 0; + + /** + * @brief Method called when a fault is generated by the remote server. + */ + virtual bool fault(LLPumpIO* pump) = 0; + + /** + * @brief Method called when there was an error + */ + virtual bool error(LLPumpIO* pump) = 0; + +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: + LLSD mReturnValue; + bool mIsError; + bool mIsFault; +}; + +/** + * @class LLSDRPCClient + * @brief Client class for a structured data remote procedure call. + * + * This class helps deal with making structured data calls to a remote + * server. You can visualize the calls as: + * <code> + * response = uri.method(parameter) + * </code> + * where you pass in everything to <code>call</code> and this class + * takes care of the rest of the details. + * In typical usage, you will derive a class from this class and + * provide an API more useful for the specific application at + * hand. For example, if you were writing a service to send an instant + * message, you could create an API for it to send the messsage, and + * that class would do the work of translating it into the method and + * parameter, find the destination, and invoke <code>call</call> with + * a useful implementation of LLSDRPCResponse passed in to handle the + * response from the network. + */ +class LLSDRPCClient : public LLIOPipe +{ +public: + LLSDRPCClient(); + virtual ~LLSDRPCClient(); + + /** + * @brief Enumeration for tracking which queue to process the + * response. + */ + enum EPassBackQueue + { + EPBQ_PROCESS, + EPBQ_CALLBACK, + }; + + /** + * @brief Call a method on a remote LLSDRPCServer + * + * @param uri The remote object to call, eg, + * http://localhost/usher. If you are using a factory with a fixed + * url, the uri passed in will probably be ignored. + * @param method The method to call on the remote object + * @param parameter The parameter to pass into the remote + * object. It is up to the caller to delete the value passed in. + * @param response The object which gets the response. + * @param queue Specifies to call the response on the process or + * callback queue. + * @return Returns true if this object will be able to make the RPC call. + */ + bool call( + const std::string& uri, + const std::string& method, + const LLSD& parameter, + LLSDRPCResponse* response, + EPassBackQueue queue); + + /** + * @brief Call a method on a remote LLSDRPCServer + * + * @param uri The remote object to call, eg, + * http://localhost/usher. If you are using a factory with a fixed + * url, the uri passed in will probably be ignored. + * @param method The method to call on the remote object + * @param parameter The seriailized parameter to pass into the + * remote object. + * @param response The object which gets the response. + * @param queue Specifies to call the response on the process or + * callback queue. + * @return Returns true if this object will be able to make the RPC call. + */ + bool call( + const std::string& uri, + const std::string& method, + const std::string& parameter, + LLSDRPCResponse* response, + EPassBackQueue queue); + +protected: + /** + * @brief Enumeration for tracking client state. + */ + enum EState + { + STATE_NONE, + STATE_READY, + STATE_WAITING_FOR_RESPONSE, + STATE_DONE + }; + + /* @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: + EState mState; + std::string mURI; + std::string mRequest; + EPassBackQueue mQueue; + LLIOPipe::ptr_t mResponse; +}; + +/** + * @class LLSDRPCClientFactory + * @brief Basic implementation for making an SD RPC client factory + * + * This class eases construction of a basic sd rpc client. Here is an + * example of it's use: + * <code> + * class LLUsefulService : public LLService { ... } + * LLService::registerCreator( + * "useful", + * LLService::creator_t(new LLSDRPCClientFactory<LLUsefulService>)) + * </code> + */ +template<class Client> +class LLSDRPCClientFactory : public LLChainIOFactory +{ +public: + LLSDRPCClientFactory() {} + LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {} + virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const + { + lldebugs << "LLSDRPCClientFactory::build" << llendl; + LLIOPipe::ptr_t service(new Client); + chain.push_back(service); + LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); + LLIOPipe::ptr_t http_pipe(http); + 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: + std::string mURL; +}; + +/** + * @class LLXMLSDRPCClientFactory + * @brief Basic implementation for making an XMLRPC to SD RPC client factory + * + * This class eases construction of a basic sd rpc client which uses + * xmlrpc as a serialization grammar. Here is an example of it's use: + * <code> + * class LLUsefulService : public LLService { ... } + * LLService::registerCreator( + * "useful", + * LLService::creator_t(new LLXMLSDRPCClientFactory<LLUsefulService>)) + * </code> + */ +template<class Client> +class LLXMLSDRPCClientFactory : public LLChainIOFactory +{ +public: + LLXMLSDRPCClientFactory() {} + LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {} + virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const + { + lldebugs << "LLXMLSDRPCClientFactory::build" << llendl; + LLIOPipe::ptr_t service(new Client); + chain.push_back(service); + LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); + LLIOPipe::ptr_t http_pipe(http); + http->addHeader("Content-Type: text/xml"); + if(mURL.empty()) + { + chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http))); + } + else + { + http->setURL(mURL); + } + chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest(NULL))); + chain.push_back(http_pipe); + chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD)); + chain.push_back(service); + return true; + } +protected: + std::string mURL; +}; + +#endif // LL_LLSDRPCCLIENT_H |