diff options
Diffstat (limited to '')
-rwxr-xr-x | linden/indra/llplugin/llpluginmessage.cpp | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/linden/indra/llplugin/llpluginmessage.cpp b/linden/indra/llplugin/llpluginmessage.cpp new file mode 100755 index 0000000..6452f4a --- /dev/null +++ b/linden/indra/llplugin/llpluginmessage.cpp | |||
@@ -0,0 +1,445 @@ | |||
1 | /** | ||
2 | * @file llpluginmessage.cpp | ||
3 | * @brief LLPluginMessage encapsulates the serialization/deserialization of messages passed to and from plugins. | ||
4 | * | ||
5 | * @cond | ||
6 | * $LicenseInfo:firstyear=2008&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2008-2010, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at | ||
22 | * http://secondlife.com/developers/opensource/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | * | ||
33 | * @endcond | ||
34 | */ | ||
35 | |||
36 | #include "linden_common.h" | ||
37 | |||
38 | #include "llpluginmessage.h" | ||
39 | #include "llsdserialize.h" | ||
40 | #include "u64.h" | ||
41 | |||
42 | /** | ||
43 | * Constructor. | ||
44 | */ | ||
45 | LLPluginMessage::LLPluginMessage() | ||
46 | { | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * Constructor. | ||
51 | * | ||
52 | * @param[in] p Existing message | ||
53 | */ | ||
54 | LLPluginMessage::LLPluginMessage(const LLPluginMessage &p) | ||
55 | { | ||
56 | mMessage = p.mMessage; | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Constructor. | ||
61 | * | ||
62 | * @param[in] message_class Message class | ||
63 | * @param[in] message_name Message name | ||
64 | */ | ||
65 | LLPluginMessage::LLPluginMessage(const std::string &message_class, const std::string &message_name) | ||
66 | { | ||
67 | setMessage(message_class, message_name); | ||
68 | } | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Destructor. | ||
73 | */ | ||
74 | LLPluginMessage::~LLPluginMessage() | ||
75 | { | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Reset all internal state. | ||
80 | */ | ||
81 | void LLPluginMessage::clear() | ||
82 | { | ||
83 | mMessage = LLSD::emptyMap(); | ||
84 | mMessage["params"] = LLSD::emptyMap(); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Sets the message class and name. Also has the side-effect of clearing any key-value pairs in the message. | ||
89 | * | ||
90 | * @param[in] message_class Message class | ||
91 | * @param[in] message_name Message name | ||
92 | */ | ||
93 | void LLPluginMessage::setMessage(const std::string &message_class, const std::string &message_name) | ||
94 | { | ||
95 | clear(); | ||
96 | mMessage["class"] = message_class; | ||
97 | mMessage["name"] = message_name; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * Sets a key/value pair in the message, where the value is a string. | ||
102 | * | ||
103 | * @param[in] key Key | ||
104 | * @param[in] value String value | ||
105 | */ | ||
106 | void LLPluginMessage::setValue(const std::string &key, const std::string &value) | ||
107 | { | ||
108 | mMessage["params"][key] = value; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * Sets a key/value pair in the message, where the value is LLSD. | ||
113 | * | ||
114 | * @param[in] key Key | ||
115 | * @param[in] value LLSD value | ||
116 | */ | ||
117 | void LLPluginMessage::setValueLLSD(const std::string &key, const LLSD &value) | ||
118 | { | ||
119 | mMessage["params"][key] = value; | ||
120 | } | ||
121 | |||
122 | /** | ||
123 | * Sets a key/value pair in the message, where the value is signed 32-bit. | ||
124 | * | ||
125 | * @param[in] key Key | ||
126 | * @param[in] value 32-bit signed value | ||
127 | */ | ||
128 | void LLPluginMessage::setValueS32(const std::string &key, S32 value) | ||
129 | { | ||
130 | mMessage["params"][key] = value; | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * Sets a key/value pair in the message, where the value is unsigned 32-bit. The value is stored as a string beginning with "0x". | ||
135 | * | ||
136 | * @param[in] key Key | ||
137 | * @param[in] value 32-bit unsigned value | ||
138 | */ | ||
139 | void LLPluginMessage::setValueU32(const std::string &key, U32 value) | ||
140 | { | ||
141 | std::stringstream temp; | ||
142 | temp << "0x" << std::hex << value; | ||
143 | setValue(key, temp.str()); | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * Sets a key/value pair in the message, where the value is a bool. | ||
148 | * | ||
149 | * @param[in] key Key | ||
150 | * @param[in] value Boolean value | ||
151 | */ | ||
152 | void LLPluginMessage::setValueBoolean(const std::string &key, bool value) | ||
153 | { | ||
154 | mMessage["params"][key] = value; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * Sets a key/value pair in the message, where the value is a double. | ||
159 | * | ||
160 | * @param[in] key Key | ||
161 | * @param[in] value Boolean value | ||
162 | */ | ||
163 | void LLPluginMessage::setValueReal(const std::string &key, F64 value) | ||
164 | { | ||
165 | mMessage["params"][key] = value; | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * Sets a key/value pair in the message, where the value is a pointer. The pointer is stored as a string. | ||
170 | * | ||
171 | * @param[in] key Key | ||
172 | * @param[in] value Pointer value | ||
173 | */ | ||
174 | void LLPluginMessage::setValuePointer(const std::string &key, void* value) | ||
175 | { | ||
176 | std::stringstream temp; | ||
177 | // iostreams should output pointer values in hex with an initial 0x by default. | ||
178 | temp << value; | ||
179 | setValue(key, temp.str()); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * Gets the message class. | ||
184 | * | ||
185 | * @return Message class | ||
186 | */ | ||
187 | std::string LLPluginMessage::getClass(void) const | ||
188 | { | ||
189 | return mMessage["class"]; | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * Gets the message name. | ||
194 | * | ||
195 | * @return Message name | ||
196 | */ | ||
197 | std::string LLPluginMessage::getName(void) const | ||
198 | { | ||
199 | return mMessage["name"]; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * Returns true if the specified key exists in this message (useful for optional parameters). | ||
204 | * | ||
205 | * @param[in] key Key | ||
206 | * | ||
207 | * @return True if key exists, false otherwise. | ||
208 | */ | ||
209 | bool LLPluginMessage::hasValue(const std::string &key) const | ||
210 | { | ||
211 | bool result = false; | ||
212 | |||
213 | if(mMessage["params"].has(key)) | ||
214 | { | ||
215 | result = true; | ||
216 | } | ||
217 | |||
218 | return result; | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * Gets the value of a key as a string. If the key does not exist, an empty string will be returned. | ||
223 | * | ||
224 | * @param[in] key Key | ||
225 | * | ||
226 | * @return String value of key if key exists, empty string if key does not exist. | ||
227 | */ | ||
228 | std::string LLPluginMessage::getValue(const std::string &key) const | ||
229 | { | ||
230 | std::string result; | ||
231 | |||
232 | if(mMessage["params"].has(key)) | ||
233 | { | ||
234 | result = mMessage["params"][key].asString(); | ||
235 | } | ||
236 | |||
237 | return result; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * Gets the value of a key as LLSD. If the key does not exist, a null LLSD will be returned. | ||
242 | * | ||
243 | * @param[in] key Key | ||
244 | * | ||
245 | * @return LLSD value of key if key exists, null LLSD if key does not exist. | ||
246 | */ | ||
247 | LLSD LLPluginMessage::getValueLLSD(const std::string &key) const | ||
248 | { | ||
249 | LLSD result; | ||
250 | |||
251 | if(mMessage["params"].has(key)) | ||
252 | { | ||
253 | result = mMessage["params"][key]; | ||
254 | } | ||
255 | |||
256 | return result; | ||
257 | } | ||
258 | |||
259 | /** | ||
260 | * Gets the value of a key as signed 32-bit int. If the key does not exist, 0 will be returned. | ||
261 | * | ||
262 | * @param[in] key Key | ||
263 | * | ||
264 | * @return Signed 32-bit int value of key if key exists, 0 if key does not exist. | ||
265 | */ | ||
266 | S32 LLPluginMessage::getValueS32(const std::string &key) const | ||
267 | { | ||
268 | S32 result = 0; | ||
269 | |||
270 | if(mMessage["params"].has(key)) | ||
271 | { | ||
272 | result = mMessage["params"][key].asInteger(); | ||
273 | } | ||
274 | |||
275 | return result; | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * Gets the value of a key as unsigned 32-bit int. If the key does not exist, 0 will be returned. | ||
280 | * | ||
281 | * @param[in] key Key | ||
282 | * | ||
283 | * @return Unsigned 32-bit int value of key if key exists, 0 if key does not exist. | ||
284 | */ | ||
285 | U32 LLPluginMessage::getValueU32(const std::string &key) const | ||
286 | { | ||
287 | U32 result = 0; | ||
288 | |||
289 | if(mMessage["params"].has(key)) | ||
290 | { | ||
291 | std::string value = mMessage["params"][key].asString(); | ||
292 | |||
293 | result = (U32)strtoul(value.c_str(), NULL, 16); | ||
294 | } | ||
295 | |||
296 | return result; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * Gets the value of a key as a bool. If the key does not exist, false will be returned. | ||
301 | * | ||
302 | * @param[in] key Key | ||
303 | * | ||
304 | * @return Boolean value of key if it exists, false otherwise. | ||
305 | */ | ||
306 | bool LLPluginMessage::getValueBoolean(const std::string &key) const | ||
307 | { | ||
308 | bool result = false; | ||
309 | |||
310 | if(mMessage["params"].has(key)) | ||
311 | { | ||
312 | result = mMessage["params"][key].asBoolean(); | ||
313 | } | ||
314 | |||
315 | return result; | ||
316 | } | ||
317 | |||
318 | /** | ||
319 | * Gets the value of a key as a double. If the key does not exist, 0 will be returned. | ||
320 | * | ||
321 | * @param[in] key Key | ||
322 | * | ||
323 | * @return Value as a double if key exists, 0 otherwise. | ||
324 | */ | ||
325 | F64 LLPluginMessage::getValueReal(const std::string &key) const | ||
326 | { | ||
327 | F64 result = 0.0f; | ||
328 | |||
329 | if(mMessage["params"].has(key)) | ||
330 | { | ||
331 | result = mMessage["params"][key].asReal(); | ||
332 | } | ||
333 | |||
334 | return result; | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * Gets the value of a key as a pointer. If the key does not exist, NULL will be returned. | ||
339 | * | ||
340 | * @param[in] key Key | ||
341 | * | ||
342 | * @return Pointer value if key exists, NULL otherwise. | ||
343 | */ | ||
344 | void* LLPluginMessage::getValuePointer(const std::string &key) const | ||
345 | { | ||
346 | void* result = NULL; | ||
347 | |||
348 | if(mMessage["params"].has(key)) | ||
349 | { | ||
350 | std::string value = mMessage["params"][key].asString(); | ||
351 | |||
352 | result = (void*)llstrtou64(value.c_str(), NULL, 16); | ||
353 | } | ||
354 | |||
355 | return result; | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Flatten the message into a string. | ||
360 | * | ||
361 | * @return Message as a string. | ||
362 | */ | ||
363 | std::string LLPluginMessage::generate(void) const | ||
364 | { | ||
365 | std::ostringstream result; | ||
366 | |||
367 | // Pretty XML may be slightly easier to deal with while debugging... | ||
368 | // LLSDSerialize::toXML(mMessage, result); | ||
369 | LLSDSerialize::toPrettyXML(mMessage, result); | ||
370 | |||
371 | return result.str(); | ||
372 | } | ||
373 | |||
374 | /** | ||
375 | * Parse an incoming message into component parts. Clears all existing state before starting the parse. | ||
376 | * | ||
377 | * @return Returns -1 on failure, otherwise returns the number of key/value pairs in the incoming message. | ||
378 | */ | ||
379 | int LLPluginMessage::parse(const std::string &message) | ||
380 | { | ||
381 | // clear any previous state | ||
382 | clear(); | ||
383 | |||
384 | std::istringstream input(message); | ||
385 | |||
386 | S32 parse_result = LLSDSerialize::fromXML(mMessage, input); | ||
387 | |||
388 | return (int)parse_result; | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
393 | * Destructor | ||
394 | */ | ||
395 | LLPluginMessageListener::~LLPluginMessageListener() | ||
396 | { | ||
397 | // TODO: should listeners have a way to ensure they're removed from dispatcher lists when deleted? | ||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Destructor | ||
403 | */ | ||
404 | LLPluginMessageDispatcher::~LLPluginMessageDispatcher() | ||
405 | { | ||
406 | |||
407 | } | ||
408 | |||
409 | /** | ||
410 | * Add a message listener. TODO:DOC need more info on what uses this. when are multiple listeners needed? | ||
411 | * | ||
412 | * @param[in] listener Message listener | ||
413 | */ | ||
414 | void LLPluginMessageDispatcher::addPluginMessageListener(LLPluginMessageListener *listener) | ||
415 | { | ||
416 | mListeners.insert(listener); | ||
417 | } | ||
418 | |||
419 | /** | ||
420 | * Remove a message listener. | ||
421 | * | ||
422 | * @param[in] listener Message listener | ||
423 | */ | ||
424 | void LLPluginMessageDispatcher::removePluginMessageListener(LLPluginMessageListener *listener) | ||
425 | { | ||
426 | mListeners.erase(listener); | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * Distribute a message to all message listeners. | ||
431 | * | ||
432 | * @param[in] message Message | ||
433 | */ | ||
434 | void LLPluginMessageDispatcher::dispatchPluginMessage(const LLPluginMessage &message) | ||
435 | { | ||
436 | for (listener_set_t::iterator it = mListeners.begin(); | ||
437 | it != mListeners.end(); | ||
438 | ) | ||
439 | { | ||
440 | LLPluginMessageListener* listener = *it; | ||
441 | listener->receivePluginMessage(message); | ||
442 | // In case something deleted an entry. | ||
443 | it = mListeners.upper_bound(listener); | ||
444 | } | ||
445 | } | ||