* Fixed endianness for OSD handling of uint, long, and ulong (big endian byte arrays are used)
* Fixed CapsServer to handle all content types (old SL clients were sending application/xml, new ones send application/llsd+xml) * Start the EventQueue ID at 1 (seems to help) * HyperGrid teleporting is now working in Simian git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@2428 52acb1d6-8a22-11de-b505-999d5b087335
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace OpenMetaverse.Http
|
||||
|
||||
WebServer server;
|
||||
BlockingQueue<EventQueueEvent> eventQueue = new BlockingQueue<EventQueueEvent>();
|
||||
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();
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace Simian
|
||||
void ForEachAgent(Action<Agent> action);
|
||||
|
||||
void SendEvent(Agent agent, string name, OSDMap body);
|
||||
bool HasRunningEventQueue(Agent agent);
|
||||
bool SeedCapabilityHandler(IHttpClientContext context, IHttpRequest request, IHttpResponse response, object state);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user