diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs new file mode 100644 index 0000000..d1543a0 --- /dev/null +++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/MessageTransferModule.cs | |||
@@ -0,0 +1,626 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | using System; | ||
28 | using System.Collections; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Reflection; | ||
31 | using System.Net; | ||
32 | using System.Threading; | ||
33 | using OpenMetaverse; | ||
34 | using log4net; | ||
35 | using Nini.Config; | ||
36 | using Nwc.XmlRpc; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Framework.Client; | ||
39 | using OpenSim.Region.Interfaces; | ||
40 | using OpenSim.Region.Environment.Interfaces; | ||
41 | using OpenSim.Region.Environment.Scenes; | ||
42 | |||
43 | namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage | ||
44 | { | ||
45 | public class MessageTransferModule : IRegionModule, IMessageTransferModule | ||
46 | { | ||
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
48 | |||
49 | private bool m_Enabled = false; | ||
50 | private bool m_Gridmode = false; | ||
51 | private List<Scene> m_Scenes = new List<Scene>(); | ||
52 | private Dictionary<UUID, ulong> m_UserRegionMap = new Dictionary<UUID, ulong>(); | ||
53 | |||
54 | public void Initialise(Scene scene, IConfigSource config) | ||
55 | { | ||
56 | if (config.Configs["Messaging"] != null) | ||
57 | { | ||
58 | IConfig cnf = config.Configs["Messaging"]; | ||
59 | if (cnf == null || cnf.GetString( | ||
60 | "MessageTransferModule", "MessageTransferModule") != | ||
61 | "MessageTransferModule") | ||
62 | return; | ||
63 | |||
64 | cnf = config.Configs["Startup"]; | ||
65 | if (cnf != null) | ||
66 | m_Gridmode = cnf.GetBoolean("m_Gridmode", false); | ||
67 | |||
68 | m_Enabled = true; | ||
69 | } | ||
70 | |||
71 | lock (m_Scenes) | ||
72 | { | ||
73 | if (m_Scenes.Count == 0) | ||
74 | { | ||
75 | scene.AddXmlRPCHandler("grid_instant_message", processXMLRPCGridInstantMessage); | ||
76 | scene.RegisterModuleInterface<IMessageTransferModule>(this); | ||
77 | } | ||
78 | |||
79 | m_Scenes.Add(scene); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | public void PostInitialise() | ||
84 | { | ||
85 | } | ||
86 | |||
87 | public void Close() | ||
88 | { | ||
89 | } | ||
90 | |||
91 | public string Name | ||
92 | { | ||
93 | get { return "MessageTransferModule"; } | ||
94 | } | ||
95 | |||
96 | public bool IsSharedModule | ||
97 | { | ||
98 | get { return true; } | ||
99 | } | ||
100 | |||
101 | public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) | ||
102 | { | ||
103 | UUID toAgentID = new UUID(im.toAgentID); | ||
104 | |||
105 | m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM fromn {0} to {1}", im.fromAgentName, toAgentID.ToString()); | ||
106 | |||
107 | // Try root avatar only first | ||
108 | foreach (Scene scene in m_Scenes) | ||
109 | { | ||
110 | if (scene.Entities.ContainsKey(toAgentID) && | ||
111 | scene.Entities[toAgentID] is ScenePresence) | ||
112 | { | ||
113 | m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); | ||
114 | // Local message | ||
115 | ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; | ||
116 | if (!user.IsChildAgent) | ||
117 | { | ||
118 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); | ||
119 | user.ControllingClient.SendInstantMessage( | ||
120 | new UUID(im.fromAgentID), | ||
121 | im.message, | ||
122 | new UUID(im.toAgentID), | ||
123 | im.fromAgentName, | ||
124 | im.dialog, | ||
125 | im.timestamp, | ||
126 | new UUID(im.imSessionID), | ||
127 | im.fromGroup, | ||
128 | im.binaryBucket); | ||
129 | // Message sent | ||
130 | result(true); | ||
131 | return; | ||
132 | } | ||
133 | } | ||
134 | } | ||
135 | |||
136 | // try child avatar second | ||
137 | foreach (Scene scene in m_Scenes) | ||
138 | { | ||
139 | m_log.DebugFormat("[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); | ||
140 | |||
141 | if (scene.Entities.ContainsKey(toAgentID) && | ||
142 | scene.Entities[toAgentID] is ScenePresence) | ||
143 | { | ||
144 | // Local message | ||
145 | ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; | ||
146 | |||
147 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); | ||
148 | user.ControllingClient.SendInstantMessage( | ||
149 | new UUID(im.fromAgentID), | ||
150 | im.message, | ||
151 | new UUID(im.toAgentID), | ||
152 | im.fromAgentName, | ||
153 | im.dialog, | ||
154 | im.timestamp, | ||
155 | new UUID(im.imSessionID), | ||
156 | im.fromGroup, | ||
157 | im.binaryBucket); | ||
158 | // Message sent | ||
159 | result(true); | ||
160 | return; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | if (m_Gridmode) | ||
165 | { | ||
166 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid"); | ||
167 | // Still here, try send via Grid | ||
168 | SendGridInstantMessageViaXMLRPC(im, result); | ||
169 | return; | ||
170 | } | ||
171 | |||
172 | m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable"); | ||
173 | result(false); | ||
174 | return; | ||
175 | } | ||
176 | |||
177 | /// <summary> | ||
178 | /// Process a XMLRPC Grid Instant Message | ||
179 | /// </summary> | ||
180 | /// <param name="request">XMLRPC parameters | ||
181 | /// </param> | ||
182 | /// <returns>Nothing much</returns> | ||
183 | protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request) | ||
184 | { | ||
185 | bool successful = false; | ||
186 | // various rational defaults | ||
187 | UUID fromAgentID = UUID.Zero; | ||
188 | UUID fromAgentSession = UUID.Zero; | ||
189 | UUID toAgentID = UUID.Zero; | ||
190 | UUID imSessionID = UUID.Zero; | ||
191 | uint timestamp = 0; | ||
192 | string fromAgentName = ""; | ||
193 | string message = ""; | ||
194 | byte dialog = (byte)0; | ||
195 | bool fromGroup = false; | ||
196 | byte offline = (byte)0; | ||
197 | uint ParentEstateID=0; | ||
198 | Vector3 Position = Vector3.Zero; | ||
199 | UUID RegionID = UUID.Zero ; | ||
200 | byte[] binaryBucket = new byte[0]; | ||
201 | |||
202 | float pos_x = 0; | ||
203 | float pos_y = 0; | ||
204 | float pos_z = 0; | ||
205 | //m_log.Info("Processing IM"); | ||
206 | |||
207 | |||
208 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
209 | // Check if it's got all the data | ||
210 | if (requestData.ContainsKey("from_agent_id") && requestData.ContainsKey("from_agent_session") | ||
211 | && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id") | ||
212 | && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name") | ||
213 | && requestData.ContainsKey("message") && requestData.ContainsKey("dialog") | ||
214 | && requestData.ContainsKey("from_group") | ||
215 | && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id") | ||
216 | && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y") | ||
217 | && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id") | ||
218 | && requestData.ContainsKey("binary_bucket")) | ||
219 | { | ||
220 | // Do the easy way of validating the UUIDs | ||
221 | UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID); | ||
222 | UUID.TryParse((string)requestData["from_agent_session"], out fromAgentSession); | ||
223 | UUID.TryParse((string)requestData["to_agent_id"], out toAgentID); | ||
224 | UUID.TryParse((string)requestData["im_session_id"], out imSessionID); | ||
225 | UUID.TryParse((string)requestData["region_id"], out RegionID); | ||
226 | |||
227 | try | ||
228 | { | ||
229 | timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]); | ||
230 | } | ||
231 | catch (ArgumentException) | ||
232 | { | ||
233 | } | ||
234 | catch (FormatException) | ||
235 | { | ||
236 | } | ||
237 | catch (OverflowException) | ||
238 | { | ||
239 | } | ||
240 | |||
241 | fromAgentName = (string)requestData["from_agent_name"]; | ||
242 | message = (string)requestData["message"]; | ||
243 | |||
244 | // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. | ||
245 | string requestData1 = (string)requestData["dialog"]; | ||
246 | if (string.IsNullOrEmpty(requestData1)) | ||
247 | { | ||
248 | dialog = 0; | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | byte[] dialogdata = Convert.FromBase64String(requestData1); | ||
253 | dialog = dialogdata[0]; | ||
254 | } | ||
255 | |||
256 | if ((string)requestData["from_group"] == "TRUE") | ||
257 | fromGroup = true; | ||
258 | |||
259 | string requestData2 = (string)requestData["offline"]; | ||
260 | if (String.IsNullOrEmpty(requestData2)) | ||
261 | { | ||
262 | offline = 0; | ||
263 | } | ||
264 | else | ||
265 | { | ||
266 | byte[] offlinedata = Convert.FromBase64String(requestData2); | ||
267 | offline = offlinedata[0]; | ||
268 | } | ||
269 | |||
270 | try | ||
271 | { | ||
272 | ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]); | ||
273 | } | ||
274 | catch (ArgumentException) | ||
275 | { | ||
276 | } | ||
277 | catch (FormatException) | ||
278 | { | ||
279 | } | ||
280 | catch (OverflowException) | ||
281 | { | ||
282 | } | ||
283 | |||
284 | try | ||
285 | { | ||
286 | pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]); | ||
287 | } | ||
288 | catch (ArgumentException) | ||
289 | { | ||
290 | } | ||
291 | catch (FormatException) | ||
292 | { | ||
293 | } | ||
294 | catch (OverflowException) | ||
295 | { | ||
296 | } | ||
297 | try | ||
298 | { | ||
299 | pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]); | ||
300 | } | ||
301 | catch (ArgumentException) | ||
302 | { | ||
303 | } | ||
304 | catch (FormatException) | ||
305 | { | ||
306 | } | ||
307 | catch (OverflowException) | ||
308 | { | ||
309 | } | ||
310 | try | ||
311 | { | ||
312 | pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]); | ||
313 | } | ||
314 | catch (ArgumentException) | ||
315 | { | ||
316 | } | ||
317 | catch (FormatException) | ||
318 | { | ||
319 | } | ||
320 | catch (OverflowException) | ||
321 | { | ||
322 | } | ||
323 | |||
324 | Position = new Vector3(pos_x, pos_y, pos_z); | ||
325 | |||
326 | string requestData3 = (string)requestData["binary_bucket"]; | ||
327 | if (string.IsNullOrEmpty(requestData3)) | ||
328 | { | ||
329 | binaryBucket = new byte[0]; | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | binaryBucket = Convert.FromBase64String(requestData3); | ||
334 | } | ||
335 | |||
336 | // Create a New GridInstantMessageObject the the data | ||
337 | GridInstantMessage gim = new GridInstantMessage(); | ||
338 | gim.fromAgentID = fromAgentID.Guid; | ||
339 | gim.fromAgentName = fromAgentName; | ||
340 | gim.fromAgentSession = fromAgentSession.Guid; | ||
341 | gim.fromGroup = fromGroup; | ||
342 | gim.imSessionID = imSessionID.Guid; | ||
343 | gim.RegionID = RegionID.Guid; | ||
344 | gim.timestamp = timestamp; | ||
345 | gim.toAgentID = toAgentID.Guid; | ||
346 | gim.message = message; | ||
347 | gim.dialog = dialog; | ||
348 | gim.offline = offline; | ||
349 | gim.ParentEstateID = ParentEstateID; | ||
350 | gim.Position = Position; | ||
351 | gim.binaryBucket = binaryBucket; | ||
352 | |||
353 | |||
354 | // Trigger the Instant message in the scene. | ||
355 | foreach (Scene scene in m_Scenes) | ||
356 | { | ||
357 | if (scene.Entities.ContainsKey(toAgentID) && | ||
358 | scene.Entities[toAgentID] is ScenePresence) | ||
359 | { | ||
360 | ScenePresence user = | ||
361 | (ScenePresence)scene.Entities[toAgentID]; | ||
362 | |||
363 | if (!user.IsChildAgent) | ||
364 | { | ||
365 | scene.EventManager.TriggerIncomingInstantMessage(gim); | ||
366 | successful = true; | ||
367 | } | ||
368 | } | ||
369 | } | ||
370 | if (!successful) | ||
371 | { | ||
372 | // If the message can't be delivered to an agent, it | ||
373 | // is likely to be a group IM. On a group IM, the | ||
374 | // imSessionID = toAgentID = group id. Raise the | ||
375 | // unhandled IM event to give the groups module | ||
376 | // a chance to pick it up. We raise that in a random | ||
377 | // scene, since the groups module is shared. | ||
378 | // | ||
379 | m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim); | ||
380 | } | ||
381 | } | ||
382 | |||
383 | //Send response back to region calling if it was successful | ||
384 | // calling region uses this to know when to look up a user's location again. | ||
385 | XmlRpcResponse resp = new XmlRpcResponse(); | ||
386 | Hashtable respdata = new Hashtable(); | ||
387 | if (successful) | ||
388 | respdata["success"] = "TRUE"; | ||
389 | else | ||
390 | respdata["success"] = "FALSE"; | ||
391 | resp.Value = respdata; | ||
392 | |||
393 | return resp; | ||
394 | } | ||
395 | |||
396 | /// <summary> | ||
397 | /// delegate for sending a grid instant message asynchronously | ||
398 | /// </summary> | ||
399 | public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle); | ||
400 | |||
401 | private void GridInstantMessageCompleted(IAsyncResult iar) | ||
402 | { | ||
403 | GridInstantMessageDelegate icon = | ||
404 | (GridInstantMessageDelegate)iar.AsyncState; | ||
405 | icon.EndInvoke(iar); | ||
406 | } | ||
407 | |||
408 | |||
409 | protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result) | ||
410 | { | ||
411 | GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; | ||
412 | |||
413 | d.BeginInvoke(im, result, 0, GridInstantMessageCompleted, d); | ||
414 | } | ||
415 | |||
416 | /// <summary> | ||
417 | /// Recursive SendGridInstantMessage over XMLRPC method. | ||
418 | /// </summary> | ||
419 | /// <param name="prevRegionHandle"></param> | ||
420 | protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, ulong prevRegionHandle) | ||
421 | { | ||
422 | UUID toAgentID = new UUID(im.toAgentID); | ||
423 | |||
424 | UserAgentData upd = null; | ||
425 | |||
426 | bool lookupAgent = false; | ||
427 | |||
428 | lock (m_UserRegionMap) | ||
429 | { | ||
430 | if (m_UserRegionMap.ContainsKey(toAgentID)) | ||
431 | { | ||
432 | upd = new UserAgentData(); | ||
433 | upd.AgentOnline = true; | ||
434 | upd.Handle = m_UserRegionMap[toAgentID]; | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | lookupAgent = true; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | // Are we needing to look-up an agent? | ||
443 | if (lookupAgent) | ||
444 | { | ||
445 | // Non-cached user agent lookup. | ||
446 | upd = m_Scenes[0].CommsManager.UserService.GetAgentByUUID(toAgentID); | ||
447 | |||
448 | if (upd != null) | ||
449 | { | ||
450 | // check if we've tried this before.. | ||
451 | // This is one way to end the recursive loop | ||
452 | // | ||
453 | if (upd.Handle == prevRegionHandle) | ||
454 | { | ||
455 | m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); | ||
456 | result(false); | ||
457 | return; | ||
458 | } | ||
459 | } | ||
460 | else | ||
461 | { | ||
462 | m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); | ||
463 | result(false); | ||
464 | return; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | if (upd != null) | ||
469 | { | ||
470 | if (upd.AgentOnline) | ||
471 | { | ||
472 | RegionInfo reginfo = m_Scenes[0].SceneGridService.RequestNeighbouringRegionInfo(upd.Handle); | ||
473 | if (reginfo != null) | ||
474 | { | ||
475 | Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); | ||
476 | // Not actually used anymore, left in for compatibility | ||
477 | // Remove at next interface change | ||
478 | // | ||
479 | msgdata["region_handle"] = 0; | ||
480 | bool imresult = doIMSending(reginfo, msgdata); | ||
481 | if (imresult) | ||
482 | { | ||
483 | // IM delivery successful, so store the Agent's location in our local cache. | ||
484 | lock (m_UserRegionMap) | ||
485 | { | ||
486 | if (m_UserRegionMap.ContainsKey(toAgentID)) | ||
487 | { | ||
488 | m_UserRegionMap[toAgentID] = upd.Handle; | ||
489 | } | ||
490 | else | ||
491 | { | ||
492 | m_UserRegionMap.Add(toAgentID, upd.Handle); | ||
493 | } | ||
494 | } | ||
495 | result(true); | ||
496 | } | ||
497 | else | ||
498 | { | ||
499 | // try again, but lookup user this time. | ||
500 | // Warning, this must call the Async version | ||
501 | // of this method or we'll be making thousands of threads | ||
502 | // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync | ||
503 | // The version that spawns the thread is SendGridInstantMessageViaXMLRPC | ||
504 | |||
505 | // This is recursive!!!!! | ||
506 | SendGridInstantMessageViaXMLRPCAsync(im, result, | ||
507 | upd.Handle); | ||
508 | } | ||
509 | |||
510 | } | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | result(false); | ||
515 | } | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | result(false); | ||
520 | } | ||
521 | |||
522 | } | ||
523 | |||
524 | /// <summary> | ||
525 | /// This actually does the XMLRPC Request | ||
526 | /// </summary> | ||
527 | /// <param name="reginfo">RegionInfo we pull the data out of to send the request to</param> | ||
528 | /// <param name="xmlrpcdata">The Instant Message data Hashtable</param> | ||
529 | /// <returns>Bool if the message was successfully delivered at the other side.</returns> | ||
530 | private bool doIMSending(RegionInfo reginfo, Hashtable xmlrpcdata) | ||
531 | { | ||
532 | |||
533 | ArrayList SendParams = new ArrayList(); | ||
534 | SendParams.Add(xmlrpcdata); | ||
535 | XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); | ||
536 | try | ||
537 | { | ||
538 | |||
539 | XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); | ||
540 | |||
541 | Hashtable responseData = (Hashtable)GridResp.Value; | ||
542 | |||
543 | if (responseData.ContainsKey("success")) | ||
544 | { | ||
545 | if ((string)responseData["success"] == "TRUE") | ||
546 | { | ||
547 | return true; | ||
548 | } | ||
549 | else | ||
550 | { | ||
551 | return false; | ||
552 | } | ||
553 | } | ||
554 | else | ||
555 | { | ||
556 | return false; | ||
557 | } | ||
558 | } | ||
559 | catch (WebException e) | ||
560 | { | ||
561 | m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to http://{0}:{1} the host didn't respond ({2})", | ||
562 | reginfo.ExternalHostName, reginfo.HttpPort, e.Message); | ||
563 | } | ||
564 | |||
565 | return false; | ||
566 | } | ||
567 | |||
568 | /// <summary> | ||
569 | /// Get ulong region handle for region by it's Region UUID. | ||
570 | /// We use region handles over grid comms because there's all sorts of free and cool caching. | ||
571 | /// </summary> | ||
572 | /// <param name="regionID">UUID of region to get the region handle for</param> | ||
573 | /// <returns></returns> | ||
574 | private ulong getLocalRegionHandleFromUUID(UUID regionID) | ||
575 | { | ||
576 | ulong returnhandle = 0; | ||
577 | |||
578 | lock (m_Scenes) | ||
579 | { | ||
580 | foreach (Scene sn in m_Scenes) | ||
581 | { | ||
582 | if (sn.RegionInfo.RegionID == regionID) | ||
583 | { | ||
584 | returnhandle = sn.RegionInfo.RegionHandle; | ||
585 | break; | ||
586 | } | ||
587 | } | ||
588 | } | ||
589 | return returnhandle; | ||
590 | } | ||
591 | |||
592 | /// <summary> | ||
593 | /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC | ||
594 | /// </summary> | ||
595 | /// <param name="msg">The GridInstantMessage object</param> | ||
596 | /// <returns>Hashtable containing the XMLRPC request</returns> | ||
597 | private Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) | ||
598 | { | ||
599 | Hashtable gim = new Hashtable(); | ||
600 | gim["from_agent_id"] = msg.fromAgentID.ToString(); | ||
601 | gim["from_agent_session"] = msg.fromAgentSession.ToString(); | ||
602 | gim["to_agent_id"] = msg.toAgentID.ToString(); | ||
603 | gim["im_session_id"] = msg.imSessionID.ToString(); | ||
604 | gim["timestamp"] = msg.timestamp.ToString(); | ||
605 | gim["from_agent_name"] = msg.fromAgentName; | ||
606 | gim["message"] = msg.message; | ||
607 | byte[] dialogdata = new byte[1];dialogdata[0] = msg.dialog; | ||
608 | gim["dialog"] = Convert.ToBase64String(dialogdata,Base64FormattingOptions.None); | ||
609 | |||
610 | if (msg.fromGroup) | ||
611 | gim["from_group"] = "TRUE"; | ||
612 | else | ||
613 | gim["from_group"] = "FALSE"; | ||
614 | byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline; | ||
615 | gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None); | ||
616 | gim["parent_estate_id"] = msg.ParentEstateID.ToString(); | ||
617 | gim["position_x"] = msg.Position.X.ToString(); | ||
618 | gim["position_y"] = msg.Position.Y.ToString(); | ||
619 | gim["position_z"] = msg.Position.Z.ToString(); | ||
620 | gim["region_id"] = msg.RegionID.ToString(); | ||
621 | gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); | ||
622 | return gim; | ||
623 | } | ||
624 | |||
625 | } | ||
626 | } | ||