diff options
author | Charles Krinke | 2009-04-18 21:33:48 +0000 |
---|---|---|
committer | Charles Krinke | 2009-04-18 21:33:48 +0000 |
commit | 659b55905dc7e006ae73f3d569efdf52276aa825 (patch) | |
tree | f7df089ce48fa94895ad113afddc460688cb703b /OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs | |
parent | Allow reading of notecards by asset ID. (diff) | |
download | opensim-SC-659b55905dc7e006ae73f3d569efdf52276aa825.zip opensim-SC-659b55905dc7e006ae73f3d569efdf52276aa825.tar.gz opensim-SC-659b55905dc7e006ae73f3d569efdf52276aa825.tar.bz2 opensim-SC-659b55905dc7e006ae73f3d569efdf52276aa825.tar.xz |
Thank you kindly, MCortez, for a patch that:
Added is a patch that adds a rough Groups implementation. This patch allows
the creation, adding and maintaining Groups, Roles and Members. Work has begun
on a very naive implementation of messaging, and minimal support for notifications
{no attachments yet}. Proposals are not yet supported, but are on the to-do list.
This implementation is not active by default, and must be configured in
OpenSim.ini to become active.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs | 423 |
1 files changed, 423 insertions, 0 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs new file mode 100644 index 0000000..d14d135 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs | |||
@@ -0,0 +1,423 @@ | |||
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 | |||
28 | using System; | ||
29 | //using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Reflection; | ||
32 | |||
33 | |||
34 | using log4net; | ||
35 | using Nini.Config; | ||
36 | |||
37 | using OpenMetaverse; | ||
38 | using OpenMetaverse.StructuredData; | ||
39 | |||
40 | using OpenSim.Framework; | ||
41 | using OpenSim.Region.CoreModules.Framework.EventQueue; | ||
42 | using OpenSim.Region.Framework.Interfaces; | ||
43 | using OpenSim.Region.Framework.Scenes; | ||
44 | |||
45 | |||
46 | using Caps = OpenSim.Framework.Communications.Capabilities.Caps; | ||
47 | |||
48 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | ||
49 | { | ||
50 | public class XmlRpcGroupsMessaging : INonSharedRegionModule | ||
51 | { | ||
52 | |||
53 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
54 | |||
55 | private List<Scene> m_SceneList = new List<Scene>(); | ||
56 | |||
57 | // must be NonShared for this to work, otherewise we may actually get multiple active clients | ||
58 | private Dictionary<Guid, IClientAPI> m_ActiveClients = new Dictionary<Guid, IClientAPI>(); | ||
59 | |||
60 | private IMessageTransferModule m_MsgTransferModule = null; | ||
61 | |||
62 | private IGroupsModule m_GroupsModule = null; | ||
63 | |||
64 | // Config Options | ||
65 | private bool m_GroupMessagingEnabled = true; | ||
66 | private bool m_debugEnabled = true; | ||
67 | |||
68 | #region IRegionModule Members | ||
69 | |||
70 | public void Initialise(IConfigSource config) | ||
71 | { | ||
72 | IConfig groupsConfig = config.Configs["Groups"]; | ||
73 | |||
74 | m_log.Info("[GROUPS-MESSAGING]: Initializing XmlRpcGroupsMessaging"); | ||
75 | |||
76 | if (groupsConfig == null) | ||
77 | { | ||
78 | // Do not run this module by default. | ||
79 | m_log.Info("[GROUPS-MESSAGING]: No config found in OpenSim.ini -- not enabling XmlRpcGroupsMessaging"); | ||
80 | return; | ||
81 | } | ||
82 | else | ||
83 | { | ||
84 | if (!groupsConfig.GetBoolean("Enabled", false)) | ||
85 | { | ||
86 | m_log.Info("[GROUPS-MESSAGING]: Groups disabled in configuration"); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | if (groupsConfig.GetString("Module", "Default") != "XmlRpcGroups") | ||
91 | { | ||
92 | m_log.Info("[GROUPS-MESSAGING]: Config Groups Module not set to XmlRpcGroups"); | ||
93 | |||
94 | return; | ||
95 | } | ||
96 | |||
97 | m_GroupMessagingEnabled = groupsConfig.GetBoolean("XmlRpcMessagingEnabled", true); | ||
98 | |||
99 | if (!m_GroupMessagingEnabled) | ||
100 | { | ||
101 | m_log.Info("[GROUPS-MESSAGING]: XmlRpcGroups Messaging disabled."); | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | m_debugEnabled = groupsConfig.GetBoolean("XmlRpcDebugEnabled", true); | ||
106 | |||
107 | } | ||
108 | |||
109 | m_log.Info("[GROUPS-MESSAGING]: XmlRpcGroupsMessaging starting up"); | ||
110 | |||
111 | } | ||
112 | |||
113 | public void AddRegion(Scene scene) | ||
114 | { | ||
115 | } | ||
116 | public void RegionLoaded(Scene scene) | ||
117 | { | ||
118 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
119 | |||
120 | if (!m_GroupMessagingEnabled) | ||
121 | return; | ||
122 | |||
123 | |||
124 | m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); | ||
125 | |||
126 | // No groups module, no groups messaging | ||
127 | if (m_GroupsModule == null) | ||
128 | { | ||
129 | m_GroupMessagingEnabled = false; | ||
130 | m_log.Info("[GROUPS-MESSAGING]: Could not get IGroupsModule, XmlRpcGroupsMessaging is now disabled."); | ||
131 | Close(); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | m_MsgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>(); | ||
136 | |||
137 | // No message transfer module, no groups messaging | ||
138 | if (m_MsgTransferModule == null) | ||
139 | { | ||
140 | m_GroupMessagingEnabled = false; | ||
141 | m_log.Info("[GROUPS-MESSAGING]: Could not get MessageTransferModule"); | ||
142 | Close(); | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | |||
147 | m_SceneList.Add(scene); | ||
148 | |||
149 | scene.EventManager.OnNewClient += OnNewClient; | ||
150 | scene.EventManager.OnClientClosed += OnClientClosed; | ||
151 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; | ||
152 | |||
153 | } | ||
154 | |||
155 | public void RemoveRegion(Scene scene) | ||
156 | { | ||
157 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
158 | |||
159 | m_SceneList.Remove(scene); | ||
160 | } | ||
161 | |||
162 | |||
163 | public void Close() | ||
164 | { | ||
165 | m_log.Debug("[GROUPS-MESSAGING]: Shutting down XmlRpcGroupsMessaging module."); | ||
166 | |||
167 | |||
168 | foreach (Scene scene in m_SceneList) | ||
169 | { | ||
170 | scene.EventManager.OnNewClient -= OnNewClient; | ||
171 | scene.EventManager.OnClientClosed -= OnClientClosed; | ||
172 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; | ||
173 | } | ||
174 | |||
175 | m_SceneList.Clear(); | ||
176 | |||
177 | m_GroupsModule = null; | ||
178 | m_MsgTransferModule = null; | ||
179 | } | ||
180 | |||
181 | public string Name | ||
182 | { | ||
183 | get { return "XmlRpcGroupsMessaging"; } | ||
184 | } | ||
185 | |||
186 | #endregion | ||
187 | |||
188 | #region SimGridEventHandlers | ||
189 | |||
190 | private void OnNewClient(IClientAPI client) | ||
191 | { | ||
192 | RegisterClientAgent(client); | ||
193 | } | ||
194 | private void OnClientClosed(UUID AgentId) | ||
195 | { | ||
196 | UnregisterClientAgent(AgentId); | ||
197 | } | ||
198 | |||
199 | private void OnGridInstantMessage(GridInstantMessage msg) | ||
200 | { | ||
201 | m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
202 | |||
203 | DebugGridInstantMessage(msg); | ||
204 | |||
205 | // Incoming message from a group | ||
206 | if ((msg.dialog == (byte)InstantMessageDialog.SessionSend) && (msg.fromGroup == true)) | ||
207 | { | ||
208 | if (m_ActiveClients.ContainsKey(msg.toAgentID)) | ||
209 | { | ||
210 | UUID GroupID = new UUID(msg.fromAgentID); | ||
211 | // SendMessageToGroup(im); | ||
212 | |||
213 | GroupRecord GroupInfo = m_GroupsModule.GetGroupRecord(GroupID); | ||
214 | if (GroupInfo != null) | ||
215 | { | ||
216 | |||
217 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Sending chatterbox invite instant message"); | ||
218 | |||
219 | // Force? open the group session dialog??? | ||
220 | IEventQueue eq = m_ActiveClients[msg.toAgentID].Scene.RequestModuleInterface<IEventQueue>(); | ||
221 | eq.ChatterboxInvitation( | ||
222 | GroupID | ||
223 | , GroupInfo.GroupName | ||
224 | , new UUID(msg.fromAgentID) | ||
225 | , msg.message, new UUID(msg.toAgentID) | ||
226 | , msg.fromAgentName | ||
227 | , msg.dialog | ||
228 | , msg.timestamp | ||
229 | , msg.offline==1 | ||
230 | , (int)msg.ParentEstateID | ||
231 | , msg.Position | ||
232 | , 1 | ||
233 | , new UUID(msg.imSessionID) | ||
234 | , msg.fromGroup | ||
235 | , Utils.StringToBytes(GroupInfo.GroupName) | ||
236 | ); | ||
237 | |||
238 | eq.ChatterBoxSessionAgentListUpdates( | ||
239 | new UUID(GroupID) | ||
240 | , new UUID(msg.fromAgentID) | ||
241 | , new UUID(msg.toAgentID) | ||
242 | , false //canVoiceChat | ||
243 | , false //isModerator | ||
244 | , false //text mute | ||
245 | ); | ||
246 | |||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
251 | } | ||
252 | |||
253 | #endregion | ||
254 | |||
255 | #region ClientEvents | ||
256 | private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) | ||
257 | { | ||
258 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
259 | |||
260 | DebugGridInstantMessage(im); | ||
261 | |||
262 | // Start group IM session | ||
263 | if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) | ||
264 | { | ||
265 | UUID GroupID = new UUID(im.toAgentID); | ||
266 | |||
267 | GroupRecord GroupInfo = m_GroupsModule.GetGroupRecord(GroupID); | ||
268 | if (GroupInfo != null) | ||
269 | { | ||
270 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Start Group Session for {0}", GroupInfo.GroupName); | ||
271 | |||
272 | // remoteClient.SendInstantMessage(new GridInstantMessage(remoteClient.Scene, GroupID, GroupProfile.Name, remoteClient.AgentId, (byte)OpenMetaverse.InstantMessageDialog.SessionSend, true, "Welcome", GroupID, false, new Vector3(), new byte[0])); | ||
273 | |||
274 | ChatterBoxSessionStartReplyViaCaps(remoteClient, GroupInfo.GroupName, GroupID); | ||
275 | |||
276 | IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); | ||
277 | queue.ChatterBoxSessionAgentListUpdates( | ||
278 | new UUID(GroupID) | ||
279 | , new UUID(im.fromAgentID) | ||
280 | , new UUID(im.toAgentID) | ||
281 | , false //canVoiceChat | ||
282 | , false //isModerator | ||
283 | , false //text mute | ||
284 | ); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | // Send a message to a group | ||
289 | if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) | ||
290 | { | ||
291 | UUID GroupID = new UUID(im.toAgentID); | ||
292 | |||
293 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Send message to session for group {0}", GroupID); | ||
294 | |||
295 | SendMessageToGroup(im, GroupID); | ||
296 | } | ||
297 | |||
298 | // Incoming message from a group | ||
299 | if ((im.dialog == (byte)InstantMessageDialog.SessionSend) && (im.fromGroup == true)) | ||
300 | { | ||
301 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Message from group session {0} going to agent {1}", im.fromAgentID, im.toAgentID); | ||
302 | } | ||
303 | } | ||
304 | #endregion | ||
305 | |||
306 | private void RegisterClientAgent(IClientAPI client) | ||
307 | { | ||
308 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
309 | |||
310 | lock (m_ActiveClients) | ||
311 | { | ||
312 | if (!m_ActiveClients.ContainsKey(client.AgentId.Guid)) | ||
313 | { | ||
314 | client.OnInstantMessage += OnInstantMessage; | ||
315 | |||
316 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] OnInstantMessage registered for {0}", client.Name); | ||
317 | |||
318 | m_ActiveClients.Add(client.AgentId.Guid, client); | ||
319 | } | ||
320 | else | ||
321 | { | ||
322 | // Remove old client connection for this agent | ||
323 | UnregisterClientAgent(client.AgentId); | ||
324 | |||
325 | // Add new client connection | ||
326 | RegisterClientAgent(client); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | private void UnregisterClientAgent(UUID agentID) | ||
331 | { | ||
332 | lock (m_ActiveClients) | ||
333 | { | ||
334 | if (m_ActiveClients.ContainsKey(agentID.Guid)) | ||
335 | { | ||
336 | IClientAPI client = m_ActiveClients[agentID.Guid]; | ||
337 | client.OnInstantMessage -= OnInstantMessage; | ||
338 | |||
339 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] OnInstantMessage unregistered for {0}", client.Name); | ||
340 | |||
341 | m_ActiveClients.Remove(agentID.Guid); | ||
342 | } | ||
343 | else | ||
344 | { | ||
345 | m_log.InfoFormat("[GROUPS-MESSAGING] Client closed that wasn't registered here."); | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | |||
350 | private void SendMessageToGroup(GridInstantMessage im, UUID groupID) | ||
351 | { | ||
352 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
353 | |||
354 | GridInstantMessage msg = new GridInstantMessage(); | ||
355 | msg.imSessionID = im.imSessionID; | ||
356 | msg.fromAgentID = im.imSessionID; // GroupID | ||
357 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); | ||
358 | msg.fromAgentName = im.fromAgentName; | ||
359 | msg.message = im.message; | ||
360 | msg.dialog = im.dialog; | ||
361 | msg.fromGroup = true; | ||
362 | msg.offline = (byte)0; | ||
363 | msg.ParentEstateID = im.ParentEstateID; | ||
364 | msg.Position = im.Position; | ||
365 | msg.RegionID = im.RegionID; | ||
366 | msg.binaryBucket = new byte[1] { 0 }; | ||
367 | |||
368 | foreach (GroupMembersData member in m_GroupsModule.GroupMembersRequest(null, groupID)) | ||
369 | { | ||
370 | msg.toAgentID = member.AgentID.Guid; | ||
371 | m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) | ||
376 | { | ||
377 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
378 | |||
379 | OSDMap moderatedMap = new OSDMap(4); | ||
380 | moderatedMap.Add("voice", OSD.FromBoolean(false)); | ||
381 | |||
382 | OSDMap sessionMap = new OSDMap(4); | ||
383 | sessionMap.Add("moderated_mode", moderatedMap); | ||
384 | sessionMap.Add("session_name", OSD.FromString(groupName)); | ||
385 | sessionMap.Add("type", OSD.FromInteger(0)); | ||
386 | sessionMap.Add("voice_enabled", OSD.FromBoolean(false)); | ||
387 | |||
388 | |||
389 | OSDMap bodyMap = new OSDMap(4); | ||
390 | bodyMap.Add("session_id", OSD.FromUUID(groupID)); | ||
391 | bodyMap.Add("temp_session_id", OSD.FromUUID(groupID)); | ||
392 | bodyMap.Add("success", OSD.FromBoolean(true)); | ||
393 | bodyMap.Add("session_info", sessionMap); | ||
394 | |||
395 | |||
396 | IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); | ||
397 | |||
398 | if (queue != null) | ||
399 | { | ||
400 | queue.Enqueue(EventQueueHelper.buildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId); | ||
401 | } | ||
402 | |||
403 | } | ||
404 | |||
405 | |||
406 | private void DebugGridInstantMessage(GridInstantMessage im) | ||
407 | { | ||
408 | if (m_debugEnabled) | ||
409 | { | ||
410 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: fromGroup({0})", im.fromGroup ? "True" : "False"); | ||
411 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString()); | ||
412 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: fromAgentID({0})", im.fromAgentID.ToString()); | ||
413 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: fromAgentName({0})", im.fromAgentName.ToString()); | ||
414 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: imSessionID({0})", im.imSessionID.ToString()); | ||
415 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: message({0})", im.message.ToString()); | ||
416 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: offline({0})", im.offline.ToString()); | ||
417 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: toAgentID({0})", im.toAgentID.ToString()); | ||
418 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | } | ||
423 | } | ||