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