/// <summary>
/// Add information about a new circuit so that later on we can authenticate a new client session.
/// </summary>
/// <param name = "circuitCode"></param>
/// <param name = "agentData"></param>
public virtual void AddNewCircuit(uint circuitCode, AgentCircuitData agentData)
{
lock (AgentCircuits)
{
AgentCircuits[circuitCode] = agentData;
}
}
/// <summary>
/// </summary>
/// <param name = "acircuit"></param>
/// <returns>uuid[;endpoint[;name]]</returns>
public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit)
{
if (acircuit.ServiceURLs.ContainsKey("HomeURI"))
{
string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString();
if (!agentsURI.EndsWith("/"))
agentsURI += "/";
// This is ugly, but there's no other way, given that the name is changed
// in the agent circuit data for foreigners
if (acircuit.lastname.Contains("@"))
{
string[] parts = acircuit.firstname.Split(new[] {'.'});
if (parts.Length == 2)
return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
}
return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " +
acircuit.lastname;
}
else
return acircuit.AgentID.ToString();
}
public virtual bool TeleportAgent(ref GridRegion destination, uint TeleportFlags, int DrawDistance,
AgentCircuitData circuit, AgentData agentData, UUID AgentID,
ulong requestingRegion,
out string reason)
{
IClientCapsService clientCaps =
m_registry.RequestModuleInterface<ICapsService>().GetClientCapsService(AgentID);
IRegionClientCapsService regionCaps = clientCaps.GetCapsService(requestingRegion);
if (regionCaps == null || !regionCaps.RootAgent)
{
reason = "";
ResetFromTransit(AgentID);
return false;
}
bool result = false;
try
{
bool callWasCanceled = false;
ISimulationService SimulationService = m_registry.RequestModuleInterface<ISimulationService>();
if (SimulationService != null)
{
//Set the user in transit so that we block duplicate tps and reset any cancelations
if (!SetUserInTransit(AgentID))
{
reason = "Already in a teleport";
return false;
}
bool useCallbacks = false;
//Note: we have to pull the new grid region info as the one from the region cannot be trusted
GridRegion oldRegion = destination;
IGridService GridService = m_registry.RequestModuleInterface<IGridService>();
if (GridService != null)
{
destination = GridService.GetRegionByUUID(clientCaps.AccountInfo.AllScopeIDs, destination.RegionID);
if (destination == null) //If its not in this grid
destination = oldRegion;
//Inform the client of the neighbor if needed
circuit.child = false; //Force child status to the correct type
circuit.roothandle = destination.RegionHandle;
if (!InformClientOfNeighbor(AgentID, requestingRegion, circuit, ref destination, TeleportFlags,
agentData, out reason, out useCallbacks))
{
ResetFromTransit(AgentID);
return false;
}
}
else
{
reason = "Could not find the grid service";
ResetFromTransit(AgentID);
return false;
}
IEventQueueService EQService = m_registry.RequestModuleInterface<IEventQueueService>();
IRegionClientCapsService otherRegion = clientCaps.GetCapsService(destination.RegionHandle);
EQService.TeleportFinishEvent(destination.RegionHandle, destination.Access,
otherRegion.LoopbackRegionIP,
otherRegion.CircuitData.RegionUDPPort,
otherRegion.CapsUrl,
4, AgentID, TeleportFlags,
destination.RegionSizeX, destination.RegionSizeY,
requestingRegion);
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
// that the client contacted the destination before we send the attachments and close things here.
result = !useCallbacks || WaitForCallback(AgentID, out callWasCanceled);
if (!result)
{
//It says it failed, lets call the sim and check
AgentData data = null;
AgentCircuitData circuitData;
result = SimulationService.RetrieveAgent(destination, AgentID, false, out data, out circuitData);
}
if (!result)
{
if (!callWasCanceled)
{
MainConsole.Instance.Warn("[AgentProcessing]: Callback never came for teleporting agent " +
AgentID + ". Resetting.");
}
//Close the agent at the place we just created if it isn't a neighbor
// 7/22 -- Kill the agent no matter what, it obviously is having issues getting there
//if (IsOutsideView (regionCaps.RegionX, destination.RegionLocX, regionCaps.Region.RegionSizeX, destination.RegionSizeX,
// regionCaps.RegionY, destination.RegionLocY, regionCaps.Region.RegionSizeY, destination.RegionSizeY))
{
SimulationService.CloseAgent(destination, AgentID);
clientCaps.RemoveCAPS(destination.RegionHandle);
}
reason = !callWasCanceled ? "The teleport timed out" : "Cancelled";
}
else
{
//.........这里部分代码省略.........
public virtual LoginAgentArgs LoginAgent(GridRegion region, AgentCircuitData aCircuit)
{
object retVal = base.DoRemoteByHTTP(_capsURL, region, aCircuit);
if (retVal != null || m_doRemoteOnly)
{
if (retVal == null)
{
ReadRemoteCapsPassword();
retVal = base.DoRemoteByHTTP(_capsURL, region, aCircuit);
}
return retVal == null ? null : (LoginAgentArgs)retVal;
}
bool success = false;
string seedCap = "";
string reason = "Could not find the simulation service";
ICapsService capsService = m_registry.RequestModuleInterface<ICapsService>();
ISimulationService SimulationService = m_registry.RequestModuleInterface<ISimulationService>();
if (SimulationService != null)
{
// The client is in the region, we need to make sure it gets the right Caps
// If CreateAgent is successful, it passes back a OSDMap of params that the client
// wants to inform us about, and it includes the Caps SEED url for the region
IRegionClientCapsService regionClientCaps = null;
IClientCapsService clientCaps = null;
if (capsService != null)
{
//Remove any previous users
seedCap = capsService.CreateCAPS(aCircuit.AgentID,
CapsUtil.GetCapsSeedPath(aCircuit.CapsPath),
region.RegionHandle, true, aCircuit, 0);
clientCaps = capsService.GetClientCapsService(aCircuit.AgentID);
regionClientCaps = clientCaps.GetCapsService(region.RegionHandle);
}
ICommunicationService commsService = m_registry.RequestModuleInterface<ICommunicationService>();
if (commsService != null)
commsService.GetUrlsForUser(region, aCircuit.AgentID);
//Make sure that we make userURLs if we need to
int requestedUDPPort = 0;
// As we are creating the agent, we must also initialize the CapsService for the agent
success = CreateAgent(region, regionClientCaps, ref aCircuit, SimulationService, ref requestedUDPPort, out reason);
if (requestedUDPPort == 0)
requestedUDPPort = region.ExternalEndPoint.Port;
aCircuit.RegionUDPPort = requestedUDPPort;
if (!success) // If it failed, do not set up any CapsService for the client
{
if (reason != "")
{
try
{
OSDMap reasonMap = OSDParser.DeserializeJson(reason) as OSDMap;
if (reasonMap != null && reasonMap.ContainsKey("Reason"))
reason = reasonMap["Reason"].AsString();
}
catch
{
//If its already not JSON, it'll throw an exception, catch it
}
}
//Delete the Caps!
IAgentProcessing agentProcessor = m_registry.RequestModuleInterface<IAgentProcessing>();
if (agentProcessor != null && capsService != null)
agentProcessor.LogoutAgent(regionClientCaps, true);
else if (capsService != null)
capsService.RemoveCAPS(aCircuit.AgentID);
return new LoginAgentArgs { Success = success, CircuitData = aCircuit, Reason = reason, SeedCap = seedCap };
}
IPAddress ipAddress = regionClientCaps.Region.ExternalEndPoint.Address;
if (capsService != null && reason != "")
{
try
{
OSDMap responseMap = (OSDMap) OSDParser.DeserializeJson(reason);
OSDMap SimSeedCaps = (OSDMap) responseMap["CapsUrls"];
if (responseMap.ContainsKey("OurIPForClient"))
{
string ip = responseMap["OurIPForClient"].AsString();
if (!IPAddress.TryParse(ip, out ipAddress))
#pragma warning disable 618
ipAddress = Dns.GetHostByName(ip).AddressList[0];
#pragma warning restore 618
}
region.ExternalEndPoint.Address = ipAddress;
//Fix this so that it gets sent to the client that way
regionClientCaps.AddCAPS(SimSeedCaps);
regionClientCaps = clientCaps.GetCapsService(region.RegionHandle);
regionClientCaps.LoopbackRegionIP = ipAddress;
regionClientCaps.CircuitData.RegionUDPPort = requestedUDPPort;
regionClientCaps.RootAgent = true;
}
catch
{
//Delete the Caps!
IAgentProcessing agentProcessor = m_registry.RequestModuleInterface<IAgentProcessing>();
//.........这里部分代码省略.........
public virtual bool CrossAgent(GridRegion crossingRegion, Vector3 pos,
Vector3 velocity, AgentCircuitData circuit, AgentData cAgent, UUID AgentID,
ulong requestingRegion, out string reason)
{
try
{
IClientCapsService clientCaps =
m_registry.RequestModuleInterface<ICapsService>().GetClientCapsService(AgentID);
IRegionClientCapsService requestingRegionCaps = clientCaps.GetCapsService(requestingRegion);
ISimulationService SimulationService = m_registry.RequestModuleInterface<ISimulationService>();
if (SimulationService != null)
{
//Note: we have to pull the new grid region info as the one from the region cannot be trusted
IGridService GridService = m_registry.RequestModuleInterface<IGridService>();
if (GridService != null)
{
//Set the user in transit so that we block duplicate tps and reset any cancelations
if (!SetUserInTransit(AgentID))
{
reason = "Already in a teleport";
return false;
}
bool result = false;
//We need to get it from the grid service again so that we can get the simulation service urls correctly
// as regions don't get that info
crossingRegion = GridService.GetRegionByUUID(clientCaps.AccountInfo.AllScopeIDs, crossingRegion.RegionID);
cAgent.IsCrossing = true;
if (!SimulationService.UpdateAgent(crossingRegion, cAgent))
{
MainConsole.Instance.Warn("[AgentProcessing]: Failed to cross agent " + AgentID +
" because region did not accept it. Resetting.");
reason = "Failed to update an agent";
}
else
{
IEventQueueService EQService = m_registry.RequestModuleInterface<IEventQueueService>();
//Add this for the viewer, but not for the sim, seems to make the viewer happier
int XOffset = crossingRegion.RegionLocX - requestingRegionCaps.RegionX;
pos.X += XOffset;
int YOffset = crossingRegion.RegionLocY - requestingRegionCaps.RegionY;
pos.Y += YOffset;
IRegionClientCapsService otherRegion = clientCaps.GetCapsService(crossingRegion.RegionHandle);
//Tell the client about the transfer
EQService.CrossRegion(crossingRegion.RegionHandle, pos, velocity,
otherRegion.LoopbackRegionIP,
otherRegion.CircuitData.RegionUDPPort,
otherRegion.CapsUrl,
AgentID,
circuit.SessionID,
crossingRegion.RegionSizeX,
crossingRegion.RegionSizeY,
requestingRegion);
result = WaitForCallback(AgentID);
if (!result)
{
MainConsole.Instance.Warn("[AgentProcessing]: Callback never came in crossing agent " + circuit.AgentID +
". Resetting.");
reason = "Crossing timed out";
}
else
{
// Next, let's close the child agent connections that are too far away.
//Fix the root agent status
otherRegion.RootAgent = true;
requestingRegionCaps.RootAgent = false;
CloseNeighborAgents(requestingRegionCaps.Region, crossingRegion, AgentID);
reason = "";
}
}
//All done
ResetFromTransit(AgentID);
return result;
}
else
reason = "Could not find the GridService";
}
else
reason = "Could not find the SimulationService";
}
catch (Exception ex)
{
MainConsole.Instance.WarnFormat("[AgentProcessing]: Failed to cross an agent into a new region. {0}", ex);
}
ResetFromTransit(AgentID);
reason = "Exception occured";
return false;
}
public bool RetrieveAgent(GridRegion destination, UUID id, bool agentIsLeaving, out AgentData agent,
out AgentCircuitData circuitData)
{
agent = null;
circuitData = null;
if (destination == null)
return false;
foreach (IScene s in m_sceneList)
{
if (s.RegionInfo.RegionID == destination.RegionID)
{
//MainConsole.Instance.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
IEntityTransferModule transferModule = s.RequestModuleInterface<IEntityTransferModule>();
if (transferModule != null)
return transferModule.IncomingRetrieveRootAgent(s, id, agentIsLeaving, out agent,
out circuitData);
}
}
return false;
//MainConsole.Instance.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
}
请发表评论