diff --git a/OpenMetaverse.Http/CapsServer.cs b/OpenMetaverse.Http/CapsServer.cs index 26eb21f2..25aa5f0d 100644 --- a/OpenMetaverse.Http/CapsServer.cs +++ b/OpenMetaverse.Http/CapsServer.cs @@ -250,7 +250,6 @@ namespace OpenMetaverse.Http HttpRequestHandler BuildCapsHandler(string path) { HttpRequestSignature signature = new HttpRequestSignature(); - signature.ContentType = "application/xml"; signature.Path = path; return new HttpServer.HttpRequestHandler(signature, CapsCallback); } diff --git a/OpenMetaverse.Http/EventQueueServer.cs b/OpenMetaverse.Http/EventQueueServer.cs index 6e092bb0..5276ef88 100644 --- a/OpenMetaverse.Http/EventQueueServer.cs +++ b/OpenMetaverse.Http/EventQueueServer.cs @@ -68,7 +68,7 @@ namespace OpenMetaverse.Http WebServer server; BlockingQueue eventQueue = new BlockingQueue(); - int currentID = 0; + int currentID = 1; bool running = true; public EventQueueServer(WebServer server) @@ -118,11 +118,11 @@ namespace OpenMetaverse.Http if (request != null && osdRequest.Type == OSDType.Map) { - OSDMap requestMap = (OSDMap)request; + OSDMap requestMap = (OSDMap)osdRequest; int ack = requestMap["ack"].AsInteger(); bool done = requestMap["done"].AsBoolean(); - if (ack != currentID - 1) + if (ack != currentID - 1 && ack != 0) { Logger.Log.WarnFormat("[EventQueue] Received an ack for id {0}, last id sent was {1}", ack, currentID - 1); @@ -229,8 +229,8 @@ namespace OpenMetaverse.Http EventQueueEvent currentEvent = eventsToSend[i]; OSDMap eventMap = new OSDMap(2); - eventMap.Add("body", currentEvent.Body); eventMap.Add("message", OSD.FromString(currentEvent.Name)); + eventMap.Add("body", currentEvent.Body); responseArray.Add(eventMap); } @@ -241,7 +241,7 @@ namespace OpenMetaverse.Http // Serialize the events and send the response byte[] buffer = OSDParser.SerializeLLSDXmlBytes(responseMap); - response.ContentType = "application/xml"; + response.ContentType = "application/llsd+xml"; response.ContentLength = buffer.Length; response.Body.Write(buffer, 0, buffer.Length); response.Body.Flush(); diff --git a/OpenMetaverse.StructuredData/StructuredData.cs b/OpenMetaverse.StructuredData/StructuredData.cs index c0bd34b7..cc890a37 100644 --- a/OpenMetaverse.StructuredData/StructuredData.cs +++ b/OpenMetaverse.StructuredData/StructuredData.cs @@ -673,24 +673,82 @@ namespace OpenMetaverse.StructuredData public OSDBinary(uint value) { - this.value = Utils.UIntToBytes(value); + this.value = new byte[] + { + (byte)((value >> 24) % 256), + (byte)((value >> 16) % 256), + (byte)((value >> 8) % 256), + (byte)(value % 256) + }; } public OSDBinary(long value) { - this.value = Utils.Int64ToBytes(value); + this.value = new byte[] + { + (byte)((value >> 56) % 256), + (byte)((value >> 48) % 256), + (byte)((value >> 40) % 256), + (byte)((value >> 32) % 256), + (byte)((value >> 24) % 256), + (byte)((value >> 16) % 256), + (byte)((value >> 8) % 256), + (byte)(value % 256) + }; } public OSDBinary(ulong value) { - this.value = Utils.UInt64ToBytes(value); + this.value = new byte[] + { + (byte)((value >> 56) % 256), + (byte)((value >> 48) % 256), + (byte)((value >> 40) % 256), + (byte)((value >> 32) % 256), + (byte)((value >> 24) % 256), + (byte)((value >> 16) % 256), + (byte)((value >> 8) % 256), + (byte)(value % 256) + }; } public override string AsString() { return Convert.ToBase64String(value); } public override byte[] AsBinary() { return value; } - public override uint AsUInteger() { return Utils.BytesToUInt(value); } - public override long AsLong() { return Utils.BytesToInt64(value); } - public override ulong AsULong() { return Utils.BytesToUInt64(value); } + + public override uint AsUInteger() + { + return (uint)( + (value[0] << 24) + + (value[1] << 16) + + (value[2] << 8) + + (value[3] << 0)); + } + + public override long AsLong() + { + return (long)( + ((long)value[0] << 56) + + ((long)value[1] << 48) + + ((long)value[2] << 40) + + ((long)value[3] << 32) + + ((long)value[4] << 24) + + ((long)value[5] << 16) + + ((long)value[6] << 8) + + ((long)value[7] << 0)); + } + + public override ulong AsULong() + { + return (ulong)( + ((ulong)value[0] << 56) + + ((ulong)value[1] << 48) + + ((ulong)value[2] << 40) + + ((ulong)value[3] << 32) + + ((ulong)value[4] << 24) + + ((ulong)value[5] << 16) + + ((ulong)value[6] << 8) + + ((ulong)value[7] << 0)); + } public override string ToString() { diff --git a/Programs/Simian/Extensions/LindenLogin.cs b/Programs/Simian/Extensions/LindenLogin.cs index 293e0927..85df6a83 100644 --- a/Programs/Simian/Extensions/LindenLogin.cs +++ b/Programs/Simian/Extensions/LindenLogin.cs @@ -200,6 +200,9 @@ namespace Simian.Extensions IPAddress simIP = addresses.AddressList.Length > 0 ? addresses.AddressList[addresses.AddressList.Length - 1] : IPAddress.Loopback; + agent.CurrentRegionHandle = server.Scene.RegionHandle; + agent.HomeRegionHandle = server.Scene.RegionHandle; + response.AgentID = agent.Avatar.ID; response.SecureSessionID = agent.SecureSessionID; response.SessionID = agent.SessionID; @@ -220,10 +223,8 @@ namespace Simian.Extensions response.Message = "Welcome to Simian"; response.Reason = String.Empty; - uint regionX, regionY; - Utils.LongToUInts(agent.CurrentRegionHandle, out regionX, out regionY); - response.RegionX = regionX; - response.RegionY = regionY; + response.RegionX = server.Scene.RegionX * 256; + response.RegionY = server.Scene.RegionY * 256; response.SecondsSinceEpoch = DateTime.Now; response.SeedCapability = seedCap.ToString(); diff --git a/Programs/Simian/Extensions/MapLocal.cs b/Programs/Simian/Extensions/MapLocal.cs index fa669a7f..a37b6266 100644 --- a/Programs/Simian/Extensions/MapLocal.cs +++ b/Programs/Simian/Extensions/MapLocal.cs @@ -151,7 +151,7 @@ namespace Simian.Extensions else if (request.Info.RegionHandle == Utils.UIntsToLong((server.Scene.RegionX + 1) * 256, server.Scene.RegionY * 256)) { // Special case: adjacent simulator is the HyperGrid portal - HyperGridTeleport(agent, new Uri(/*"http://192.168.1.2:9010/"*/ "http://osl2.nac.uci.edu:9006/"), request.Info.Position); + HyperGridTeleport(agent, new Uri("http://osl2.nac.uci.edu:9006/"), request.Info.Position); } else { @@ -178,33 +178,66 @@ namespace Simian.Extensions { TeleportProgress(agent, "Creating foreign agent", TeleportFlags.ViaLocation); - if (ExpectHyperGridUser(agent, destination, destPos, link)) + // This is a crufty part of the HyperGrid protocol. We need to generate a fragment of a UUID + // (missing the last four digits) and send that as the caps_path variable. Locally, we expand + // that out to http://foreignsim:httpport/CAPS/fragment0000/ and use it as the seed caps path + // that is sent to the client + UUID seedID = UUID.Random(); + string seedCapFragment = seedID.ToString().Substring(0, 32); + Uri seedCap = new Uri(destination, "/CAPS/" + seedCapFragment + "0000/"); + + if (ExpectHyperGridUser(agent, destination, destPos, link, seedCap)) { TeleportProgress(agent, "Establishing foreign agent presence", TeleportFlags.ViaLocation); - // This is a crufty part of the HyperGrid protocol. We need to generate a fragment of a UUID - // (missing the last four digits) and send that as the caps_path variable. Locally, we expand - // that out to http://foreignsim:httpport/CAPS/fragment0000/ and use it as the seed caps path - // that is sent to the client - UUID seedID = UUID.Random(); - string seedCapFragment = seedID.ToString().Substring(0, 32); - Uri seedCap = new Uri(destination, "/CAPS/" + seedCapFragment + "0000/"); - if (CreateChildAgent(agent, destination, destPos, link, seedCapFragment)) { - // Send the final teleport packet to the client - TeleportFinishPacket teleport = new TeleportFinishPacket(); - teleport.Info.AgentID = agent.Avatar.ID; - teleport.Info.LocationID = 0; // Unused by the client - teleport.Info.RegionHandle = link.RegionHandle; - teleport.Info.SeedCapability = Utils.StringToBytes(seedCap.ToString()); - teleport.Info.SimAccess = (byte)SimAccess.Min; - teleport.Info.SimIP = Utils.BytesToUInt(entry.AddressList[0].GetAddressBytes()); - teleport.Info.SimPort = (ushort)link.UDPPort; - teleport.Info.TeleportFlags = (uint)TeleportFlags.ViaLocation; + // Send the final teleport message to the client + if (server.Scene.HasRunningEventQueue(agent)) + { + uint x, y; + Utils.LongToUInts(link.RegionHandle, out x, out y); + x /= 256; + y /= 256; + Logger.Log(String.Format("HyperGrid teleporting to {0} ({1}, {2}) @ {3}", + link.RegionName, x, y, destination), Helpers.LogLevel.Info); + + OSDMap info = new OSDMap(); + info.Add("AgentID", OSD.FromUUID(agent.Avatar.ID)); + info.Add("LocationID", OSD.FromInteger(4)); // Unused by the client + info.Add("RegionHandle", OSD.FromULong(link.RegionHandle)); + info.Add("SeedCapability", OSD.FromUri(seedCap)); + info.Add("SimAccess", OSD.FromInteger((byte)SimAccess.Min)); + info.Add("SimIP", OSD.FromBinary(entry.AddressList[0].GetAddressBytes())); + info.Add("SimPort", OSD.FromInteger(link.UDPPort)); + info.Add("TeleportFlags", OSD.FromUInteger((uint)TeleportFlags.ViaLocation)); + + OSDArray infoArray = new OSDArray(1); + infoArray.Add(info); + + OSDMap teleport = new OSDMap(); + teleport.Add("Info", infoArray); + + server.Scene.SendEvent(agent, "TeleportFinish", teleport); + } + else + { + Logger.Log("No running EventQueue for " + agent.FullName + ", sending TeleportFinish over UDP", + Helpers.LogLevel.Warning); + + TeleportFinishPacket teleport = new TeleportFinishPacket(); + teleport.Info.AgentID = agent.Avatar.ID; + teleport.Info.LocationID = 0; // Unused by the client + teleport.Info.RegionHandle = link.RegionHandle; + teleport.Info.SeedCapability = Utils.StringToBytes(seedCap.ToString()); + teleport.Info.SimAccess = (byte)SimAccess.Min; + teleport.Info.SimIP = Utils.BytesToUInt(entry.AddressList[0].GetAddressBytes()); + teleport.Info.SimPort = (ushort)link.UDPPort; + teleport.Info.TeleportFlags = (uint)TeleportFlags.ViaLocation; + + server.UDP.SendPacket(agent.Avatar.ID, teleport, PacketCategory.Transaction); + } - server.UDP.SendPacket(agent.Avatar.ID, teleport, PacketCategory.Transaction); - // Remove the agent from the local scene (will also tear down the UDP connection) //server.Scene.ObjectRemove(this, agent.Avatar.ID); @@ -342,7 +375,7 @@ namespace Simian.Extensions return false; } - bool ExpectHyperGridUser(Agent agent, Uri destination, Vector3 destPos, HyperGridLink link) + bool ExpectHyperGridUser(Agent agent, Uri destination, Vector3 destPos, HyperGridLink link, Uri seedCap) { try { @@ -373,7 +406,7 @@ namespace Simian.Extensions WriteStringMember(writer, "startpos_x", destPos.X.ToString(Utils.EnUsCulture)); WriteStringMember(writer, "startpos_y", destPos.Y.ToString(Utils.EnUsCulture)); WriteStringMember(writer, "startpos_z", destPos.Z.ToString(Utils.EnUsCulture)); - WriteStringMember(writer, "caps_path", String.Empty); + WriteStringMember(writer, "caps_path", seedCap.ToString()); WriteStringMember(writer, "region_uuid", link.RegionID.ToString()); //WriteStringMember(writer, "userserver_id", ""); @@ -382,7 +415,7 @@ namespace Simian.Extensions WriteStringMember(writer, "root_folder_id", agent.InventoryRoot.ToString()); WriteStringMember(writer, "internal_port", server.HttpPort.ToString()); - WriteStringMember(writer, "regionhandle", link.RegionHandle.ToString()); + WriteStringMember(writer, "regionhandle", server.Scene.RegionHandle.ToString()); WriteStringMember(writer, "home_address", IPAddress.Loopback.ToString()); WriteStringMember(writer, "home_port", server.HttpPort.ToString()); WriteStringMember(writer, "home_remoting", server.HttpPort.ToString()); diff --git a/Programs/Simian/Extensions/SceneManager.cs b/Programs/Simian/Extensions/SceneManager.cs index 5ee7cf6c..c6009685 100644 --- a/Programs/Simian/Extensions/SceneManager.cs +++ b/Programs/Simian/Extensions/SceneManager.cs @@ -50,8 +50,8 @@ namespace Simian.Extensions public event AgentAppearanceCallback OnAgentAppearance; public event TerrainUpdateCallback OnTerrainUpdate; - public uint RegionX { get { return 1000; } } - public uint RegionY { get { return 1000; } } + public uint RegionX { get { return 7777; } } + public uint RegionY { get { return 7777; } } public ulong RegionHandle { get { return regionHandle; } } public UUID RegionID { get { return regionID; } } public string RegionName { get { return "Simian"; } } @@ -517,6 +517,11 @@ namespace Simian.Extensions return eventQueues.Remove(agentID); } + public bool HasRunningEventQueue(Agent agent) + { + return eventQueues.ContainsKey(agent.Avatar.ID); + } + public void SendEvent(Agent agent, string name, OSDMap body) { EventQueueServerCap eventQueue; diff --git a/Programs/Simian/Interfaces/ISceneProvider.cs b/Programs/Simian/Interfaces/ISceneProvider.cs index 23a6bb8b..d937acaf 100644 --- a/Programs/Simian/Interfaces/ISceneProvider.cs +++ b/Programs/Simian/Interfaces/ISceneProvider.cs @@ -80,6 +80,7 @@ namespace Simian void ForEachAgent(Action action); void SendEvent(Agent agent, string name, OSDMap body); + bool HasRunningEventQueue(Agent agent); bool SeedCapabilityHandler(IHttpClientContext context, IHttpRequest request, IHttpResponse response, object state); } }