aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llsdrpcserver.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/llsdrpcserver.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/llsdrpcserver.cpp341
1 files changed, 341 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llsdrpcserver.cpp b/linden/indra/llmessage/llsdrpcserver.cpp
new file mode 100644
index 0000000..67eaf33
--- /dev/null
+++ b/linden/indra/llmessage/llsdrpcserver.cpp
@@ -0,0 +1,341 @@
1/**
2 * @file llsdrpcserver.cpp
3 * @author Phoenix
4 * @date 2005-10-11
5 * @brief Implementation of the LLSDRPCServer and related classes.
6 *
7 * Copyright (c) 2005-2007, Linden Research, Inc.
8 *
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception
20 *
21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above,
23 * and agree to abide by those obligations.
24 *
25 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
26 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27 * COMPLETENESS OR PERFORMANCE.
28 */
29
30#include "linden_common.h"
31#include "llsdrpcserver.h"
32
33#include "llbuffer.h"
34#include "llbufferstream.h"
35#include "llmemtype.h"
36#include "llpumpio.h"
37#include "llsdserialize.h"
38#include "llstl.h"
39
40static const char FAULT_PART_1[] = "{'fault':{'code':i";
41static const char FAULT_PART_2[] = ", 'description':'";
42static const char FAULT_PART_3[] = "'}}";
43
44static const char RESPONSE_PART_1[] = "{'response':";
45static const char RESPONSE_PART_2[] = "}";
46
47static const S32 FAULT_GENERIC = 1000;
48static const S32 FAULT_METHOD_NOT_FOUND = 1001;
49
50static const std::string LLSDRPC_METHOD_SD_NAME("method");
51static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter");
52
53
54/**
55 * LLSDRPCServer
56 */
57LLSDRPCServer::LLSDRPCServer() :
58 mState(LLSDRPCServer::STATE_NONE),
59 mPump(NULL),
60 mLock(0)
61{
62 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
63}
64
65LLSDRPCServer::~LLSDRPCServer()
66{
67 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
68 std::for_each(
69 mMethods.begin(),
70 mMethods.end(),
71 llcompose1(
72 DeletePointerFunctor<LLSDRPCMethodCallBase>(),
73 llselect2nd<method_map_t::value_type>()));
74 std::for_each(
75 mCallbackMethods.begin(),
76 mCallbackMethods.end(),
77 llcompose1(
78 DeletePointerFunctor<LLSDRPCMethodCallBase>(),
79 llselect2nd<method_map_t::value_type>()));
80}
81
82
83// virtual
84ESDRPCSStatus LLSDRPCServer::deferredResponse(
85 const LLChannelDescriptors& channels,
86 LLBufferArray* data) {
87 // subclass should provide a sane implementation
88 return ESDRPCS_DONE;
89}
90
91void LLSDRPCServer::clearLock()
92{
93 if(mLock && mPump)
94 {
95 mPump->clearLock(mLock);
96 mPump = NULL;
97 mLock = 0;
98 }
99}
100
101// virtual
102LLIOPipe::EStatus LLSDRPCServer::process_impl(
103 const LLChannelDescriptors& channels,
104 buffer_ptr_t& buffer,
105 bool& eos,
106 LLSD& context,
107 LLPumpIO* pump)
108{
109 PUMP_DEBUG;
110 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
111// lldebugs << "LLSDRPCServer::process_impl" << llendl;
112 // Once we have all the data, We need to read the sd on
113 // the the in channel, and respond on the out channel
114 if(!eos) return STATUS_BREAK;
115 if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
116
117 std::string method_name;
118 LLIOPipe::EStatus status = STATUS_DONE;
119
120 switch(mState)
121 {
122 case STATE_DEFERRED:
123 PUMP_DEBUG;
124 if(ESDRPCS_DONE != deferredResponse(channels, buffer.get()))
125 {
126 buildFault(
127 channels,
128 buffer.get(),
129 FAULT_GENERIC,
130 "deferred response failed.");
131 }
132 mState = STATE_DONE;
133 return STATUS_DONE;
134
135 case STATE_DONE:
136// lldebugs << "STATE_DONE" << llendl;
137 break;
138 case STATE_CALLBACK:
139// lldebugs << "STATE_CALLBACK" << llendl;
140 PUMP_DEBUG;
141 method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
142 if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
143 {
144 if(ESDRPCS_DONE != callbackMethod(
145 method_name,
146 mRequest[LLSDRPC_PARAMETER_SD_NAME],
147 channels,
148 buffer.get()))
149 {
150 buildFault(
151 channels,
152 buffer.get(),
153 FAULT_GENERIC,
154 "Callback method call failed.");
155 }
156 }
157 else
158 {
159 // this should never happen, since we should not be in
160 // this state unless we originally found a method and
161 // params during the first call to process.
162 buildFault(
163 channels,
164 buffer.get(),
165 FAULT_GENERIC,
166 "Invalid LLSDRPC sever state - callback without method.");
167 }
168 pump->clearLock(mLock);
169 mLock = 0;
170 mState = STATE_DONE;
171 break;
172 case STATE_NONE:
173// lldebugs << "STATE_NONE" << llendl;
174 default:
175 {
176 // First time we got here - process the SD request, and call
177 // the method.
178 PUMP_DEBUG;
179 LLBufferStream istr(channels, buffer.get());
180 mRequest.clear();
181 LLSDSerialize::fromNotation(mRequest, istr);
182
183 // { 'method':'...', 'parameter': ... }
184 method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
185 if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
186 {
187 ESDRPCSStatus rv = callMethod(
188 method_name,
189 mRequest[LLSDRPC_PARAMETER_SD_NAME],
190 channels,
191 buffer.get());
192 switch(rv)
193 {
194 case ESDRPCS_DEFERRED:
195 mPump = pump;
196 mLock = pump->setLock();
197 mState = STATE_DEFERRED;
198 status = STATUS_BREAK;
199 break;
200
201 case ESDRPCS_CALLBACK:
202 {
203 mState = STATE_CALLBACK;
204 LLPumpIO::LLLinkInfo link;
205 link.mPipe = LLIOPipe::ptr_t(this);
206 link.mChannels = channels;
207 LLPumpIO::links_t links;
208 links.push_back(link);
209 pump->respond(links, buffer, context);
210 mLock = pump->setLock();
211 status = STATUS_BREAK;
212 break;
213 }
214 case ESDRPCS_DONE:
215 mState = STATE_DONE;
216 break;
217 case ESDRPCS_ERROR:
218 default:
219 buildFault(
220 channels,
221 buffer.get(),
222 FAULT_GENERIC,
223 "Method call failed.");
224 break;
225 }
226 }
227 else
228 {
229 // send a fault
230 buildFault(
231 channels,
232 buffer.get(),
233 FAULT_GENERIC,
234 "Unable to find method and parameter in request.");
235 }
236 break;
237 }
238 }
239
240 PUMP_DEBUG;
241 return status;
242}
243
244// virtual
245ESDRPCSStatus LLSDRPCServer::callMethod(
246 const std::string& method,
247 const LLSD& params,
248 const LLChannelDescriptors& channels,
249 LLBufferArray* response)
250{
251 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
252 // Try to find the method in the method table.
253 ESDRPCSStatus rv = ESDRPCS_DONE;
254 method_map_t::iterator it = mMethods.find(method);
255 if(it != mMethods.end())
256 {
257 rv = (*it).second->call(params, channels, response);
258 }
259 else
260 {
261 it = mCallbackMethods.find(method);
262 if(it == mCallbackMethods.end())
263 {
264 // method not found.
265 std::ostringstream message;
266 message << "rpc server unable to find method: " << method;
267 buildFault(
268 channels,
269 response,
270 FAULT_METHOD_NOT_FOUND,
271 message.str());
272 }
273 else
274 {
275 // we found it in the callback methods - tell the process
276 // to coordinate calling on the pump callback.
277 return ESDRPCS_CALLBACK;
278 }
279 }
280 return rv;
281}
282
283// virtual
284ESDRPCSStatus LLSDRPCServer::callbackMethod(
285 const std::string& method,
286 const LLSD& params,
287 const LLChannelDescriptors& channels,
288 LLBufferArray* response)
289{
290 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
291 // Try to find the method in the callback method table.
292 ESDRPCSStatus rv = ESDRPCS_DONE;
293 method_map_t::iterator it = mCallbackMethods.find(method);
294 if(it != mCallbackMethods.end())
295 {
296 rv = (*it).second->call(params, channels, response);
297 }
298 else
299 {
300 std::ostringstream message;
301 message << "pcserver unable to find callback method: " << method;
302 buildFault(
303 channels,
304 response,
305 FAULT_METHOD_NOT_FOUND,
306 message.str());
307 }
308 return rv;
309}
310
311// static
312void LLSDRPCServer::buildFault(
313 const LLChannelDescriptors& channels,
314 LLBufferArray* data,
315 S32 code,
316 const std::string& msg)
317{
318 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
319 LLBufferStream ostr(channels, data);
320 ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
321 llinfos << "LLSDRPCServer::buildFault: " << code << ", " << msg << llendl;
322}
323
324// static
325void LLSDRPCServer::buildResponse(
326 const LLChannelDescriptors& channels,
327 LLBufferArray* data,
328 const LLSD& response)
329{
330 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
331 LLBufferStream ostr(channels, data);
332 ostr << RESPONSE_PART_1;
333 LLSDSerialize::toNotation(response, ostr);
334 ostr << RESPONSE_PART_2;
335#if LL_DEBUG
336 std::ostringstream debug_ostr;
337 debug_ostr << "LLSDRPCServer::buildResponse: ";
338 LLSDSerialize::toNotation(response, debug_ostr);
339 llinfos << debug_ostr.str() << llendl;
340#endif
341}