aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Serialization/TarArchiveWriter.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs73
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs142
3 files changed, 155 insertions, 64 deletions
diff --git a/OpenSim/Framework/Serialization/TarArchiveWriter.cs b/OpenSim/Framework/Serialization/TarArchiveWriter.cs
index 20d0f7e..0bd639f 100644
--- a/OpenSim/Framework/Serialization/TarArchiveWriter.cs
+++ b/OpenSim/Framework/Serialization/TarArchiveWriter.cs
@@ -208,7 +208,9 @@ namespace OpenSim.Framework.Serialization
208 m_bw.Write(header); 208 m_bw.Write(header);
209 209
210 // Write out data 210 // Write out data
211 m_bw.Write(data); 211 // An IOException occurs if we try to write out an empty array in Mono 2.6
212 if (data.Length > 0)
213 m_bw.Write(data);
212 214
213 if (data.Length % 512 != 0) 215 if (data.Length % 512 != 0)
214 { 216 {
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
new file mode 100644
index 0000000..f158236
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
@@ -0,0 +1,73 @@
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 OpenSimulator 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
28using OpenMetaverse;
29using OpenSim.Framework;
30
31namespace OpenSim.Region.Framework.Interfaces
32{
33 /// <summary>
34 /// Provide mechanisms for messaging groups.
35 /// </summary>
36 ///
37 /// TODO: Provide a mechanism for receiving group messages as well as sending them
38 ///
39 public interface IGroupsMessagingModule
40 {
41 /// <summary>
42 /// Start a group chat session.
43 /// </summary>
44 /// You must call this before calling SendMessageToGroup(). If a chat session for this group is already taking
45 /// place then the agent will added to that session.
46 /// <param name="agentID">
47 /// A UUID that represents the agent being added. If you are agentless (e.g. you are
48 /// a region module), then you can use any random ID.
49 /// </param>
50 /// <param name="groupID">
51 /// The ID for the group to join. Currently, the session ID used is identical to the
52 /// group ID.
53 /// </param>
54 /// <returns>
55 /// True if the chat session was started successfully, false otherwise.
56 /// </returns>
57 bool StartGroupChatSession(UUID agentID, UUID groupID);
58
59 /// <summary>
60 /// Send a message to an entire group.
61 /// </summary>
62 /// <param name="im">
63 /// The message itself. The fields that must be populated are
64 ///
65 /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical)
66 /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog
67 /// message - The message itself
68 /// dialog - This must be (byte)InstantMessageDialog.SessionSend
69 /// </param>
70 /// <param name="groupID"></param>
71 void SendMessageToGroup(GridInstantMessage im, UUID groupID);
72 }
73} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
index 00fe5df..533815f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -28,29 +28,23 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31
32
33using log4net; 31using log4net;
34using Mono.Addins; 32using Mono.Addins;
35using Nini.Config; 33using Nini.Config;
36
37using OpenMetaverse; 34using OpenMetaverse;
38using OpenMetaverse.StructuredData; 35using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework; 36using OpenSim.Framework;
41using OpenSim.Region.CoreModules.Framework.EventQueue; 37using OpenSim.Region.CoreModules.Framework.EventQueue;
42using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
44 40
45
46using Caps = OpenSim.Framework.Capabilities.Caps; 41using Caps = OpenSim.Framework.Capabilities.Caps;
47 42
48namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 43namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
49{ 44{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
51 public class GroupsMessagingModule : ISharedRegionModule 46 public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule
52 { 47 {
53
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 49
56 private List<Scene> m_sceneList = new List<Scene>(); 50 private List<Scene> m_sceneList = new List<Scene>();
@@ -108,8 +102,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
108 102
109 public void AddRegion(Scene scene) 103 public void AddRegion(Scene scene)
110 { 104 {
111 // NoOp 105 if (!m_groupMessagingEnabled)
106 return;
107
108 scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
112 } 109 }
110
113 public void RegionLoaded(Scene scene) 111 public void RegionLoaded(Scene scene)
114 { 112 {
115 if (!m_groupMessagingEnabled) 113 if (!m_groupMessagingEnabled)
@@ -197,6 +195,73 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
197 195
198 #endregion 196 #endregion
199 197
198 public bool StartGroupChatSession(UUID agentID, UUID groupID)
199 {
200 if (m_debugEnabled)
201 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
202
203 GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID);
204
205 if (groupInfo != null)
206 {
207 AddAgentToGroupSession(agentID.Guid, groupID.Guid);
208 return true;
209 }
210 else
211 {
212 return false;
213 }
214 }
215
216 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
217 {
218 if (m_debugEnabled)
219 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
220
221 foreach (GroupMembersData member in m_groupsModule.GroupMembersRequest(null, groupID))
222 {
223 if (!m_agentsDroppedSession.ContainsKey(im.imSessionID) || m_agentsDroppedSession[im.imSessionID].Contains(member.AgentID.Guid))
224 {
225 // Don't deliver messages to people who have dropped this session
226 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID);
227 continue;
228 }
229
230 // Copy Message
231 GridInstantMessage msg = new GridInstantMessage();
232 msg.imSessionID = im.imSessionID;
233 msg.fromAgentName = im.fromAgentName;
234 msg.message = im.message;
235 msg.dialog = im.dialog;
236 msg.offline = im.offline;
237 msg.ParentEstateID = im.ParentEstateID;
238 msg.Position = im.Position;
239 msg.RegionID = im.RegionID;
240 msg.binaryBucket = im.binaryBucket;
241 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
242
243 // Updat Pertinate fields to make it a "group message"
244 msg.fromAgentID = groupID.Guid;
245 msg.fromGroup = true;
246
247 msg.toAgentID = member.AgentID.Guid;
248
249 IClientAPI client = GetActiveClient(member.AgentID);
250 if (client == null)
251 {
252 // If they're not local, forward across the grid
253 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID);
254 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
255 }
256 else
257 {
258 // Deliver locally, directly
259 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
260 ProcessMessageFromGroupSession(msg);
261 }
262 }
263 }
264
200 #region SimGridEventHandlers 265 #region SimGridEventHandlers
201 266
202 private void OnNewClient(IClientAPI client) 267 private void OnNewClient(IClientAPI client)
@@ -370,7 +435,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
370 m_agentsDroppedSession.Add(sessionID, new List<Guid>()); 435 m_agentsDroppedSession.Add(sessionID, new List<Guid>());
371 } 436 }
372 } 437 }
373 438
374 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) 439 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
375 { 440 {
376 if (m_debugEnabled) 441 if (m_debugEnabled)
@@ -384,13 +449,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
384 if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) 449 if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart))
385 { 450 {
386 UUID groupID = new UUID(im.toAgentID); 451 UUID groupID = new UUID(im.toAgentID);
387
388 GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); 452 GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID);
453
389 if (groupInfo != null) 454 if (groupInfo != null)
390 { 455 {
391 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Start Group Session for {0}", groupInfo.GroupName); 456 AddAgentToGroupSession(im.fromAgentID, groupInfo.GroupID.Guid);
392
393 AddAgentToGroupSession(im.fromAgentID, im.imSessionID);
394 457
395 ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, groupID); 458 ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, groupID);
396 459
@@ -411,7 +474,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
411 { 474 {
412 UUID groupID = new UUID(im.toAgentID); 475 UUID groupID = new UUID(im.toAgentID);
413 476
414 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", groupID, im.imSessionID.ToString()); 477 if (m_debugEnabled)
478 m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", groupID, im.imSessionID.ToString());
415 479
416 SendMessageToGroup(im, groupID); 480 SendMessageToGroup(im, groupID);
417 } 481 }
@@ -419,54 +483,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
419 483
420 #endregion 484 #endregion
421 485
422 private void SendMessageToGroup(GridInstantMessage im, UUID groupID)
423 {
424 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
425
426 foreach (GroupMembersData member in m_groupsModule.GroupMembersRequest(null, groupID))
427 {
428 if (!m_agentsDroppedSession.ContainsKey(im.imSessionID) || m_agentsDroppedSession[im.imSessionID].Contains(member.AgentID.Guid))
429 {
430 // Don't deliver messages to people who have dropped this session
431 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID);
432 continue;
433 }
434
435 // Copy Message
436 GridInstantMessage msg = new GridInstantMessage();
437 msg.imSessionID = im.imSessionID;
438 msg.fromAgentName = im.fromAgentName;
439 msg.message = im.message;
440 msg.dialog = im.dialog;
441 msg.offline = im.offline;
442 msg.ParentEstateID = im.ParentEstateID;
443 msg.Position = im.Position;
444 msg.RegionID = im.RegionID;
445 msg.binaryBucket = im.binaryBucket;
446 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
447
448 // Updat Pertinate fields to make it a "group message"
449 msg.fromAgentID = groupID.Guid;
450 msg.fromGroup = true;
451
452 msg.toAgentID = member.AgentID.Guid;
453
454 IClientAPI client = GetActiveClient(member.AgentID);
455 if (client == null)
456 {
457 // If they're not local, forward across the grid
458 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID);
459 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
460 }
461 else
462 {
463 // Deliver locally, directly
464 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name);
465 ProcessMessageFromGroupSession(msg);
466 }
467 }
468 }
469
470 void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) 486 void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID)
471 { 487 {
472 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 488 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);