diff options
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs')
-rw-r--r-- | OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs | 398 |
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 |