diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/llsdrpcserver.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 341 |
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 | |||
40 | static const char FAULT_PART_1[] = "{'fault':{'code':i"; | ||
41 | static const char FAULT_PART_2[] = ", 'description':'"; | ||
42 | static const char FAULT_PART_3[] = "'}}"; | ||
43 | |||
44 | static const char RESPONSE_PART_1[] = "{'response':"; | ||
45 | static const char RESPONSE_PART_2[] = "}"; | ||
46 | |||
47 | static const S32 FAULT_GENERIC = 1000; | ||
48 | static const S32 FAULT_METHOD_NOT_FOUND = 1001; | ||
49 | |||
50 | static const std::string LLSDRPC_METHOD_SD_NAME("method"); | ||
51 | static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter"); | ||
52 | |||
53 | |||
54 | /** | ||
55 | * LLSDRPCServer | ||
56 | */ | ||
57 | LLSDRPCServer::LLSDRPCServer() : | ||
58 | mState(LLSDRPCServer::STATE_NONE), | ||
59 | mPump(NULL), | ||
60 | mLock(0) | ||
61 | { | ||
62 | LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER); | ||
63 | } | ||
64 | |||
65 | LLSDRPCServer::~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 | ||
84 | ESDRPCSStatus LLSDRPCServer::deferredResponse( | ||
85 | const LLChannelDescriptors& channels, | ||
86 | LLBufferArray* data) { | ||
87 | // subclass should provide a sane implementation | ||
88 | return ESDRPCS_DONE; | ||
89 | } | ||
90 | |||
91 | void LLSDRPCServer::clearLock() | ||
92 | { | ||
93 | if(mLock && mPump) | ||
94 | { | ||
95 | mPump->clearLock(mLock); | ||
96 | mPump = NULL; | ||
97 | mLock = 0; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | // virtual | ||
102 | LLIOPipe::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 | ||
245 | ESDRPCSStatus 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 | ||
284 | ESDRPCSStatus 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 | ||
312 | void 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 | ||
325 | void 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 | } | ||