aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorHomer Horwitz2008-11-16 23:50:18 +0000
committerHomer Horwitz2008-11-16 23:50:18 +0000
commit07afe9c13741cd560f42696cf764a1d4a92ffc42 (patch)
tree278a9d4531183ef1e697a15f254b6026a857a3bf /OpenSim/Region
parentRemove a redundant parameter (diff)
downloadopensim-SC-07afe9c13741cd560f42696cf764a1d4a92ffc42.zip
opensim-SC-07afe9c13741cd560f42696cf764a1d4a92ffc42.tar.gz
opensim-SC-07afe9c13741cd560f42696cf764a1d4a92ffc42.tar.bz2
opensim-SC-07afe9c13741cd560f42696cf764a1d4a92ffc42.tar.xz
Fix friends again. Friends-handling is now stateless and, thanks to
MessageTransferModule, much easier to understand (I hope).
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs398
1 files changed, 135 insertions, 263 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
index f07cd4c..daff760 100644
--- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs
@@ -101,7 +101,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
101 101
102 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>(); 102 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>();
103 103
104 private Dictionary<UUID, Transaction> m_pendingFriendRequests = new Dictionary<UUID, Transaction>();
105 private Dictionary<UUID, UUID> m_pendingCallingcardRequests = new Dictionary<UUID,UUID>(); 104 private Dictionary<UUID, UUID> m_pendingCallingcardRequests = new Dictionary<UUID,UUID>();
106 105
107 private Scene m_initialScene; // saves a lookup if we don't have a specific scene 106 private Scene m_initialScene; // saves a lookup if we don't have a specific scene
@@ -263,7 +262,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
263 // to a user to 'add a friend' without causing dialog box spam 262 // to a user to 'add a friend' without causing dialog box spam
264 263
265 // Subscribe to instant messages 264 // Subscribe to instant messages
266// client.OnInstantMessage += OnInstantMessage; 265 client.OnInstantMessage += OnInstantMessage;
267 266
268 // Friend list management 267 // Friend list management
269 client.OnApproveFriendRequest += OnApproveFriendRequest; 268 client.OnApproveFriendRequest += OnApproveFriendRequest;
@@ -369,233 +368,143 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
369 368
370 #region FriendRequestHandling 369 #region FriendRequestHandling
371 370
372 private void OnInstantMessage(IClientAPI client, UUID fromAgentID, 371 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
373 UUID toAgentID,
374 UUID imSessionID, uint timestamp, string fromAgentName,
375 string message, byte dialog, bool fromGroup, byte offline,
376 uint ParentEstateID, Vector3 Position, UUID RegionID,
377 byte[] binaryBucket)
378 { 372 {
379 // Friend Requests go by Instant Message.. using the dialog param 373 // Friend Requests go by Instant Message.. using the dialog param
380 // https://wiki.secondlife.com/wiki/ImprovedInstantMessage 374 // https://wiki.secondlife.com/wiki/ImprovedInstantMessage
375 UUID fromAgentID = new UUID(im.fromAgentID);
376 UUID toAgentID = new UUID(im.toAgentID);
381 377
382 if (dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38 378 if (im.dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38
383 { 379 {
384 // this is triggered by the initiating agent and has two parts: 380 // this is triggered by the initiating agent:
385 // A local agent offers friendship to some possibly remote friend. 381 // A local agent offers friendship to some possibly remote friend.
386 // A IM is triggered, processed here (1), sent to the destination region, 382 // A IM is triggered, processed here and sent to the friend (possibly in a remote region).
387 // and processed there in this part of the code again (2).
388 // (1) has fromAgentSession != UUID.Zero,
389 // (2) has fromAgentSession == UUID.Zero (don't leak agent sessions to other agents)
390 // For (1), build the IM to send to the other region (and trigger sending it)
391 // FOr (2), just store the transaction; we will wait for Approval or Decline
392 383
393 // some properties are misused here: 384 // some properties are misused here:
394 // fromAgentName is the *destination* name (the friend we offer friendship to) 385 // fromAgentName is the *destination* name (the friend we offer friendship to)
395 386
396 // (1)
397 // send the friendship-offer to the target
398 m_log.InfoFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}", 387 m_log.InfoFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}",
399 fromAgentID, fromAgentName, toAgentID, imSessionID, message, offline); 388 im.fromAgentID, im.fromAgentName, im.toAgentID, im.imSessionID, im.message, im.offline);
400
401 UUID transactionID = UUID.Random();
402 389
403 // 1.20 protocol sends an UUID in the message field, instead of the friendship offer text. 390 // 1.20 protocol sends an UUID in the message field, instead of the friendship offer text.
404 // For interoperability, we have to clear that 391 // For interoperability, we have to clear that
405 if (Util.isUUID(message)) message = ""; 392 if (Util.isUUID(im.message)) im.message = "";
406
407 GridInstantMessage msg = new GridInstantMessage();
408 msg.fromAgentID = fromAgentID.Guid;
409 msg.toAgentID = toAgentID.Guid;
410 msg.imSessionID = transactionID.Guid; // Start new transaction
411 m_log.DebugFormat("[FRIEND]: new transactionID: {0}", msg.imSessionID);
412 msg.timestamp = timestamp;
413 if (client != null)
414 {
415 msg.fromAgentName = client.Name; // fromAgentName;
416 }
417 else
418 {
419 msg.fromAgentName = "(hippos)"; // Added for posterity. This means that we can't figure out who sent it
420 }
421 msg.message = message;
422 msg.dialog = dialog;
423 msg.fromGroup = fromGroup;
424 msg.offline = offline;
425 msg.ParentEstateID = ParentEstateID;
426 msg.Position = Position;
427 msg.RegionID = RegionID.Guid;
428 msg.binaryBucket = binaryBucket;
429
430 m_log.DebugFormat("[FRIEND]: storing transactionID {0} on sender side", transactionID);
431 lock (m_pendingFriendRequests)
432 {
433 m_pendingFriendRequests.Add(transactionID, new Transaction(fromAgentID, fromAgentName));
434 outPending();
435 }
436 393
437 // we don't want to get that new IM into here if we aren't local, as only on the destination 394 // be sneeky and use the initiator-UUID as transactionID. This means we can be stateless.
438 // should receive it. If we *are* local, *we* are the destination, so we have to receive it. 395 // we have to look up the agent name on friendship-approval, though.
439 // As grid-IMs are routed to all modules (in contrast to local IMs), we have to decide here. 396 im.imSessionID = im.fromAgentID;
397 im.fromAgentName = client.Name;
440 398
441 // We don't really care which local scene we pipe it through.
442 if (m_TransferModule != null) 399 if (m_TransferModule != null)
443 { 400 {
444 m_TransferModule.SendInstantMessage(msg, 401 // Send it to whoever is the destination.
445 delegate(bool success) {} 402 // If new friend is local, it will send an IM to the viewer.
403 // If new friend is remote, it will cause a OnGridInstantMessage on the remote server
404 m_TransferModule.SendInstantMessage(im,
405 delegate(bool success) {
406 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
407 }
446 ); 408 );
447 } 409 }
448 } 410 }
449 else if (dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39 411 else if (im.dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39
450 { 412 {
451 // accepting the friendship offer causes a type 39 IM being sent to the (possibly remote) initiator 413 m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {2} {3}, imsession {4} to {5}: {6} (dialog {7})",
452 // toAgentID is initiator, fromAgentID is new friend (which just approved) 414 client.AgentId, im.fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
453 m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})",
454 client != null ? client.AgentId.ToString() : "<null>",
455 fromAgentID, fromAgentName, imSessionID, toAgentID, message, dialog);
456 lock (m_pendingFriendRequests)
457 {
458 if (!m_pendingFriendRequests.ContainsKey(imSessionID))
459 {
460 m_log.DebugFormat("[FRIEND]: Got friendship approval from {0} to {1} without matching transaction {2}",
461 fromAgentID, toAgentID, imSessionID);
462 return; // unknown transaction
463 }
464 // else found pending friend request with that transaction => remove it if we handled all
465 if (--m_pendingFriendRequests[imSessionID].count <= 0) m_pendingFriendRequests.Remove(imSessionID);
466 outPending();
467 }
468
469 // a new friend was added in the initiator's and friend's data, so the cache entries are wrong now.
470 lock (m_friendLists)
471 {
472 m_friendLists.Invalidate(toAgentID);
473 m_friendLists.Invalidate(fromAgentID);
474 }
475
476 // now send presence update and add a calling card for the new friend
477 415
478 ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID);
479 if (initiator == null)
480 {
481 // quite wrong. Shouldn't happen.
482 m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID);
483 return;
484 }
485
486 // tell initiator that friend is online
487 initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID });
488
489 // find the folder for the friend...
490 InventoryFolderImpl folder =
491 initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard);
492 if (folder != null)
493 {
494 // ... and add the calling card
495 CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromAgentName);
496 }
497 } 416 }
498 else if (dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40 417 else if (im.dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40
499 { 418 {
500 // declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator 419 // declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator
501 // toAgentID is initiator, fromAgentID declined friendship 420 // toAgentID is initiator, fromAgentID declined friendship
502 m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})", 421 m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})",
503 client != null ? client.AgentId.ToString() : "<null>", 422 client != null ? client.AgentId.ToString() : "<null>",
504 fromAgentID, fromAgentName, imSessionID, toAgentID, message, dialog); 423 fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
505 424
506 // not much to do, just clean up the transaction... 425 // Send the decline to whoever is the destination.
507 lock (m_pendingFriendRequests) 426 GridInstantMessage msg = new GridInstantMessage(client.Scene, fromAgentID, client.Name, toAgentID,
508 { 427 im.dialog, im.message, im.offline != 0, im.Position);
509 if (!m_pendingFriendRequests.ContainsKey(imSessionID)) 428 // If new friend is local, it will send an IM to the viewer.
510 { 429 // If new friend is remote, it will cause a OnGridInstantMessage on the remote server
511 m_log.DebugFormat("[FRIEND]: Got friendship denial from {0} to {1} without matching transaction {2}", 430 m_TransferModule.SendInstantMessage(msg,
512 fromAgentID, toAgentID, imSessionID); 431 delegate(bool success) {
513 return; // unknown transaction 432 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
514 } 433 }
515 // else found pending friend request with that transaction => remove it if we handled all 434 );
516 if (--m_pendingFriendRequests[imSessionID].count <= 0) m_pendingFriendRequests.Remove(imSessionID);
517 outPending();
518 }
519 } 435 }
520 } 436 }
521 437
522 private void OnGridInstantMessage(GridInstantMessage msg) 438 private void OnGridInstantMessage(GridInstantMessage msg)
523 { 439 {
524 if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered) 440 // This event won't be raised unless we have that agent,
441 // so we can depend on the above not trying to send
442 // via grid again
443 m_log.DebugFormat("[FRIEND]: Got GridIM from {0}, to {1}, imSession {2}, message {3}, dialog {4}",
444 msg.fromAgentID, msg.toAgentID, msg.imSessionID, msg.message, msg.dialog);
445 if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered ||
446 msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted ||
447 msg.dialog == (byte)InstantMessageDialog.FriendshipDeclined)
525 { 448 {
526 // we are on the receiving end here; just add the transactionID 449 // this should succeed as we *know* the root agent is here.
527 // to the stored transactions for later lookup 450 m_TransferModule.SendInstantMessage(msg,
528 // 451 delegate(bool success) {
529 m_log.DebugFormat("[FRIEND]: storing transactionID {0} on "+ 452 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
530 "receiver side", msg.imSessionID);
531
532 lock (m_pendingFriendRequests)
533 {
534 // if both are on the same region-server, the transaction
535 // is stored already, but we have to update the name
536 //
537 if (m_pendingFriendRequests.ContainsKey(
538 new UUID(msg.imSessionID)))
539 {
540 m_pendingFriendRequests[new UUID(msg.imSessionID)].agentName =
541 msg.fromAgentName;
542 m_pendingFriendRequests[new UUID(msg.imSessionID)].count++;
543 } 453 }
544 else m_pendingFriendRequests.Add(new UUID(msg.imSessionID), 454 );
545 new Transaction(new UUID(msg.fromAgentID),
546 msg.fromAgentName));
547
548 outPending();
549 }
550
551 return;
552 } 455 }
553 456
554 // Just call the IM handler above 457 if (msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted)
555 // This event won't be raised unless we have that agent, 458 {
556 // so we can depend on the above not trying to send 459 // for accept friendship, we have to do a bit more
557 // via grid again 460 approveFriendship(new UUID(msg.fromAgentID), new UUID(msg.toAgentID), msg.fromAgentName);
558 // 461 }
559 OnInstantMessage(null, new UUID(msg.fromAgentID),
560 new UUID(msg.toAgentID), new UUID(msg.imSessionID),
561 msg.timestamp, msg.fromAgentName, msg.message,
562 msg.dialog, msg.fromGroup, msg.offline,
563 msg.ParentEstateID, msg.Position,
564 new UUID(msg.RegionID), msg.binaryBucket);
565 } 462 }
566 463
567 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID transactionID, List<UUID> callingCardFolders) 464 private void approveFriendship(UUID fromAgentID, UUID toAgentID, string fromName)
568 { 465 {
569 m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}", 466 m_log.DebugFormat("[FRIEND]: Approve friendship from {0} (ID: {1}) to {2}",
570 client.Name, client.AgentId, agentID, transactionID); 467 fromAgentID, fromName, toAgentID);
571 Transaction transaction; 468
572 lock (m_pendingFriendRequests) 469 // a new friend was added in the initiator's and friend's data, so the cache entries are wrong now.
470 lock (m_friendLists)
573 { 471 {
574 if (!m_pendingFriendRequests.TryGetValue(transactionID, out transaction)) 472 m_friendLists.Invalidate(fromAgentID);
575 { 473 m_friendLists.Invalidate(toAgentID);
576 m_log.DebugFormat("[FRIEND]: Got friendship approval {0} from {1} ({2}) without matching transaction {3}", 474 }
577 agentID, client.AgentId, client.Name, transactionID); 475
578 return; // unknown transaction 476 // now send presence update and add a calling card for the new friend
579 } 477
580 // else found pending friend request with that transaction => remove if done with all 478 ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID);
581 if (--m_pendingFriendRequests[transactionID].count <= 0) m_pendingFriendRequests.Remove(transactionID); 479 if (initiator == null)
582 outPending(); 480 {
481 // quite wrong. Shouldn't happen.
482 m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID);
483 return;
583 } 484 }
584 485
585 UUID friendID = transaction.agentID; 486 m_log.DebugFormat("[FRIEND]: Tell {0} that {1} is online",
586 m_log.DebugFormat("[FRIEND]: {0} ({1}) approved friendship request from {2}", 487 initiator.Name, fromName);
587 client.Name, client.AgentId, friendID); 488 // tell initiator that friend is online
489 initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID });
588 490
589 Scene SceneAgentIn = m_initialScene; 491 // find the folder for the friend...
590 // we need any presence to send the packets to, not necessarily the root agent... 492 InventoryFolderImpl folder =
591 ScenePresence agentpresence = GetAnyPresenceFromAgentID(agentID); 493 initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard);
592 if (agentpresence != null) 494 if (folder != null)
593 { 495 {
594 SceneAgentIn = agentpresence.Scene; 496 // ... and add the calling card
497 CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromName);
595 } 498 }
499 }
500
501 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
502 {
503 m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}",
504 client.Name, client.AgentId, agentID, friendID);
596 505
597 // store the new friend persistently for both avatars 506 // store the new friend persistently for both avatars
598 SceneAgentIn.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline); 507 m_initialScene.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline);
599 508
600 // The cache entries aren't valid anymore either, as we just added a friend to both sides. 509 // The cache entries aren't valid anymore either, as we just added a friend to both sides.
601 lock (m_friendLists) 510 lock (m_friendLists)
@@ -604,94 +513,67 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
604 m_friendLists.Invalidate(friendID); 513 m_friendLists.Invalidate(friendID);
605 } 514 }
606 515
607 // create calling card 516 // if it's a local friend, we don't have to do the lookup
608 CreateCallingCard(client, friendID, callingCardFolders[0], transaction.agentName); 517 ScenePresence friendPresence = GetAnyPresenceFromAgentID(friendID);
609 518
610 // Compose response to other agent. 519 if(friendPresence != null)
611 GridInstantMessage msg = new GridInstantMessage();
612 msg.toAgentID = friendID.Guid;
613 msg.fromAgentID = agentID.Guid;
614 msg.fromAgentName = client.Name;
615 msg.fromGroup = false;
616 msg.imSessionID = transactionID.Guid;
617 msg.message = agentID.Guid.ToString();
618 msg.ParentEstateID = 0;
619 msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
620 msg.RegionID = SceneAgentIn.RegionInfo.RegionID.Guid;
621 msg.dialog = (byte) InstantMessageDialog.FriendshipAccepted;
622 msg.Position = Vector3.Zero;
623 msg.offline = (byte) 0;
624 msg.binaryBucket = new byte[0];
625
626 // we don't want to get that new IM into here if we aren't local, as only on the destination
627 // should receive it. If we *are* local, *we* are the destination, so we have to receive it.
628 // As grid-IMs are routed to all modules (in contrast to local IMs), we have to decide here.
629
630 // now we have to inform the agent about the friend. For the opposite direction, this happens in the handler
631 // of the type 39 IM
632 if (m_TransferModule != null)
633 { 520 {
634 m_TransferModule.SendInstantMessage(msg, 521 m_log.Debug("[FRIEND]: Local agent detected.");
635 delegate(bool success) {} 522
636 ); 523 // create calling card
524 CreateCallingCard(client, friendID, callingCardFolders[0], friendPresence.Name);
525
526 // local message means OnGridInstantMessage won't be triggered, so do the work here.
527 friendPresence.ControllingClient.SendInstantMessage(agentID, agentID.ToString(), friendID, client.Name,
528 (byte)InstantMessageDialog.FriendshipAccepted,
529 (uint)Util.UnixTimeSinceEpoch());
530 approveFriendship(agentID, friendID, client.Name);
531 }
532 else
533 {
534 m_log.Debug("[FRIEND]: Remote agent detected.");
535
536 // fetch the friend's name for the calling card.
537 CachedUserInfo info = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(friendID);
538
539 // create calling card
540 CreateCallingCard(client, friendID, callingCardFolders[0],
541 info.UserProfile.FirstName + " " + info.UserProfile.SurName);
542
543 // Compose (remote) response to friend.
544 GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
545 (byte)InstantMessageDialog.FriendshipAccepted,
546 agentID.ToString(), false, Vector3.Zero);
547 if (m_TransferModule != null)
548 {
549 m_TransferModule.SendInstantMessage(msg,
550 delegate(bool success) {
551 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
552 }
553 );
554 }
637 } 555 }
638 556
639 // tell client that new friend is online 557 // tell client that new friend is online
640 client.SendAgentOnline(new UUID[] { friendID }); 558 client.SendAgentOnline(new UUID[] { friendID });
641 } 559 }
642 560
643 private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID transactionID, List<UUID> callingCardFolders) 561 private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
644 { 562 {
645 m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}", 563 m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}",
646 client.Name, client.AgentId, agentID, transactionID); 564 client.Name, client.AgentId, agentID, friendID);
647 Transaction transaction;
648 lock (m_pendingFriendRequests)
649 {
650 if (!m_pendingFriendRequests.TryGetValue(transactionID, out transaction))
651 {
652 m_log.DebugFormat("[FRIEND]: Got friendship denial {0} from {1} ({2}) without matching transaction {3}",
653 agentID, client.AgentId, client.Name, transactionID);
654 return;
655 }
656 // else found pending friend request with that transaction.
657 if (--m_pendingFriendRequests[transactionID].count <= 0) m_pendingFriendRequests.Remove(transactionID);
658 outPending();
659 }
660 UUID friendID = transaction.agentID;
661
662 Scene SceneAgentIn = m_initialScene;
663 ScenePresence agentpresence = GetRootPresenceFromAgentID(agentID);
664 if (agentpresence != null)
665 {
666 SceneAgentIn = agentpresence.Scene;
667 }
668 565
669 // Compose response to other agent. 566 // Compose response to other agent.
670 GridInstantMessage msg = new GridInstantMessage(); 567 GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
671 msg.toAgentID = friendID.Guid; 568 (byte)InstantMessageDialog.FriendshipDeclined,
672 msg.fromAgentID = agentID.Guid; 569 agentID.ToString(), false, Vector3.Zero);
673 msg.fromAgentName = client.Name; 570 // send decline to initiator
674 msg.fromGroup = false;
675 msg.imSessionID = transactionID.Guid;
676 msg.message = agentID.Guid.ToString();
677 msg.ParentEstateID = 0;
678 msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
679 msg.RegionID = SceneAgentIn.RegionInfo.RegionID.Guid;
680 msg.dialog = (byte) InstantMessageDialog.FriendshipDeclined;
681 msg.Position = Vector3.Zero;
682 msg.offline = (byte) 0;
683 msg.binaryBucket = new byte[0];
684
685 // we don't want to get that new IM into here if we aren't local, as only on the destination
686 // should receive it. If we *are* local, *we* are the destination, so we have to receive it.
687 // As grid-IMs are routed to all modules (in contrast to local IMs), we have to decide here.
688
689 // now we have to inform the agent about the friend. For the opposite direction, this happens in the handler
690 // of the type 39 IM
691 if (m_TransferModule != null) 571 if (m_TransferModule != null)
692 { 572 {
693 m_TransferModule.SendInstantMessage(msg, 573 m_TransferModule.SendInstantMessage(msg,
694 delegate(bool success) {} 574 delegate(bool success) {
575 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
576 }
695 ); 577 );
696 } 578 }
697 } 579 }
@@ -824,8 +706,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
824 706
825 private void OnDeclineCallingCard(IClientAPI client, UUID transactionID) 707 private void OnDeclineCallingCard(IClientAPI client, UUID transactionID)
826 { 708 {
827 m_log.DebugFormat("[CALLING CARD]: User {0} declined card, tid {2}", 709 m_log.DebugFormat("[CALLING CARD]: User {0} (ID:{1}) declined card, tid {2}",
828 client.AgentId, transactionID); 710 client.Name, client.AgentId, transactionID);
829 UUID destID; 711 UUID destID;
830 lock (m_pendingCallingcardRequests) 712 lock (m_pendingCallingcardRequests)
831 { 713 {
@@ -1040,16 +922,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
1040 // tell everyone that we are offline 922 // tell everyone that we are offline
1041 SendPresenceState(remoteClient, fl, false); 923 SendPresenceState(remoteClient, fl, false);
1042 } 924 }
1043
1044 private void outPending()
1045 {
1046 m_log.DebugFormat("[FRIEND]: got {0} requests pending", m_pendingFriendRequests.Count);
1047 foreach (KeyValuePair<UUID, Transaction> pair in m_pendingFriendRequests)
1048 {
1049 m_log.DebugFormat("[FRIEND]: tid={0}, agent={1}, name={2}, count={3}",
1050 pair.Key, pair.Value.agentID, pair.Value.agentName, pair.Value.count);
1051 }
1052 }
1053 } 925 }
1054 926
1055 #endregion 927 #endregion