diff options
author | Charles Krinke | 2009-04-25 18:58:18 +0000 |
---|---|---|
committer | Charles Krinke | 2009-04-25 18:58:18 +0000 |
commit | c17a12544561de8103e1631c1a23dd225bd39698 (patch) | |
tree | 104af1bbb1dd1724b38731b37cf9b82f8d0b6fab /OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs | |
parent | Fix another typo in the ini example (diff) | |
download | opensim-SC-c17a12544561de8103e1631c1a23dd225bd39698.zip opensim-SC-c17a12544561de8103e1631c1a23dd225bd39698.tar.gz opensim-SC-c17a12544561de8103e1631c1a23dd225bd39698.tar.bz2 opensim-SC-c17a12544561de8103e1631c1a23dd225bd39698.tar.xz |
Thank you kindly, MCortez for a patch that:
The attached patch fixes a few problems that people were
having with the Messaging provided by the XmlRpcGroups
optional module, namely:
* Fixes 2x echo in group messaging
* Fixes problems with cross instance, non-neighbor, messaging
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs | 423 |
1 files changed, 278 insertions, 145 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs index b1b25aa..b1322ab 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsMessaging.cs | |||
@@ -26,7 +26,6 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | //using System.Collections; | ||
30 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
31 | using System.Reflection; | 30 | using System.Reflection; |
32 | 31 | ||
@@ -47,25 +46,27 @@ using Caps = OpenSim.Framework.Communications.Capabilities.Caps; | |||
47 | 46 | ||
48 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | 47 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups |
49 | { | 48 | { |
50 | public class XmlRpcGroupsMessaging : INonSharedRegionModule | 49 | public class XmlRpcGroupsMessaging : ISharedRegionModule |
51 | { | 50 | { |
52 | 51 | ||
53 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
54 | 53 | ||
55 | private List<Scene> m_SceneList = new List<Scene>(); | 54 | private List<Scene> m_sceneList = new List<Scene>(); |
56 | 55 | ||
57 | // must be NonShared for this to work, otherewise we may actually get multiple active clients | 56 | private IMessageTransferModule m_msgTransferModule = null; |
58 | private Dictionary<Guid, IClientAPI> m_ActiveClients = new Dictionary<Guid, IClientAPI>(); | ||
59 | 57 | ||
60 | private IMessageTransferModule m_MsgTransferModule = null; | 58 | private IGroupsModule m_groupsModule = null; |
59 | |||
60 | // TODO: Move this off to the xmlrpc server | ||
61 | public Dictionary<Guid, List<Guid>> m_agentsInGroupSession = new Dictionary<Guid, List<Guid>>(); | ||
62 | public Dictionary<Guid, List<Guid>> m_agentsDroppedSession = new Dictionary<Guid, List<Guid>>(); | ||
61 | 63 | ||
62 | private IGroupsModule m_GroupsModule = null; | ||
63 | 64 | ||
64 | // Config Options | 65 | // Config Options |
65 | private bool m_GroupMessagingEnabled = true; | 66 | private bool m_groupMessagingEnabled = true; |
66 | private bool m_debugEnabled = true; | 67 | private bool m_debugEnabled = true; |
67 | 68 | ||
68 | #region IRegionModule Members | 69 | #region IRegionModuleBase Members |
69 | 70 | ||
70 | public void Initialise(IConfigSource config) | 71 | public void Initialise(IConfigSource config) |
71 | { | 72 | { |
@@ -90,14 +91,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
90 | if (groupsConfig.GetString("Module", "Default") != "XmlRpcGroups") | 91 | if (groupsConfig.GetString("Module", "Default") != "XmlRpcGroups") |
91 | { | 92 | { |
92 | m_log.Info("[GROUPS-MESSAGING]: Config Groups Module not set to XmlRpcGroups"); | 93 | m_log.Info("[GROUPS-MESSAGING]: Config Groups Module not set to XmlRpcGroups"); |
93 | m_GroupMessagingEnabled = false; | 94 | m_groupMessagingEnabled = false; |
94 | 95 | ||
95 | return; | 96 | return; |
96 | } | 97 | } |
97 | 98 | ||
98 | m_GroupMessagingEnabled = groupsConfig.GetBoolean("XmlRpcMessagingEnabled", true); | 99 | m_groupMessagingEnabled = groupsConfig.GetBoolean("XmlRpcMessagingEnabled", true); |
99 | 100 | ||
100 | if (!m_GroupMessagingEnabled) | 101 | if (!m_groupMessagingEnabled) |
101 | { | 102 | { |
102 | m_log.Info("[GROUPS-MESSAGING]: XmlRpcGroups Messaging disabled."); | 103 | m_log.Info("[GROUPS-MESSAGING]: XmlRpcGroups Messaging disabled."); |
103 | return; | 104 | return; |
@@ -113,76 +114,74 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
113 | 114 | ||
114 | public void AddRegion(Scene scene) | 115 | public void AddRegion(Scene scene) |
115 | { | 116 | { |
117 | // NoOp | ||
116 | } | 118 | } |
117 | public void RegionLoaded(Scene scene) | 119 | public void RegionLoaded(Scene scene) |
118 | { | 120 | { |
119 | if (!m_GroupMessagingEnabled) | 121 | if (!m_groupMessagingEnabled) |
120 | return; | 122 | return; |
121 | 123 | ||
122 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 124 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
123 | 125 | ||
124 | 126 | ||
125 | m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); | 127 | m_groupsModule = scene.RequestModuleInterface<IGroupsModule>(); |
126 | 128 | ||
127 | // No groups module, no groups messaging | 129 | // No groups module, no groups messaging |
128 | if (m_GroupsModule == null) | 130 | if (m_groupsModule == null) |
129 | { | 131 | { |
130 | m_GroupMessagingEnabled = false; | 132 | m_groupMessagingEnabled = false; |
131 | m_log.Info("[GROUPS-MESSAGING]: Could not get IGroupsModule, XmlRpcGroupsMessaging is now disabled."); | 133 | m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsModule, XmlRpcGroupsMessaging is now disabled."); |
132 | Close(); | 134 | Close(); |
133 | return; | 135 | return; |
134 | } | 136 | } |
135 | 137 | ||
136 | m_MsgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>(); | 138 | m_msgTransferModule = scene.RequestModuleInterface<IMessageTransferModule>(); |
137 | 139 | ||
138 | // No message transfer module, no groups messaging | 140 | // No message transfer module, no groups messaging |
139 | if (m_MsgTransferModule == null) | 141 | if (m_msgTransferModule == null) |
140 | { | 142 | { |
141 | m_GroupMessagingEnabled = false; | 143 | m_groupMessagingEnabled = false; |
142 | m_log.Info("[GROUPS-MESSAGING]: Could not get MessageTransferModule"); | 144 | m_log.Error("[GROUPS-MESSAGING]: Could not get MessageTransferModule"); |
143 | Close(); | 145 | Close(); |
144 | return; | 146 | return; |
145 | } | 147 | } |
146 | 148 | ||
147 | 149 | ||
148 | m_SceneList.Add(scene); | 150 | m_sceneList.Add(scene); |
149 | 151 | ||
150 | scene.EventManager.OnNewClient += OnNewClient; | 152 | scene.EventManager.OnNewClient += OnNewClient; |
151 | scene.EventManager.OnClientClosed += OnClientClosed; | ||
152 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; | 153 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; |
153 | 154 | ||
154 | } | 155 | } |
155 | 156 | ||
156 | public void RemoveRegion(Scene scene) | 157 | public void RemoveRegion(Scene scene) |
157 | { | 158 | { |
158 | if (!m_GroupMessagingEnabled) | 159 | if (!m_groupMessagingEnabled) |
159 | return; | 160 | return; |
160 | 161 | ||
161 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 162 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
162 | 163 | ||
163 | m_SceneList.Remove(scene); | 164 | m_sceneList.Remove(scene); |
164 | } | 165 | } |
165 | 166 | ||
166 | 167 | ||
167 | public void Close() | 168 | public void Close() |
168 | { | 169 | { |
169 | if (!m_GroupMessagingEnabled) | 170 | if (!m_groupMessagingEnabled) |
170 | return; | 171 | return; |
171 | 172 | ||
172 | m_log.Debug("[GROUPS-MESSAGING]: Shutting down XmlRpcGroupsMessaging module."); | 173 | if(m_debugEnabled) m_log.Debug("[GROUPS-MESSAGING]: Shutting down XmlRpcGroupsMessaging module."); |
173 | |||
174 | 174 | ||
175 | foreach (Scene scene in m_SceneList) | 175 | foreach (Scene scene in m_sceneList) |
176 | { | 176 | { |
177 | scene.EventManager.OnNewClient -= OnNewClient; | 177 | scene.EventManager.OnNewClient -= OnNewClient; |
178 | scene.EventManager.OnClientClosed -= OnClientClosed; | ||
179 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; | 178 | scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; |
180 | } | 179 | } |
181 | 180 | ||
182 | m_SceneList.Clear(); | 181 | m_sceneList.Clear(); |
183 | 182 | ||
184 | m_GroupsModule = null; | 183 | m_groupsModule = null; |
185 | m_MsgTransferModule = null; | 184 | m_msgTransferModule = null; |
186 | } | 185 | } |
187 | 186 | ||
188 | public string Name | 187 | public string Name |
@@ -192,195 +191,293 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
192 | 191 | ||
193 | #endregion | 192 | #endregion |
194 | 193 | ||
195 | #region SimGridEventHandlers | 194 | #region ISharedRegionModule Members |
196 | 195 | ||
197 | private void OnNewClient(IClientAPI client) | 196 | public void PostInitialise() |
198 | { | 197 | { |
199 | RegisterClientAgent(client); | 198 | // NoOp |
200 | } | 199 | } |
201 | private void OnClientClosed(UUID AgentId) | 200 | |
201 | #endregion | ||
202 | |||
203 | #region SimGridEventHandlers | ||
204 | |||
205 | private void OnNewClient(IClientAPI client) | ||
202 | { | 206 | { |
203 | UnregisterClientAgent(AgentId); | 207 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] OnInstantMessage registered for {0}", client.Name); |
208 | |||
209 | client.OnInstantMessage += OnInstantMessage; | ||
204 | } | 210 | } |
205 | 211 | ||
206 | private void OnGridInstantMessage(GridInstantMessage msg) | 212 | private void OnGridInstantMessage(GridInstantMessage msg) |
207 | { | 213 | { |
208 | m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 214 | // The instant message module will only deliver messages of dialog types: |
215 | // MessageFromAgent, StartTyping, StopTyping, MessageFromObject | ||
216 | // | ||
217 | // Any other message type will not be delivered to a client by the | ||
218 | // Instant Message Module | ||
219 | |||
220 | |||
221 | if (m_debugEnabled) | ||
222 | { | ||
223 | m_log.DebugFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
209 | 224 | ||
210 | DebugGridInstantMessage(msg); | 225 | DebugGridInstantMessage(msg); |
226 | } | ||
211 | 227 | ||
212 | // Incoming message from a group | 228 | // Incoming message from a group |
213 | if ((msg.dialog == (byte)InstantMessageDialog.SessionSend) && (msg.fromGroup == true)) | 229 | if ((msg.fromGroup == true) && |
230 | ( (msg.dialog == (byte)InstantMessageDialog.SessionSend) | ||
231 | || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) | ||
232 | || (msg.dialog == (byte)InstantMessageDialog.SessionDrop) | ||
233 | )) | ||
234 | { | ||
235 | ProcessMessageFromGroupSession(msg); | ||
236 | } | ||
237 | |||
238 | } | ||
239 | |||
240 | private void ProcessMessageFromGroupSession(GridInstantMessage msg) | ||
241 | { | ||
242 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); | ||
243 | |||
244 | switch (msg.dialog) | ||
245 | { | ||
246 | case (byte)InstantMessageDialog.SessionAdd: | ||
247 | AddAgentToGroupSession(msg.fromAgentID, msg.imSessionID); | ||
248 | break; | ||
249 | |||
250 | case (byte)InstantMessageDialog.SessionDrop: | ||
251 | RemoveAgentFromGroupSession(msg.fromAgentID, msg.imSessionID); | ||
252 | break; | ||
253 | |||
254 | case (byte)InstantMessageDialog.SessionSend: | ||
255 | if (!m_agentsInGroupSession.ContainsKey(msg.toAgentID) | ||
256 | && !m_agentsDroppedSession.ContainsKey(msg.toAgentID)) | ||
214 | { | 257 | { |
215 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] OnGridInstantMessage from group session {0} going to agent {1}", msg.fromAgentID, msg.toAgentID); | 258 | // Agent not in session and hasn't dropped from session |
259 | // Add them to the session for now, and Invite them | ||
260 | AddAgentToGroupSession(msg.toAgentID, msg.imSessionID); | ||
216 | 261 | ||
217 | if (m_ActiveClients.ContainsKey(msg.toAgentID)) | 262 | UUID toAgentID = new UUID(msg.toAgentID); |
263 | IClientAPI activeClient = GetActiveClient(toAgentID); | ||
264 | if (activeClient != null) | ||
218 | { | 265 | { |
219 | UUID GroupID = new UUID(msg.fromAgentID); | 266 | UUID groupID = new UUID(msg.fromAgentID); |
220 | // SendMessageToGroup(im); | ||
221 | 267 | ||
222 | GroupRecord GroupInfo = m_GroupsModule.GetGroupRecord(GroupID); | 268 | GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); |
223 | if (GroupInfo != null) | 269 | if (groupInfo != null) |
224 | { | 270 | { |
225 | // TODO: Check to see if already a member of session, if so, do not send chatterbox, just forward message | 271 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Sending chatterbox invite instant message"); |
226 | |||
227 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Sending chatterbox invite instant message"); | ||
228 | 272 | ||
229 | // Force? open the group session dialog??? | 273 | // Force? open the group session dialog??? |
230 | IEventQueue eq = m_ActiveClients[msg.toAgentID].Scene.RequestModuleInterface<IEventQueue>(); | 274 | IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>(); |
231 | eq.ChatterboxInvitation( | 275 | eq.ChatterboxInvitation( |
232 | GroupID, | 276 | groupID |
233 | GroupInfo.GroupName, | 277 | , groupInfo.GroupName |
234 | new UUID(msg.fromAgentID), | 278 | , new UUID(msg.fromAgentID) |
235 | msg.message, new UUID(msg.toAgentID), | 279 | , msg.message, new UUID(msg.toAgentID) |
236 | msg.fromAgentName, | 280 | , msg.fromAgentName |
237 | msg.dialog, | 281 | , msg.dialog |
238 | msg.timestamp, | 282 | , msg.timestamp |
239 | msg.offline == 1, | 283 | , msg.offline == 1 |
240 | (int)msg.ParentEstateID, | 284 | , (int)msg.ParentEstateID |
241 | msg.Position, | 285 | , msg.Position |
242 | 1, | 286 | , 1 |
243 | new UUID(msg.imSessionID), | 287 | , new UUID(msg.imSessionID) |
244 | msg.fromGroup, | 288 | , msg.fromGroup |
245 | Utils.StringToBytes(GroupInfo.GroupName)); | 289 | , Utils.StringToBytes(groupInfo.GroupName) |
290 | ); | ||
246 | 291 | ||
247 | eq.ChatterBoxSessionAgentListUpdates( | 292 | eq.ChatterBoxSessionAgentListUpdates( |
248 | new UUID(GroupID), | 293 | new UUID(groupID) |
249 | new UUID(msg.fromAgentID), | 294 | , new UUID(msg.fromAgentID) |
250 | new UUID(msg.toAgentID), | 295 | , new UUID(msg.toAgentID) |
251 | false, //canVoiceChat | 296 | , false //canVoiceChat |
252 | false, //isModerator | 297 | , false //isModerator |
253 | false); //text mute | 298 | , false //text mute |
299 | ); | ||
300 | |||
254 | } | 301 | } |
255 | } | 302 | } |
256 | } | 303 | } |
304 | else if (!m_agentsDroppedSession.ContainsKey(msg.toAgentID)) | ||
305 | { | ||
306 | // User hasn't dropped, so they're in the session, | ||
307 | // maybe we should deliver it. | ||
308 | IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); | ||
309 | if (client != null) | ||
310 | { | ||
311 | // Deliver locally, directly | ||
312 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Delivering to {0} locally", client.Name); | ||
313 | client.SendInstantMessage(msg); | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | m_log.WarnFormat("[GROUPS-MESSAGING] Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); | ||
318 | } | ||
319 | } | ||
320 | break; | ||
257 | 321 | ||
322 | default: | ||
323 | m_log.WarnFormat("[GROUPS-MESSAGING] I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString()); | ||
324 | break; | ||
325 | } | ||
258 | } | 326 | } |
259 | 327 | ||
328 | |||
329 | |||
260 | #endregion | 330 | #endregion |
261 | 331 | ||
262 | #region ClientEvents | 332 | #region ClientEvents |
263 | private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) | ||
264 | { | ||
265 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
266 | |||
267 | DebugGridInstantMessage(im); | ||
268 | 333 | ||
269 | // Start group IM session | 334 | private void RemoveAgentFromGroupSession(Guid agentID, Guid sessionID) |
270 | if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) | 335 | { |
336 | if( m_agentsInGroupSession.ContainsKey(sessionID) ) | ||
271 | { | 337 | { |
272 | UUID GroupID = new UUID(im.toAgentID); | 338 | // If in session remove |
273 | 339 | if( m_agentsInGroupSession[sessionID].Contains(agentID) ) | |
274 | GroupRecord GroupInfo = m_GroupsModule.GetGroupRecord(GroupID); | ||
275 | if (GroupInfo != null) | ||
276 | { | 340 | { |
277 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Start Group Session for {0}", GroupInfo.GroupName); | 341 | m_agentsInGroupSession[sessionID].Remove(agentID); |
278 | 342 | } | |
279 | // remoteClient.SendInstantMessage(new GridInstantMessage(remoteClient.Scene, GroupID, GroupProfile.Name, remoteClient.AgentId, (byte)OpenMetaverse.InstantMessageDialog.SessionSend, true, "Welcome", GroupID, false, new Vector3(), new byte[0])); | ||
280 | |||
281 | ChatterBoxSessionStartReplyViaCaps(remoteClient, GroupInfo.GroupName, GroupID); | ||
282 | 343 | ||
283 | IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); | 344 | // If not in dropped list, add |
284 | queue.ChatterBoxSessionAgentListUpdates( | 345 | if( !m_agentsDroppedSession[sessionID].Contains(agentID) ) |
285 | new UUID(GroupID), | 346 | { |
286 | new UUID(im.fromAgentID), | 347 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Dropped {1} from session {0}", sessionID, agentID); |
287 | new UUID(im.toAgentID), | 348 | m_agentsDroppedSession[sessionID].Add(agentID); |
288 | false, //canVoiceChat | ||
289 | false, //isModerator | ||
290 | false); //text mute | ||
291 | } | 349 | } |
292 | } | 350 | } |
351 | } | ||
293 | 352 | ||
294 | // Send a message to a group | 353 | private void AddAgentToGroupSession(Guid agentID, Guid sessionID) |
295 | if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) | 354 | { |
296 | { | 355 | // Add Session Status if it doesn't exist for this session |
297 | UUID GroupID = new UUID(im.toAgentID); | 356 | CreateGroupSessionTracking(sessionID); |
298 | 357 | ||
299 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Send message to session for group {0}", GroupID); | 358 | // If nessesary, remove from dropped list |
359 | if( m_agentsDroppedSession[sessionID].Contains(agentID) ) | ||
360 | { | ||
361 | m_agentsDroppedSession[sessionID].Remove(agentID); | ||
362 | } | ||
300 | 363 | ||
301 | SendMessageToGroup(im, GroupID); | 364 | // If nessesary, add to in session list |
365 | if( !m_agentsInGroupSession[sessionID].Contains(agentID) ) | ||
366 | { | ||
367 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Added {1} to session {0}", sessionID, agentID); | ||
368 | m_agentsInGroupSession[sessionID].Add(agentID); | ||
302 | } | 369 | } |
370 | } | ||
303 | 371 | ||
304 | // Incoming message from a group | 372 | private void CreateGroupSessionTracking(Guid sessionID) |
305 | if ((im.dialog == (byte)InstantMessageDialog.SessionSend) && (im.fromGroup == true)) | 373 | { |
374 | if (!m_agentsInGroupSession.ContainsKey(sessionID)) | ||
306 | { | 375 | { |
307 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] Message from group session {0} going to agent {1}", im.fromAgentID, im.toAgentID); | 376 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Creating session tracking for : {0}", sessionID); |
377 | m_agentsInGroupSession.Add(sessionID, new List<Guid>()); | ||
378 | m_agentsDroppedSession.Add(sessionID, new List<Guid>()); | ||
308 | } | 379 | } |
309 | } | 380 | } |
310 | #endregion | ||
311 | 381 | ||
312 | private void RegisterClientAgent(IClientAPI client) | 382 | private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) |
313 | { | 383 | { |
314 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 384 | if (m_debugEnabled) |
385 | { | ||
386 | m_log.DebugFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
315 | 387 | ||
316 | lock (m_ActiveClients) | 388 | DebugGridInstantMessage(im); |
389 | } | ||
390 | |||
391 | // Start group IM session | ||
392 | if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) | ||
317 | { | 393 | { |
318 | if (!m_ActiveClients.ContainsKey(client.AgentId.Guid)) | 394 | UUID groupID = new UUID(im.toAgentID); |
395 | |||
396 | GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); | ||
397 | if (groupInfo != null) | ||
319 | { | 398 | { |
320 | client.OnInstantMessage += OnInstantMessage; | 399 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Start Group Session for {0}", groupInfo.GroupName); |
321 | 400 | ||
322 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] OnInstantMessage registered for {0}", client.Name); | 401 | AddAgentToGroupSession(im.fromAgentID, im.imSessionID); |
323 | 402 | ||
324 | m_ActiveClients.Add(client.AgentId.Guid, client); | 403 | ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, groupID); |
325 | } | ||
326 | else | ||
327 | { | ||
328 | // Remove old client connection for this agent | ||
329 | UnregisterClientAgent(client.AgentId); | ||
330 | 404 | ||
331 | // Add new client connection | 405 | IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); |
332 | RegisterClientAgent(client); | 406 | queue.ChatterBoxSessionAgentListUpdates( |
407 | new UUID(groupID) | ||
408 | , new UUID(im.fromAgentID) | ||
409 | , new UUID(im.toAgentID) | ||
410 | , false //canVoiceChat | ||
411 | , false //isModerator | ||
412 | , false //text mute | ||
413 | ); | ||
333 | } | 414 | } |
334 | } | 415 | } |
335 | } | 416 | |
336 | private void UnregisterClientAgent(UUID agentID) | 417 | // Send a message from locally connected client to a group |
337 | { | 418 | if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) |
338 | lock (m_ActiveClients) | ||
339 | { | 419 | { |
340 | if (m_ActiveClients.ContainsKey(agentID.Guid)) | 420 | UUID groupID = new UUID(im.toAgentID); |
341 | { | ||
342 | IClientAPI client = m_ActiveClients[agentID.Guid]; | ||
343 | client.OnInstantMessage -= OnInstantMessage; | ||
344 | 421 | ||
345 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] OnInstantMessage unregistered for {0}", client.Name); | 422 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Send message to session for group {0} with session ID {1}", groupID, im.imSessionID.ToString()); |
346 | 423 | ||
347 | m_ActiveClients.Remove(agentID.Guid); | 424 | SendMessageToGroup(im, groupID); |
348 | } | ||
349 | else | ||
350 | { | ||
351 | m_log.InfoFormat("[GROUPS-MESSAGING] Client closed that wasn't registered here."); | ||
352 | } | ||
353 | } | 425 | } |
354 | } | 426 | } |
427 | #endregion | ||
355 | 428 | ||
356 | private void SendMessageToGroup(GridInstantMessage im, UUID groupID) | 429 | private void SendMessageToGroup(GridInstantMessage im, UUID groupID) |
357 | { | 430 | { |
358 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 431 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
432 | |||
359 | 433 | ||
434 | foreach (GroupMembersData member in m_groupsModule.GroupMembersRequest(null, groupID)) | ||
435 | { | ||
436 | if (m_agentsDroppedSession[im.imSessionID].Contains(member.AgentID.Guid)) | ||
437 | { | ||
438 | // Don't deliver messages to people who have dropped this session | ||
439 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] {0} has dropped session, not delivering to them", member.AgentID); | ||
440 | continue; | ||
441 | } | ||
442 | |||
443 | // Copy Message | ||
360 | GridInstantMessage msg = new GridInstantMessage(); | 444 | GridInstantMessage msg = new GridInstantMessage(); |
361 | msg.imSessionID = im.imSessionID; | 445 | msg.imSessionID = im.imSessionID; |
362 | msg.fromAgentID = im.imSessionID; // GroupID | ||
363 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); | ||
364 | msg.fromAgentName = im.fromAgentName; | 446 | msg.fromAgentName = im.fromAgentName; |
365 | msg.message = im.message; | 447 | msg.message = im.message; |
366 | msg.dialog = im.dialog; | 448 | msg.dialog = im.dialog; |
367 | msg.fromGroup = true; | 449 | msg.offline = im.offline; |
368 | msg.offline = (byte)0; | ||
369 | msg.ParentEstateID = im.ParentEstateID; | 450 | msg.ParentEstateID = im.ParentEstateID; |
370 | msg.Position = im.Position; | 451 | msg.Position = im.Position; |
371 | msg.RegionID = im.RegionID; | 452 | msg.RegionID = im.RegionID; |
372 | msg.binaryBucket = new byte[1]{0}; | 453 | msg.binaryBucket = im.binaryBucket; |
454 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); | ||
455 | |||
456 | // Updat Pertinate fields to make it a "group message" | ||
457 | msg.fromAgentID = groupID.Guid; | ||
458 | msg.fromGroup = true; | ||
373 | 459 | ||
374 | foreach (GroupMembersData member in m_GroupsModule.GroupMembersRequest(null, groupID)) | ||
375 | { | ||
376 | msg.toAgentID = member.AgentID.Guid; | 460 | msg.toAgentID = member.AgentID.Guid; |
377 | m_MsgTransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 461 | |
462 | IClientAPI client = GetActiveClient(member.AgentID); | ||
463 | if (client == null) | ||
464 | { | ||
465 | // If they're not local, forward across the grid | ||
466 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Delivering to {0} via Grid", member.AgentID); | ||
467 | m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); | ||
468 | } | ||
469 | else | ||
470 | { | ||
471 | // Deliver locally, directly | ||
472 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); | ||
473 | ProcessMessageFromGroupSession(msg); | ||
474 | } | ||
378 | } | 475 | } |
379 | } | 476 | } |
380 | 477 | ||
381 | void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) | 478 | void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) |
382 | { | 479 | { |
383 | if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 480 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
384 | 481 | ||
385 | OSDMap moderatedMap = new OSDMap(4); | 482 | OSDMap moderatedMap = new OSDMap(4); |
386 | moderatedMap.Add("voice", OSD.FromBoolean(false)); | 483 | moderatedMap.Add("voice", OSD.FromBoolean(false)); |
@@ -398,12 +495,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
398 | bodyMap.Add("success", OSD.FromBoolean(true)); | 495 | bodyMap.Add("success", OSD.FromBoolean(true)); |
399 | bodyMap.Add("session_info", sessionMap); | 496 | bodyMap.Add("session_info", sessionMap); |
400 | 497 | ||
498 | |||
401 | IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); | 499 | IEventQueue queue = remoteClient.Scene.RequestModuleInterface<IEventQueue>(); |
402 | 500 | ||
403 | if (queue != null) | 501 | if (queue != null) |
404 | { | 502 | { |
405 | queue.Enqueue(EventQueueHelper.buildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId); | 503 | queue.Enqueue(EventQueueHelper.buildEvent("ChatterBoxSessionStartReply", bodyMap), remoteClient.AgentId); |
406 | } | 504 | } |
505 | |||
407 | } | 506 | } |
408 | 507 | ||
409 | 508 | ||
@@ -422,5 +521,39 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
422 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); | 521 | m_log.WarnFormat("[GROUPS-MESSAGING] IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); |
423 | } | 522 | } |
424 | } | 523 | } |
524 | |||
525 | #region Client Tools | ||
526 | |||
527 | /// <summary> | ||
528 | /// Try to find an active IClientAPI reference for agentID giving preference to root connections | ||
529 | /// </summary> | ||
530 | private IClientAPI GetActiveClient(UUID agentID) | ||
531 | { | ||
532 | IClientAPI child = null; | ||
533 | |||
534 | // Try root avatar first | ||
535 | foreach (Scene scene in m_sceneList) | ||
536 | { | ||
537 | if (scene.Entities.ContainsKey(agentID) && | ||
538 | scene.Entities[agentID] is ScenePresence) | ||
539 | { | ||
540 | ScenePresence user = (ScenePresence)scene.Entities[agentID]; | ||
541 | if (!user.IsChildAgent) | ||
542 | { | ||
543 | return user.ControllingClient; | ||
544 | } | ||
545 | else | ||
546 | { | ||
547 | child = user.ControllingClient; | ||
548 | } | ||
549 | } | ||
550 | } | ||
551 | |||
552 | // If we didn't find a root, then just return whichever child we found, or null if none | ||
553 | return child; | ||
554 | } | ||
555 | |||
556 | #endregion | ||
425 | } | 557 | } |
558 | |||
426 | } | 559 | } |