PageRenderTime 47ms CodeModel.GetById 35ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llmessage/llsdrpcclient.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 323 lines | 144 code | 22 blank | 157 comment | 4 complexity | 0e23164e0e7181bb31d38fa1d8ee8225 MD5 | raw file
  1/** 
  2 * @file llsdrpcclient.h
  3 * @author Phoenix
  4 * @date 2005-11-05
  5 * @brief Implementation and helpers for structure data RPC clients.
  6 *
  7 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#ifndef LL_LLSDRPCCLIENT_H
 30#define LL_LLSDRPCCLIENT_H
 31
 32/** 
 33 * This file declares classes to encapsulate a basic structured data
 34 * remote procedure client.
 35 */
 36
 37#include "llchainio.h"
 38#include "llfiltersd2xmlrpc.h"
 39#include "lliopipe.h"
 40#include "llurlrequest.h"
 41
 42/** 
 43 * @class LLSDRPCClientResponse
 44 * @brief Abstract base class to represent a response from an SD server.
 45 *
 46 * This is used as a base class for callbacks generated from an
 47 * structured data remote procedure call. The
 48 * <code>extractResponse</code> method will deal with the llsdrpc method
 49 * call overhead, and keep track of what to call during the next call
 50 * into <code>process</code>. If you use this as a base class, you
 51 * need to implement <code>response</code>, <code>fault</code>, and
 52 * <code>error</code> to do something useful. When in those methods,
 53 * you can parse and utilize the mReturnValue member data.
 54 */
 55class LLSDRPCResponse : public LLIOPipe
 56{
 57public:
 58	LLSDRPCResponse();
 59	virtual ~LLSDRPCResponse();
 60
 61	/** 
 62	 * @brief This method extracts the response out of the sd passed in
 63	 *
 64	 * Any appropriate data found in the sd passed in will be
 65	 * extracted and managed by this object - not copied or cloned. It
 66	 * will still be up to the caller to delete the pointer passed in.
 67	 * @param sd The raw structured data response from the remote server.
 68	 * @return Returns true if this was able to parse the structured data.
 69	 */
 70	bool extractResponse(const LLSD& sd);
 71
 72protected:
 73	/** 
 74	 * @brief Method called when the response is ready.
 75	 */
 76	virtual bool response(LLPumpIO* pump) = 0;
 77
 78	/** 
 79	 * @brief Method called when a fault is generated by the remote server.
 80	 */
 81	virtual bool fault(LLPumpIO* pump) = 0;
 82
 83	/** 
 84	 * @brief Method called when there was an error
 85	 */
 86	virtual bool error(LLPumpIO* pump) = 0;
 87
 88protected:
 89	/* @name LLIOPipe virtual implementations
 90	 */
 91	//@{
 92	/** 
 93	 * @brief Process the data in buffer
 94	 */
 95	virtual EStatus process_impl(
 96		const LLChannelDescriptors& channels,
 97		buffer_ptr_t& buffer,
 98		bool& eos,
 99		LLSD& context,
100		LLPumpIO* pump);
101	//@}
102	
103protected:
104	LLSD mReturnValue;
105	bool mIsError;
106	bool mIsFault;
107};
108
109/** 
110 * @class LLSDRPCClient
111 * @brief Client class for a structured data remote procedure call.
112 *
113 * This class helps deal with making structured data calls to a remote
114 * server. You can visualize the calls as:
115 * <code>
116 * response = uri.method(parameter)
117 * </code>
118 * where you pass in everything to <code>call</code> and this class
119 * takes care of the rest of the details.
120 * In typical usage, you will derive a class from this class and
121 * provide an API more useful for the specific application at
122 * hand. For example, if you were writing a service to send an instant
123 * message, you could create an API for it to send the messsage, and
124 * that class would do the work of translating it into the method and
125 * parameter, find the destination, and invoke <code>call</call> with
126 * a useful implementation of LLSDRPCResponse passed in to handle the
127 * response from the network.
128 */
129class LLSDRPCClient : public LLIOPipe
130{
131public:
132	LLSDRPCClient();
133	virtual ~LLSDRPCClient();
134
135	/** 
136	 * @brief Enumeration for tracking which queue to process the
137	 * response.
138	 */
139	enum EPassBackQueue
140	{
141		EPBQ_PROCESS,
142		EPBQ_CALLBACK,
143	};
144
145	/** 
146	 * @brief Call a method on a remote LLSDRPCServer
147	 *
148	 * @param uri The remote object to call, eg,
149	 * http://localhost/usher. If you are using a factory with a fixed
150	 * url, the uri passed in will probably be ignored.
151	 * @param method The method to call on the remote object
152	 * @param parameter The parameter to pass into the remote
153	 * object. It is up to the caller to delete the value passed in.
154	 * @param response The object which gets the response.
155	 * @param queue Specifies to call the response on the process or
156	 * callback queue.
157	 * @return Returns true if this object will be able to make the RPC call.
158	 */
159	bool call(
160		const std::string& uri,
161		const std::string& method,
162		const LLSD& parameter,
163		LLSDRPCResponse* response,
164		EPassBackQueue queue);
165
166	/** 
167	 * @brief Call a method on a remote LLSDRPCServer
168	 *
169	 * @param uri The remote object to call, eg,
170	 * http://localhost/usher. If you are using a factory with a fixed
171	 * url, the uri passed in will probably be ignored.
172	 * @param method The method to call on the remote object
173	 * @param parameter The seriailized parameter to pass into the
174	 * remote object.
175	 * @param response The object which gets the response.
176	 * @param queue Specifies to call the response on the process or
177	 * callback queue.
178	 * @return Returns true if this object will be able to make the RPC call.
179	 */
180	bool call(
181		const std::string& uri,
182		const std::string& method,
183		const std::string& parameter,
184		LLSDRPCResponse* response,
185		EPassBackQueue queue);
186
187protected:
188	/** 
189	 * @brief Enumeration for tracking client state.
190	 */
191	enum EState
192	{
193		STATE_NONE,
194		STATE_READY,
195		STATE_WAITING_FOR_RESPONSE,
196		STATE_DONE
197	};
198	
199	/* @name LLIOPipe virtual implementations
200	 */
201	//@{
202	/** 
203	 * @brief Process the data in buffer
204	 */
205	virtual EStatus process_impl(
206		const LLChannelDescriptors& channels,
207		buffer_ptr_t& buffer,
208		bool& eos,
209		LLSD& context,
210		LLPumpIO* pump);
211	//@}
212
213protected:
214	EState mState;
215	std::string mURI;
216	std::string mRequest;
217	EPassBackQueue mQueue;
218	LLIOPipe::ptr_t mResponse;
219};
220
221/** 
222 * @class LLSDRPCClientFactory
223 * @brief Basic implementation for making an SD RPC client factory
224 *
225 * This class eases construction of a basic sd rpc client. Here is an
226 * example of it's use:
227 * <code>
228 *  class LLUsefulService : public LLService { ... }
229 *  LLService::registerCreator(
230 *    "useful",
231 *    LLService::creator_t(new LLSDRPCClientFactory<LLUsefulService>))
232 * </code>
233 */
234template<class Client>
235class LLSDRPCClientFactory : public LLChainIOFactory
236{
237public:
238	LLSDRPCClientFactory() {}
239	LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
240	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
241	{
242		lldebugs << "LLSDRPCClientFactory::build" << llendl;
243		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
244		if(!http->isValid())
245		{
246			llwarns << "Creating LLURLRequest failed." << llendl ;
247			delete http;
248			return false;
249		}
250
251		LLIOPipe::ptr_t service(new Client);
252		chain.push_back(service);		
253		LLIOPipe::ptr_t http_pipe(http);
254		http->addHeader("Content-Type: text/llsd");
255		if(mURL.empty())
256		{
257			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
258		}
259		else
260		{
261			http->setURL(mURL);
262		}
263		chain.push_back(http_pipe);
264		chain.push_back(service);
265		return true;
266	}
267protected:
268	std::string mURL;
269};
270
271/** 
272 * @class LLXMLSDRPCClientFactory
273 * @brief Basic implementation for making an XMLRPC to SD RPC client factory
274 *
275 * This class eases construction of a basic sd rpc client which uses
276 * xmlrpc as a serialization grammar. Here is an example of it's use:
277 * <code>
278 *  class LLUsefulService : public LLService { ... }
279 *  LLService::registerCreator(
280 *    "useful",
281 *    LLService::creator_t(new LLXMLSDRPCClientFactory<LLUsefulService>))
282 * </code>
283 */
284template<class Client>
285class LLXMLSDRPCClientFactory : public LLChainIOFactory
286{
287public:
288	LLXMLSDRPCClientFactory() {}
289	LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
290	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
291	{
292		lldebugs << "LLXMLSDRPCClientFactory::build" << llendl;
293
294		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST));
295		if(!http->isValid())
296		{
297			llwarns << "Creating LLURLRequest failed." << llendl ;
298			delete http;
299			return false ;
300		}
301		LLIOPipe::ptr_t service(new Client);
302		chain.push_back(service);		
303		LLIOPipe::ptr_t http_pipe(http);
304		http->addHeader("Content-Type: text/xml");
305		if(mURL.empty())
306		{
307			chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
308		}
309		else
310		{
311			http->setURL(mURL);
312		}
313		chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest(NULL)));
314		chain.push_back(http_pipe);
315		chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
316		chain.push_back(service);
317		return true;
318	}
319protected:
320	std::string mURL;
321};
322
323#endif // LL_LLSDRPCCLIENT_H