aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups')
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs289
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs82
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs148
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs19
4 files changed, 402 insertions, 136 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
index 2802e2f..e1b6abb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -55,8 +55,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
55 private IGroupsServicesConnector m_groupData = null; 55 private IGroupsServicesConnector m_groupData = null;
56 56
57 // Config Options 57 // Config Options
58 private bool m_groupMessagingEnabled = false; 58 private bool m_groupMessagingEnabled;
59 private bool m_debugEnabled = true; 59 private bool m_debugEnabled;
60 60
61 /// <summary> 61 /// <summary>
62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information. 62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information.
@@ -113,7 +113,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
113 if (m_messageOnlineAgentsOnly) 113 if (m_messageOnlineAgentsOnly)
114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>(); 114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
115 115
116 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); 116 m_debugEnabled = groupsConfig.GetBoolean("MessagingDebugEnabled", m_debugEnabled);
117 } 117 }
118 118
119 m_log.InfoFormat( 119 m_log.InfoFormat(
@@ -127,6 +127,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
127 return; 127 return;
128 128
129 scene.RegisterModuleInterface<IGroupsMessagingModule>(this); 129 scene.RegisterModuleInterface<IGroupsMessagingModule>(this);
130
131 scene.AddCommand(
132 "Debug",
133 this,
134 "debug groups messaging verbose",
135 "debug groups messaging verbose <true|false>",
136 "This setting turns on very verbose groups messaging debugging",
137 HandleDebugGroupsMessagingVerbose);
130 } 138 }
131 139
132 public void RegionLoaded(Scene scene) 140 public void RegionLoaded(Scene scene)
@@ -218,6 +226,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
218 226
219 #endregion 227 #endregion
220 228
229 private void HandleDebugGroupsMessagingVerbose(object modules, string[] args)
230 {
231 if (args.Length < 5)
232 {
233 MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
234 return;
235 }
236
237 bool verbose = false;
238 if (!bool.TryParse(args[4], out verbose))
239 {
240 MainConsole.Instance.Output("Usage: debug groups messaging verbose <true|false>");
241 return;
242 }
243
244 m_debugEnabled = verbose;
245
246 MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
247 }
248
221 /// <summary> 249 /// <summary>
222 /// Not really needed, but does confirm that the group exists. 250 /// Not really needed, but does confirm that the group exists.
223 /// </summary> 251 /// </summary>
@@ -237,11 +265,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
237 return false; 265 return false;
238 } 266 }
239 } 267 }
240 268
241 public void SendMessageToGroup(GridInstantMessage im, UUID groupID) 269 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
242 { 270 {
243 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); 271 SendMessageToGroup(im, groupID, new UUID(im.fromAgentID), null);
272 }
273
274 public void SendMessageToGroup(
275 GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func<GroupMembersData, bool> sendCondition)
276 {
277 int requestStartTick = Environment.TickCount;
278
279 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(sendingAgentForGroupCalls, groupID);
244 int groupMembersCount = groupMembers.Count; 280 int groupMembersCount = groupMembers.Count;
281 HashSet<string> attemptDeliveryUuidSet = null;
245 282
246 if (m_messageOnlineAgentsOnly) 283 if (m_messageOnlineAgentsOnly)
247 { 284 {
@@ -257,10 +294,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
257 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); 294 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
258 } 295 }
259 296
260 HashSet<string> onlineAgentsUuidSet = new HashSet<string>(); 297 attemptDeliveryUuidSet
261 Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); 298 = new HashSet<string>(Array.ConvertAll<PresenceInfo, string>(onlineAgents, pi => pi.UserID));
299
300 //Array.ForEach<PresenceInfo>(onlineAgents, pi => attemptDeliveryUuidSet.Add(pi.UserID));
262 301
263 groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); 302 //groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
264 303
265 // if (m_debugEnabled) 304 // if (m_debugEnabled)
266// m_log.DebugFormat( 305// m_log.DebugFormat(
@@ -269,26 +308,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
269 } 308 }
270 else 309 else
271 { 310 {
311 attemptDeliveryUuidSet
312 = new HashSet<string>(groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()));
313
272 if (m_debugEnabled) 314 if (m_debugEnabled)
273 m_log.DebugFormat( 315 m_log.DebugFormat(
274 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", 316 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members",
275 groupID, groupMembers.Count); 317 groupID, groupMembers.Count);
276 } 318 }
277
278 int requestStartTick = Environment.TickCount;
279 319
280 foreach (GroupMembersData member in groupMembers) 320 foreach (GroupMembersData member in groupMembers)
281 { 321 {
282 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) 322 if (sendCondition != null)
323 {
324 if (!sendCondition(member))
325 {
326 if (m_debugEnabled)
327 m_log.DebugFormat(
328 "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition",
329 member.AgentID);
330
331 continue;
332 }
333 }
334 else if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID))
283 { 335 {
284 // Don't deliver messages to people who have dropped this session 336 // Don't deliver messages to people who have dropped this session
285 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); 337 if (m_debugEnabled)
338 m_log.DebugFormat(
339 "[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID);
340
286 continue; 341 continue;
287 } 342 }
288 343
289 // Copy Message 344 // Copy Message
290 GridInstantMessage msg = new GridInstantMessage(); 345 GridInstantMessage msg = new GridInstantMessage();
291 msg.imSessionID = groupID.Guid; 346 msg.imSessionID = im.imSessionID;
292 msg.fromAgentName = im.fromAgentName; 347 msg.fromAgentName = im.fromAgentName;
293 msg.message = im.message; 348 msg.message = im.message;
294 msg.dialog = im.dialog; 349 msg.dialog = im.dialog;
@@ -304,26 +359,51 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
304 359
305 msg.toAgentID = member.AgentID.Guid; 360 msg.toAgentID = member.AgentID.Guid;
306 361
307 IClientAPI client = GetActiveClient(member.AgentID); 362 if (attemptDeliveryUuidSet.Contains(member.AgentID.ToString()))
308 if (client == null)
309 { 363 {
310 // If they're not local, forward across the grid 364 IClientAPI client = GetActiveClient(member.AgentID);
311 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); 365 if (client == null)
312 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); 366 {
367 int startTick = Environment.TickCount;
368
369 // If they're not local, forward across the grid
370 m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { });
371
372 if (m_debugEnabled)
373 m_log.DebugFormat(
374 "[GROUPS-MESSAGING]: Delivering to {0} via grid took {1} ms",
375 member.AgentID, Environment.TickCount - startTick);
376 }
377 else
378 {
379 int startTick = Environment.TickCount;
380
381 ProcessMessageFromGroupSession(msg, client);
382
383 // Deliver locally, directly
384 if (m_debugEnabled)
385 m_log.DebugFormat(
386 "[GROUPS-MESSAGING]: Delivering to {0} locally took {1} ms",
387 member.AgentID, Environment.TickCount - startTick);
388 }
313 } 389 }
314 else 390 else
315 { 391 {
316 // Deliver locally, directly 392 int startTick = Environment.TickCount;
317 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); 393
318 ProcessMessageFromGroupSession(msg); 394 m_msgTransferModule.HandleUndeliverableMessage(msg, delegate(bool success) { });
395
396 if (m_debugEnabled)
397 m_log.DebugFormat(
398 "[GROUPS-MESSAGING]: Handling undeliverable message for {0} took {1} ms",
399 member.AgentID, Environment.TickCount - startTick);
319 } 400 }
320 } 401 }
321 402
322 // Temporary for assessing how long it still takes to send messages to large online groups. 403 if (m_debugEnabled)
323 if (m_messageOnlineAgentsOnly)
324 m_log.DebugFormat( 404 m_log.DebugFormat(
325 "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", 405 "[GROUPS-MESSAGING]: Total SendMessageToGroup for group {0} with {1} members, {2} candidates for delivery took {3} ms",
326 groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); 406 groupID, groupMembersCount, attemptDeliveryUuidSet.Count(), Environment.TickCount - requestStartTick);
327 } 407 }
328 408
329 #region SimGridEventHandlers 409 #region SimGridEventHandlers
@@ -348,7 +428,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
348 // Any other message type will not be delivered to a client by the 428 // Any other message type will not be delivered to a client by the
349 // Instant Message Module 429 // Instant Message Module
350 430
351
352 if (m_debugEnabled) 431 if (m_debugEnabled)
353 { 432 {
354 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 433 m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -362,13 +441,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
362 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) 441 || (msg.dialog == (byte)InstantMessageDialog.SessionAdd)
363 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) 442 || (msg.dialog == (byte)InstantMessageDialog.SessionDrop)))
364 { 443 {
365 ProcessMessageFromGroupSession(msg); 444 IClientAPI client = null;
445
446 if (msg.dialog == (byte)InstantMessageDialog.SessionSend)
447 {
448 client = GetActiveClient(new UUID(msg.toAgentID));
449
450 if (client != null)
451 {
452 if (m_debugEnabled)
453 m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name);
454 }
455 else
456 {
457 m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
458
459 return;
460 }
461 }
462
463 ProcessMessageFromGroupSession(msg, client);
366 } 464 }
367 } 465 }
368 466
369 private void ProcessMessageFromGroupSession(GridInstantMessage msg) 467 private void ProcessMessageFromGroupSession(GridInstantMessage msg, IClientAPI client)
370 { 468 {
371 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); 469 if (m_debugEnabled)
470 m_log.DebugFormat(
471 "[GROUPS-MESSAGING]: Session message from {0} going to agent {1}, sessionID {2}, type {3}",
472 msg.fromAgentName, msg.toAgentID, msg.imSessionID, (InstantMessageDialog)msg.dialog);
372 473
373 UUID AgentID = new UUID(msg.fromAgentID); 474 UUID AgentID = new UUID(msg.fromAgentID);
374 UUID GroupID = new UUID(msg.imSessionID); 475 UUID GroupID = new UUID(msg.imSessionID);
@@ -392,74 +493,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
392 // Add them to the session for now, and Invite them 493 // Add them to the session for now, and Invite them
393 m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); 494 m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID);
394 495
395 UUID toAgentID = new UUID(msg.toAgentID); 496 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null);
396 IClientAPI activeClient = GetActiveClient(toAgentID); 497 if (groupInfo != null)
397 if (activeClient != null)
398 { 498 {
399 GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); 499 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message");
400 if (groupInfo != null) 500
401 { 501 // Force? open the group session dialog???
402 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); 502 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg);
403 503 IEventQueue eq = client.Scene.RequestModuleInterface<IEventQueue>();
404 // Force? open the group session dialog??? 504 eq.ChatterboxInvitation(
405 // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); 505 GroupID
406 IEventQueue eq = activeClient.Scene.RequestModuleInterface<IEventQueue>(); 506 , groupInfo.GroupName
407 eq.ChatterboxInvitation( 507 , new UUID(msg.fromAgentID)
408 GroupID 508 , msg.message
409 , groupInfo.GroupName 509 , new UUID(msg.toAgentID)
410 , new UUID(msg.fromAgentID) 510 , msg.fromAgentName
411 , msg.message 511 , msg.dialog
412 , new UUID(msg.toAgentID) 512 , msg.timestamp
413 , msg.fromAgentName 513 , msg.offline == 1
414 , msg.dialog 514 , (int)msg.ParentEstateID
415 , msg.timestamp 515 , msg.Position
416 , msg.offline == 1 516 , 1
417 , (int)msg.ParentEstateID 517 , new UUID(msg.imSessionID)
418 , msg.Position 518 , msg.fromGroup
419 , 1 519 , Utils.StringToBytes(groupInfo.GroupName)
420 , new UUID(msg.imSessionID) 520 );
421 , msg.fromGroup 521
422 , Utils.StringToBytes(groupInfo.GroupName) 522 eq.ChatterBoxSessionAgentListUpdates(
423 ); 523 new UUID(GroupID)
424 524 , new UUID(msg.fromAgentID)
425 eq.ChatterBoxSessionAgentListUpdates( 525 , new UUID(msg.toAgentID)
426 new UUID(GroupID) 526 , false //canVoiceChat
427 , new UUID(msg.fromAgentID) 527 , false //isModerator
428 , new UUID(msg.toAgentID) 528 , false //text mute
429 , false //canVoiceChat 529 );
430 , false //isModerator
431 , false //text mute
432 );
433 }
434 } 530 }
531
532 break;
435 } 533 }
436 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) 534 else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID))
437 { 535 {
438 // User hasn't dropped, so they're in the session, 536 // User hasn't dropped, so they're in the session,
439 // maybe we should deliver it. 537 // maybe we should deliver it.
440 IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); 538 client.SendInstantMessage(msg);
441 if (client != null)
442 {
443 // Deliver locally, directly
444 if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name);
445 client.SendInstantMessage(msg);
446 }
447 else
448 {
449 m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID);
450 }
451 } 539 }
540
452 break; 541 break;
453 542
454 default: 543 default:
455 m_log.WarnFormat("[GROUPS-MESSAGING]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString()); 544 client.SendInstantMessage(msg);
456 break; 545
546 break;;
457 } 547 }
458 } 548 }
459 549
460 #endregion 550 #endregion
461 551
462
463 #region ClientEvents 552 #region ClientEvents
464 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) 553 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
465 { 554 {
@@ -548,15 +637,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
548 // Don't log any normal IMs (privacy!) 637 // Don't log any normal IMs (privacy!)
549 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent) 638 if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent)
550 { 639 {
551 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False"); 640 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False");
552 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString()); 641 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", (InstantMessageDialog)im.dialog);
553 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID.ToString()); 642 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID);
554 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName.ToString()); 643 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName);
555 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID.ToString()); 644 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID);
556 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message.ToString()); 645 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message);
557 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline.ToString()); 646 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline);
558 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID.ToString()); 647 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID);
559 m_log.WarnFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); 648 m_log.DebugFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket"));
560 } 649 }
561 } 650 }
562 651
@@ -567,7 +656,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
567 /// </summary> 656 /// </summary>
568 private IClientAPI GetActiveClient(UUID agentID) 657 private IClientAPI GetActiveClient(UUID agentID)
569 { 658 {
570 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); 659 if (m_debugEnabled)
660 m_log.DebugFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID);
571 661
572 IClientAPI child = null; 662 IClientAPI child = null;
573 663
@@ -579,12 +669,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
579 { 669 {
580 if (!sp.IsChildAgent) 670 if (!sp.IsChildAgent)
581 { 671 {
582 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name); 672 if (m_debugEnabled)
673 m_log.DebugFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name);
674
583 return sp.ControllingClient; 675 return sp.ControllingClient;
584 } 676 }
585 else 677 else
586 { 678 {
587 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name); 679 if (m_debugEnabled)
680 m_log.DebugFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name);
681
588 child = sp.ControllingClient; 682 child = sp.ControllingClient;
589 } 683 }
590 } 684 }
@@ -593,12 +687,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
593 // If we didn't find a root, then just return whichever child we found, or null if none 687 // If we didn't find a root, then just return whichever child we found, or null if none
594 if (child == null) 688 if (child == null)
595 { 689 {
596 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); 690 if (m_debugEnabled)
691 m_log.DebugFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID);
597 } 692 }
598 else 693 else
599 { 694 {
600 if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); 695 if (m_debugEnabled)
696 m_log.DebugFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name);
601 } 697 }
698
602 return child; 699 return child;
603 } 700 }
604 701
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 2764465..0512e48 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -77,9 +77,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
77 77
78 private List<Scene> m_sceneList = new List<Scene>(); 78 private List<Scene> m_sceneList = new List<Scene>();
79 79
80 private IMessageTransferModule m_msgTransferModule = null; 80 private IMessageTransferModule m_msgTransferModule;
81
82 private IGroupsMessagingModule m_groupsMessagingModule;
81 83
82 private IGroupsServicesConnector m_groupData = null; 84 private IGroupsServicesConnector m_groupData;
83 85
84 // Configuration settings 86 // Configuration settings
85 private bool m_groupsEnabled = false; 87 private bool m_groupsEnabled = false;
@@ -185,10 +187,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
185 if (m_msgTransferModule == null) 187 if (m_msgTransferModule == null)
186 { 188 {
187 m_groupsEnabled = false; 189 m_groupsEnabled = false;
188 m_log.Warn("[GROUPS]: Could not get MessageTransferModule"); 190 m_log.Warn("[GROUPS]: Could not get IMessageTransferModule");
189 } 191 }
190 } 192 }
191 193
194 if (m_groupsMessagingModule == null)
195 {
196 m_groupsMessagingModule = scene.RequestModuleInterface<IGroupsMessagingModule>();
197
198 // No message transfer module, no notices, group invites, rejects, ejects, etc
199 if (m_groupsMessagingModule == null)
200 m_log.Warn("[GROUPS]: Could not get IGroupsMessagingModule");
201 }
202
192 lock (m_sceneList) 203 lock (m_sceneList)
193 { 204 {
194 m_sceneList.Add(scene); 205 m_sceneList.Add(scene);
@@ -363,7 +374,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
363 374
364 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) 375 private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im)
365 { 376 {
366 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 377 if (m_debugEnabled)
378 m_log.DebugFormat(
379 "[GROUPS]: {0} called for {1}, message type {2}",
380 System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name, (InstantMessageDialog)im.dialog);
367 381
368 // Group invitations 382 // Group invitations
369 if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) 383 if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline))
@@ -514,31 +528,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
514 OnNewGroupNotice(GroupID, NoticeID); 528 OnNewGroupNotice(GroupID, NoticeID);
515 } 529 }
516 530
517 // Send notice out to everyone that wants notices 531 if (m_debugEnabled)
518 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
519 { 532 {
520 if (m_debugEnabled) 533 foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID))
521 { 534 {
522 UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); 535 if (m_debugEnabled)
523 if (targetUser != null)
524 { 536 {
525 m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); 537 UserAccount targetUser
526 } 538 = m_sceneList[0].UserAccountService.GetUserAccount(
527 else 539 remoteClient.Scene.RegionInfo.ScopeID, member.AgentID);
528 { 540
529 m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices); 541 if (targetUser != null)
542 {
543 m_log.DebugFormat(
544 "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
545 NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices);
546 }
547 else
548 {
549 m_log.DebugFormat(
550 "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})",
551 NoticeID, member.AgentID, member.AcceptNotices);
552 }
530 } 553 }
531 } 554 }
555 }
532 556
533 if (member.AcceptNotices) 557 GridInstantMessage msg
534 { 558 = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
535 // Build notice IM
536 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
537 559
538 msg.toAgentID = member.AgentID.Guid; 560 if (m_groupsMessagingModule != null)
539 OutgoingInstantMessage(msg, member.AgentID); 561 m_groupsMessagingModule.SendMessageToGroup(
540 } 562 msg, GroupID, remoteClient.AgentId, gmd => gmd.AcceptNotices);
541 }
542 } 563 }
543 } 564 }
544 565
@@ -550,6 +571,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
550 571
551 UUID noticeID = new UUID(im.imSessionID); 572 UUID noticeID = new UUID(im.imSessionID);
552 573
574 if (m_debugEnabled)
575 m_log.DebugFormat("[GROUPS]: Requesting notice {0} for {1}", noticeID, remoteClient.AgentId);
576
553 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID); 577 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
554 if (notice != null) 578 if (notice != null)
555 { 579 {
@@ -559,17 +583,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
559 if (m_debugEnabled) 583 if (m_debugEnabled)
560 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); 584 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
561 585
586 string message;
562 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, 587 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
563 giver, attachmentUUID); 588 giver, attachmentUUID, out message);
564 589
565 if (itemCopy == null) 590 if (itemCopy == null)
566 { 591 {
567 remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); 592 remoteClient.SendAgentAlertMessage(message, false);
568 return; 593 return;
569 } 594 }
570 595
571 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); 596 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
572 } 597 }
598 else
599 {
600 if (m_debugEnabled)
601 m_log.DebugFormat(
602 "[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.",
603 noticeID, remoteClient.AgentId);
604 }
573 } 605 }
574 606
575 // Interop, received special 210 code for ejecting a group member 607 // Interop, received special 210 code for ejecting a group member
@@ -1366,7 +1398,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1366 presence.Grouptitle = Title; 1398 presence.Grouptitle = Title;
1367 1399
1368 if (! presence.IsChildAgent) 1400 if (! presence.IsChildAgent)
1369 presence.SendAvatarDataToAllAgents(); 1401 presence.SendAvatarDataToAllClients();
1370 } 1402 }
1371 } 1403 }
1372 } 1404 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index 26d2597..e03e71d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Net; 31using System.Net;
31using System.Reflection; 32using System.Reflection;
32using Nini.Config; 33using Nini.Config;
@@ -40,11 +41,11 @@ using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers; 41using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 42using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden; 43using OpenSim.Region.ClientStack.Linden;
44using OpenSim.Region.CoreModules.Avatar.InstantMessage;
43using OpenSim.Region.CoreModules.Framework; 45using OpenSim.Region.CoreModules.Framework;
44using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; 47using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
46using OpenSim.Tests.Common; 48using OpenSim.Tests.Common;
47using OpenSim.Tests.Common.Mock;
48 49
49namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests 50namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
50{ 51{
@@ -118,5 +119,150 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
118 119
119 // TODO: More checking of more actual event data. 120 // TODO: More checking of more actual event data.
120 } 121 }
122
123 [Test]
124 public void TestSendGroupNotice()
125 {
126 TestHelpers.InMethod();
127// TestHelpers.EnableLogging();
128
129 TestScene scene = new SceneHelpers().SetupScene();
130
131 MessageTransferModule mtm = new MessageTransferModule();
132 GroupsModule gm = new GroupsModule();
133 GroupsMessagingModule gmm = new GroupsMessagingModule();
134 MockGroupsServicesConnector mgsc = new MockGroupsServicesConnector();
135
136 IConfigSource configSource = new IniConfigSource();
137
138 {
139 IConfig config = configSource.AddConfig("Messaging");
140 config.Set("MessageTransferModule", mtm.Name);
141 }
142
143 {
144 IConfig config = configSource.AddConfig("Groups");
145 config.Set("Enabled", true);
146 config.Set("Module", gm.Name);
147 config.Set("DebugEnabled", true);
148 config.Set("MessagingModule", gmm.Name);
149 config.Set("MessagingEnabled", true);
150 }
151
152 SceneHelpers.SetupSceneModules(scene, configSource, mgsc, mtm, gm, gmm);
153
154 UUID userId = TestHelpers.ParseTail(0x1);
155 string subjectText = "newman";
156 string messageText = "Hello";
157 string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText);
158
159 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
160 TestClient tc = (TestClient)sp.ControllingClient;
161
162 UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true);
163 gm.JoinGroupRequest(tc, groupID);
164
165 // Create a second user who doesn't want to receive notices
166 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2));
167 TestClient tc2 = (TestClient)sp2.ControllingClient;
168 gm.JoinGroupRequest(tc2, groupID);
169 gm.SetGroupAcceptNotices(tc2, groupID, false, true);
170
171 List<GridInstantMessage> spReceivedMessages = new List<GridInstantMessage>();
172 tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im);
173
174 List<GridInstantMessage> sp2ReceivedMessages = new List<GridInstantMessage>();
175 tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im);
176
177 GridInstantMessage noticeIm = new GridInstantMessage();
178 noticeIm.fromAgentID = userId.Guid;
179 noticeIm.toAgentID = groupID.Guid;
180 noticeIm.message = combinedSubjectMessage;
181 noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice;
182
183 tc.HandleImprovedInstantMessage(noticeIm);
184
185 Assert.That(spReceivedMessages.Count, Is.EqualTo(1));
186 Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage));
187
188 List<GroupNoticeData> notices = mgsc.GetGroupNotices(UUID.Zero, groupID);
189 Assert.AreEqual(1, notices.Count);
190
191 // OpenSimulator (possibly also SL) transport the notice ID as the session ID!
192 Assert.AreEqual(notices[0].NoticeID.Guid, spReceivedMessages[0].imSessionID);
193
194 Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0));
195 }
196
197 /// <summary>
198 /// Run test with the MessageOnlineUsersOnly flag set.
199 /// </summary>
200 [Test]
201 public void TestSendGroupNoticeOnlineOnly()
202 {
203 TestHelpers.InMethod();
204 // TestHelpers.EnableLogging();
205
206 TestScene scene = new SceneHelpers().SetupScene();
207
208 MessageTransferModule mtm = new MessageTransferModule();
209 GroupsModule gm = new GroupsModule();
210 GroupsMessagingModule gmm = new GroupsMessagingModule();
211
212 IConfigSource configSource = new IniConfigSource();
213
214 {
215 IConfig config = configSource.AddConfig("Messaging");
216 config.Set("MessageTransferModule", mtm.Name);
217 }
218
219 {
220 IConfig config = configSource.AddConfig("Groups");
221 config.Set("Enabled", true);
222 config.Set("Module", gm.Name);
223 config.Set("DebugEnabled", true);
224 config.Set("MessagingModule", gmm.Name);
225 config.Set("MessagingEnabled", true);
226 config.Set("MessageOnlineUsersOnly", true);
227 }
228
229 SceneHelpers.SetupSceneModules(scene, configSource, new MockGroupsServicesConnector(), mtm, gm, gmm);
230
231 UUID userId = TestHelpers.ParseTail(0x1);
232 string subjectText = "newman";
233 string messageText = "Hello";
234 string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText);
235
236 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
237 TestClient tc = (TestClient)sp.ControllingClient;
238
239 UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true);
240 gm.JoinGroupRequest(tc, groupID);
241
242 // Create a second user who doesn't want to receive notices
243 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2));
244 TestClient tc2 = (TestClient)sp2.ControllingClient;
245 gm.JoinGroupRequest(tc2, groupID);
246 gm.SetGroupAcceptNotices(tc2, groupID, false, true);
247
248 List<GridInstantMessage> spReceivedMessages = new List<GridInstantMessage>();
249 tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im);
250
251 List<GridInstantMessage> sp2ReceivedMessages = new List<GridInstantMessage>();
252 tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im);
253
254 GridInstantMessage noticeIm = new GridInstantMessage();
255 noticeIm.fromAgentID = userId.Guid;
256 noticeIm.toAgentID = groupID.Guid;
257 noticeIm.message = combinedSubjectMessage;
258 noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice;
259
260 tc.HandleImprovedInstantMessage(noticeIm);
261
262 Assert.That(spReceivedMessages.Count, Is.EqualTo(1));
263 Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage));
264
265 Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0));
266 }
121 } 267 }
122} \ No newline at end of file 268} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index e28d0c2..a040f43 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -1012,7 +1012,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1012 Hashtable respData = (Hashtable)resp.Value; 1012 Hashtable respData = (Hashtable)resp.Value;
1013 if (respData.Contains("error") && !respData.Contains("succeed")) 1013 if (respData.Contains("error") && !respData.Contains("succeed"))
1014 { 1014 {
1015 LogRespDataToConsoleError(respData); 1015 LogRespDataToConsoleError(requestingAgentID, function, param, respData);
1016 } 1016 }
1017 1017
1018 return respData; 1018 return respData;
@@ -1040,20 +1040,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1040 return error; 1040 return error;
1041 } 1041 }
1042 1042
1043 private void LogRespDataToConsoleError(Hashtable respData) 1043 private void LogRespDataToConsoleError(UUID requestingAgentID, string function, Hashtable param, Hashtable respData)
1044 { 1044 {
1045 m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:"); 1045 m_log.ErrorFormat(
1046 1046 "[XMLRPC-GROUPS-CONNECTOR]: Error when calling {0} for {1} with params {2}. Response params are {3}",
1047 foreach (string key in respData.Keys) 1047 function, requestingAgentID, Util.PrettyFormatToSingleLine(param), Util.PrettyFormatToSingleLine(respData));
1048 {
1049 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key);
1050
1051 string[] lines = respData[key].ToString().Split(new char[] { '\n' });
1052 foreach (string line in lines)
1053 {
1054 m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line);
1055 }
1056 }
1057 } 1048 }
1058 1049
1059 /// <summary> 1050 /// <summary>