OpenSimMirror/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs

224 lines
9.9 KiB
C#
Raw Normal View History

/*
2008-03-18 05:16:43 +00:00
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
2007-12-11 01:26:06 +00:00
using System;
2007-11-04 14:34:45 +00:00
using System.Collections.Generic;
using System.Net;
using System.Reflection;
2008-05-01 14:45:56 +00:00
using System.Threading;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using log4net;
2007-11-04 14:34:45 +00:00
using OpenSim.Framework;
using OpenSim.Framework.Client;
2007-11-04 14:34:45 +00:00
using OpenSim.Framework.Communications;
using OpenSim.Framework.Capabilities;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Services.Interfaces;
using OSD = OpenMetaverse.StructuredData.OSD;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
2007-11-04 14:34:45 +00:00
namespace OpenSim.Region.Framework.Scenes
2007-11-04 14:34:45 +00:00
{
public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
/// <summary>
/// Class that Region communications runs through
/// </summary>
2007-11-04 14:34:45 +00:00
public class SceneCommunicationService //one instance per region
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
2007-11-04 14:34:45 +00:00
protected RegionInfo m_regionInfo;
protected Scene m_scene;
2008-05-01 18:04:42 +00:00
public void SetScene(Scene s)
{
m_scene = s;
m_regionInfo = s.RegionInfo;
}
public delegate void InformNeighbourThatRegionUpDelegate(INeighbourService nService, RegionInfo region, ulong regionhandle);
2008-05-01 18:04:42 +00:00
private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
{
InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
icon.EndInvoke(iar);
}
/// <summary>
/// Asynchronous call to information neighbouring regions that this region is up
/// </summary>
/// <param name="region"></param>
/// <param name="regionhandle"></param>
private void InformNeighboursThatRegionIsUpAsync(INeighbourService neighbourService, RegionInfo region, ulong regionhandle)
{
uint x = 0, y = 0;
Utils.LongToUInts(regionhandle, out x, out y);
GridRegion neighbour = null;
if (neighbourService != null)
neighbour = neighbourService.HelloNeighbour(regionhandle, region);
else
m_log.DebugFormat("[SCS]: No neighbour service provided for informing neigbhours of this region");
if (neighbour != null)
{
m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
m_scene.EventManager.TriggerOnRegionUp(neighbour);
}
else
{
m_log.InfoFormat("[INTERGRID]: Failed to inform neighbour {0}-{1} that I'm here.", x / Constants.RegionSize, y / Constants.RegionSize);
}
}
public void InformNeighborsThatRegionisUp(INeighbourService neighbourService, RegionInfo region)
{
//m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
foreach (GridRegion n in neighbours)
{
InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
d.BeginInvoke(neighbourService, region, n.RegionHandle,
InformNeighborsThatRegionisUpCompleted,
d);
}
}
public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, UUID scopeID, GridRegion dest);
2008-05-01 18:04:42 +00:00
/// <summary>
/// This informs all neighboring regions about the settings of it's child agent.
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
2008-05-16 01:22:11 +00:00
///
/// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
2008-05-16 01:22:11 +00:00
///
/// </summary>
private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, UUID scopeID, GridRegion dest)
{
//m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
try
{
m_scene.SimulationService.UpdateAgent(dest, cAgentData);
}
catch
{
// Ignore; we did our best
}
}
private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
{
SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
icon.EndInvoke(iar);
}
public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
{
// This assumes that we know what our neighbors are.
try
{
uint x = 0, y = 0;
List<string> simulatorList = new List<string>();
foreach (ulong regionHandle in presence.KnownRegionHandles)
{
if (regionHandle != m_regionInfo.RegionHandle)
{
// we only want to send one update to each simulator; the simulator will
// hand it off to the regions where a child agent exists, this does assume
// that the region position is cached or performance will degrade
Utils.LongToUInts(regionHandle, out x, out y);
GridRegion dest = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
2012-04-09 00:54:59 +00:00
if (dest == null)
continue;
if (!simulatorList.Contains(dest.ServerURI))
{
// we havent seen this simulator before, add it to the list
// and send it an update
simulatorList.Add(dest.ServerURI);
// Let move this to sync. Mono definitely does not like async networking.
m_scene.SimulationService.UpdateAgent(dest, cAgentData);
// Leaving this here as a reminder that we tried, and it sucks.
//SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
//d.BeginInvoke(cAgentData, m_regionInfo.ScopeID, dest,
// SendChildAgentDataUpdateCompleted,
// d);
}
}
}
}
catch (InvalidOperationException)
{
// We're ignoring a collection was modified error because this data gets old and outdated fast.
}
}
/// <summary>
/// Closes a child agent on a given region
/// </summary>
protected void SendCloseChildAgent(UUID agentID, ulong regionHandle)
{
// let's do our best, but there's not much we can do if the neighbour doesn't accept.
2008-05-16 01:22:11 +00:00
//m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
uint x = 0, y = 0;
Utils.LongToUInts(regionHandle, out x, out y);
2011-01-03 19:42:26 +00:00
GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
m_log.DebugFormat(
"[INTERGRID]: Sending close agent {0} to region at {1}-{2}",
agentID, destination.RegionCoordX, destination.RegionCoordY);
m_scene.SimulationService.CloseAgent(destination, agentID);
}
/// <summary>
/// Closes a child agents in a collection of regions. Does so asynchronously
/// so that the caller doesn't wait.
/// </summary>
/// <param name="agentID"></param>
/// <param name="regionslst"></param>
public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
{
foreach (ulong handle in regionslst)
{
SendCloseChildAgent(agentID, handle);
}
}
public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
{
return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
}
2007-11-04 14:34:45 +00:00
}
}