aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs456
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs49
2 files changed, 281 insertions, 224 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index fcc7a85..e85f270 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
183 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); 183 sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
184 sp.Teleport(position); 184 sp.Teleport(position);
185 } 185 }
186 else 186 else // Another region possibly in another simulator
187 { 187 {
188 uint x = 0, y = 0; 188 uint x = 0, y = 0;
189 Utils.LongToUInts(regionHandle, out x, out y); 189 Utils.LongToUInts(regionHandle, out x, out y);
@@ -191,15 +191,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
191 191
192 if (reg != null) 192 if (reg != null)
193 { 193 {
194 m_log.DebugFormat(
195 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation to {0} in {1}",
196 position, reg.RegionName);
197
198 uint newRegionX = (uint)(reg.RegionHandle >> 40);
199 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
200 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
201 uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
202
203 GridRegion finalDestination = GetFinalDestination(reg); 194 GridRegion finalDestination = GetFinalDestination(reg);
204 if (finalDestination == null) 195 if (finalDestination == null)
205 { 196 {
@@ -207,220 +198,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
207 sp.ControllingClient.SendTeleportFailed("Problem at destination"); 198 sp.ControllingClient.SendTeleportFailed("Problem at destination");
208 return; 199 return;
209 } 200 }
210 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}", finalDestination.RegionLocX, finalDestination.RegionLocY, finalDestination.RegionID); 201 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final destination is x={0} y={1} uuid={2}",
211 ulong destinationHandle = finalDestination.RegionHandle; 202 finalDestination.RegionLocX / Constants.RegionSize, finalDestination.RegionLocY / Constants.RegionSize, finalDestination.RegionID);
212 203
213 if (eq == null) 204 //
214 sp.ControllingClient.SendTeleportLocationStart(); 205 // This is it
215 206 //
216 // Let's do DNS resolution only once in this process, please! 207 DoTeleport(sp, reg, finalDestination, position, lookAt, teleportFlags, eq);
217 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, 208 //
218 // it's actually doing a lot of work. 209 //
219 IPEndPoint endPoint = finalDestination.ExternalEndPoint; 210 //
220 if (endPoint.Address == null)
221 {
222 // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
223 destRegionUp = false;
224 }
225
226 if (destRegionUp)
227 {
228 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
229 // both regions
230 if (sp.ParentID != (uint)0)
231 sp.StandUp();
232
233 if (!sp.ValidateAttachments())
234 {
235 sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
236 return;
237 }
238
239 // the avatar.Close below will clear the child region list. We need this below for (possibly)
240 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
241 //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
242 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
243 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
244 // once we reach here...
245 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
246
247 string capsPath = String.Empty;
248
249 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
250 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
251 agentCircuit.startpos = position;
252 agentCircuit.child = true;
253 agentCircuit.Appearance = sp.Appearance;
254 if (currentAgentCircuit != null)
255 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
256
257 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
258 {
259 // brand new agent, let's create a new caps seed
260 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
261 }
262
263 string reason = String.Empty;
264
265 // Let's create an agent there if one doesn't exist yet.
266 if (!CreateAgent(reg, finalDestination, agentCircuit, teleportFlags, out reason))
267 {
268 sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
269 reason));
270 return;
271 }
272
273 // OK, it got this agent. Let's close some child agents
274 sp.CloseChildAgents(newRegionX, newRegionY);
275
276 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
277 {
278 #region IP Translation for NAT
279 IClientIPEndpoint ipepClient;
280 if (sp.ClientView.TryGet(out ipepClient))
281 {
282 capsPath
283 = "http://"
284 + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName)
285 + ":"
286 + finalDestination.HttpPort
287 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
288 }
289 else
290 {
291 capsPath
292 = "http://"
293 + finalDestination.ExternalHostName
294 + ":"
295 + finalDestination.HttpPort
296 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
297 }
298 #endregion
299
300 if (eq != null)
301 {
302 #region IP Translation for NAT
303 // Uses ipepClient above
304 if (sp.ClientView.TryGet(out ipepClient))
305 {
306 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
307 }
308 #endregion
309
310 eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);
311
312 // ES makes the client send a UseCircuitCode message to the destination,
313 // which triggers a bunch of things there.
314 // So let's wait
315 Thread.Sleep(2000);
316
317 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
318
319 }
320 else
321 {
322 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
323 }
324 }
325 else
326 {
327 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
328 capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort
329 + "/CAPS/" + agentCircuit.CapsPath + "0000/";
330 }
331
332 // Expect avatar crossing is a heavy-duty function at the destination.
333 // That is where MakeRoot is called, which fetches appearance and inventory.
334 // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
335 //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
336 // position, false);
337
338 //{
339 // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
340 // // We should close that agent we just created over at destination...
341 // List<ulong> lst = new List<ulong>();
342 // lst.Add(reg.RegionHandle);
343 // SendCloseChildAgentAsync(avatar.UUID, lst);
344 // return;
345 //}
346
347 SetInTransit(sp.UUID);
348
349 // Let's send a full update of the agent. This is a synchronous call.
350 AgentData agent = new AgentData();
351 sp.CopyTo(agent);
352 agent.Position = position;
353 SetCallbackURL(agent, sp.Scene.RegionInfo);
354
355 UpdateAgent(reg, finalDestination, agent);
356
357 m_log.DebugFormat(
358 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID);
359
360
361 if (eq != null)
362 {
363 eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
364 0, teleportFlags, capsPath, sp.UUID);
365 }
366 else
367 {
368 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
369 teleportFlags, capsPath);
370 }
371
372 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
373 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
374 // that the client contacted the destination before we send the attachments and close things here.
375 if (!WaitForCallback(sp.UUID))
376 {
377 // Client never contacted destination. Let's restore everything back
378 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
379
380 ResetFromTransit(sp.UUID);
381
382 // Yikes! We should just have a ref to scene here.
383 //sp.Scene.InformClientOfNeighbours(sp);
384 EnableChildAgents(sp);
385
386 // Finally, kill the agent we just created at the destination.
387 m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID);
388
389 return;
390 }
391
392 KillEntity(sp.Scene, sp.LocalId);
393
394 sp.MakeChildAgent();
395
396 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
397 CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
398
399 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
400
401 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
402 {
403 Thread.Sleep(5000);
404 sp.Close();
405 sp.Scene.IncomingCloseAgent(sp.UUID);
406 }
407 else
408 // now we have a child agent in this region.
409 sp.Reset();
410
411
412 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
413 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
414 {
415 m_log.DebugFormat(
416 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
417 sp.UUID);
418 }
419 }
420 else
421 {
422 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
423 }
424 } 211 }
425 else 212 else
426 { 213 {
@@ -450,6 +237,227 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
450 } 237 }
451 } 238 }
452 239
240 protected void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq)
241 {
242 m_log.DebugFormat(
243 "[ENTITY TRANSFER MODULE]: RequestTeleportToLocation to {0} in {1}",
244 position, reg.RegionName);
245
246 uint newRegionX = (uint)(reg.RegionHandle >> 40);
247 uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
248 uint oldRegionX = (uint)(sp.Scene.RegionInfo.RegionHandle >> 40);
249 uint oldRegionY = (((uint)(sp.Scene.RegionInfo.RegionHandle)) >> 8);
250
251 ulong destinationHandle = finalDestination.RegionHandle;
252
253 if (eq == null)
254 sp.ControllingClient.SendTeleportLocationStart();
255
256 // Let's do DNS resolution only once in this process, please!
257 // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
258 // it's actually doing a lot of work.
259 IPEndPoint endPoint = finalDestination.ExternalEndPoint;
260 if (endPoint.Address != null)
261 {
262 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
263 // both regions
264 if (sp.ParentID != (uint)0)
265 sp.StandUp();
266
267 if (!sp.ValidateAttachments())
268 {
269 sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
270 return;
271 }
272
273 // the avatar.Close below will clear the child region list. We need this below for (possibly)
274 // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
275 //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
276 // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
277 // failure at this point (unlike a border crossing failure). So perhaps this can never fail
278 // once we reach here...
279 //avatar.Scene.RemoveCapsHandler(avatar.UUID);
280
281 string capsPath = String.Empty;
282
283 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
284 AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo();
285 agentCircuit.startpos = position;
286 agentCircuit.child = true;
287 agentCircuit.Appearance = sp.Appearance;
288 if (currentAgentCircuit != null)
289 agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs;
290
291 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
292 {
293 // brand new agent, let's create a new caps seed
294 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
295 }
296
297 string reason = String.Empty;
298
299 // Let's create an agent there if one doesn't exist yet.
300 if (!CreateAgent(reg, finalDestination, agentCircuit, teleportFlags, out reason))
301 {
302 sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",
303 reason));
304 return;
305 }
306
307 // OK, it got this agent. Let's close some child agents
308 sp.CloseChildAgents(newRegionX, newRegionY);
309
310 if (NeedsNewAgent(oldRegionX, newRegionX, oldRegionY, newRegionY))
311 {
312 #region IP Translation for NAT
313 IClientIPEndpoint ipepClient;
314 if (sp.ClientView.TryGet(out ipepClient))
315 {
316 capsPath
317 = "http://"
318 + NetworkUtil.GetHostFor(ipepClient.EndPoint, finalDestination.ExternalHostName)
319 + ":"
320 + finalDestination.HttpPort
321 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
322 }
323 else
324 {
325 capsPath
326 = "http://"
327 + finalDestination.ExternalHostName
328 + ":"
329 + finalDestination.HttpPort
330 + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
331 }
332 #endregion
333
334 if (eq != null)
335 {
336 #region IP Translation for NAT
337 // Uses ipepClient above
338 if (sp.ClientView.TryGet(out ipepClient))
339 {
340 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
341 }
342 #endregion
343
344 eq.EnableSimulator(destinationHandle, endPoint, sp.UUID);
345
346 // ES makes the client send a UseCircuitCode message to the destination,
347 // which triggers a bunch of things there.
348 // So let's wait
349 Thread.Sleep(2000);
350
351 eq.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
352
353 }
354 else
355 {
356 sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
357 }
358 }
359 else
360 {
361 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
362 capsPath = "http://" + finalDestination.ExternalHostName + ":" + finalDestination.HttpPort
363 + "/CAPS/" + agentCircuit.CapsPath + "0000/";
364 }
365
366 // Expect avatar crossing is a heavy-duty function at the destination.
367 // That is where MakeRoot is called, which fetches appearance and inventory.
368 // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
369 //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
370 // position, false);
371
372 //{
373 // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
374 // // We should close that agent we just created over at destination...
375 // List<ulong> lst = new List<ulong>();
376 // lst.Add(reg.RegionHandle);
377 // SendCloseChildAgentAsync(avatar.UUID, lst);
378 // return;
379 //}
380
381 SetInTransit(sp.UUID);
382
383 // Let's send a full update of the agent. This is a synchronous call.
384 AgentData agent = new AgentData();
385 sp.CopyTo(agent);
386 agent.Position = position;
387 SetCallbackURL(agent, sp.Scene.RegionInfo);
388
389 UpdateAgent(reg, finalDestination, agent);
390
391 m_log.DebugFormat(
392 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID);
393
394
395 if (eq != null)
396 {
397 eq.TeleportFinishEvent(destinationHandle, 13, endPoint,
398 0, teleportFlags, capsPath, sp.UUID);
399 }
400 else
401 {
402 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
403 teleportFlags, capsPath);
404 }
405
406 // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
407 // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
408 // that the client contacted the destination before we send the attachments and close things here.
409 if (!WaitForCallback(sp.UUID))
410 {
411 // Client never contacted destination. Let's restore everything back
412 sp.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
413
414 ResetFromTransit(sp.UUID);
415
416 // Yikes! We should just have a ref to scene here.
417 //sp.Scene.InformClientOfNeighbours(sp);
418 EnableChildAgents(sp);
419
420 // Finally, kill the agent we just created at the destination.
421 m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID);
422
423 return;
424 }
425
426 KillEntity(sp.Scene, sp.LocalId);
427
428 sp.MakeChildAgent();
429
430 // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
431 CrossAttachmentsIntoNewRegion(finalDestination, sp, true);
432
433 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
434
435 if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
436 {
437 Thread.Sleep(5000);
438 sp.Close();
439 sp.Scene.IncomingCloseAgent(sp.UUID);
440 }
441 else
442 // now we have a child agent in this region.
443 sp.Reset();
444
445
446 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
447 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
448 {
449 m_log.DebugFormat(
450 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
451 sp.UUID);
452 }
453 }
454 else
455 {
456 sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
457 }
458 }
459
460
453 protected virtual bool CreateAgent(GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason) 461 protected virtual bool CreateAgent(GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason)
454 { 462 {
455 return m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason); 463 return m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 101aea0..0e6323b 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -111,6 +111,55 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
111 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); 111 return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason);
112 } 112 }
113 113
114 public override void TeleportHome(UUID id, IClientAPI client)
115 {
116 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName);
117
118 // Let's find out if this is a foreign user or a local user
119 UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, id);
120 if (account != null)
121 {
122 // local grid user
123 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local");
124 base.TeleportHome(id, client);
125 return;
126 }
127
128 // Foreign user wants to go home
129 //
130 AgentCircuitData aCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
131 if (aCircuit == null || (aCircuit != null && !aCircuit.ServiceURLs.ContainsKey("GatewayURI")))
132 {
133 client.SendTeleportFailed("Your information has been lost");
134 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information");
135 return;
136 }
137
138 GridRegion homeGatekeeper = MakeRegion(aCircuit);
139 if (homeGatekeeper == null)
140 {
141 client.SendTeleportFailed("Your information has been lost");
142 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's gateway information is malformed");
143 return;
144 }
145
146 Vector3 position = Vector3.UnitY, lookAt = Vector3.UnitY;
147 GridRegion finalDestination = m_GatekeeperConnector.GetHomeRegion(homeGatekeeper, aCircuit.AgentID, out position, out lookAt);
148 }
114 #endregion 149 #endregion
150
151 private GridRegion MakeRegion(AgentCircuitData aCircuit)
152 {
153 GridRegion region = new GridRegion();
154
155 Uri uri = null;
156 if (!Uri.TryCreate(aCircuit.ServiceURLs["GatewayURI"].ToString(), UriKind.Absolute, out uri))
157 return null;
158
159 region.ExternalHostName = uri.Host;
160 region.HttpPort = (uint)uri.Port;
161 region.RegionName = string.Empty;
162 return region;
163 }
115 } 164 }
116} 165}