* 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:
John Hurliman
2009-02-05 03:12:41 +00:00
parent 808b681b83
commit 06404ab4e4
7 changed files with 140 additions and 43 deletions

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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()
{

View File

@@ -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();

View File

@@ -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());

View File

@@ -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;

View File

@@ -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);
}
}