398 lines
15 KiB
C#
398 lines
15 KiB
C#
/*
|
|
* Copyright (c) Contributors, http://opensimulator.org/
|
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of the OpenSimulator Project nor the
|
|
* names of its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Collections.Generic;
|
|
using log4net;
|
|
using OpenMetaverse;
|
|
using OpenMetaverse.StructuredData;
|
|
|
|
namespace OpenSim.Framework
|
|
{
|
|
/// <summary>
|
|
/// Circuit data for an agent. Connection information shared between
|
|
/// regions that accept UDP connections from a client
|
|
/// </summary>
|
|
public class AgentCircuitData
|
|
{
|
|
// DEBUG ON
|
|
private static readonly ILog m_log =
|
|
LogManager.GetLogger(
|
|
MethodBase.GetCurrentMethod().DeclaringType);
|
|
// DEBUG OFF
|
|
|
|
/// <summary>
|
|
/// Avatar Unique Agent Identifier
|
|
/// </summary>
|
|
public UUID AgentID;
|
|
|
|
/// <summary>
|
|
/// Avatar's Appearance
|
|
/// </summary>
|
|
public AvatarAppearance Appearance;
|
|
|
|
/// <summary>
|
|
/// Agent's root inventory folder
|
|
/// </summary>
|
|
public UUID BaseFolder;
|
|
|
|
/// <summary>
|
|
/// Base Caps path for user
|
|
/// </summary>
|
|
public string CapsPath = String.Empty;
|
|
|
|
/// <summary>
|
|
/// Seed caps for neighbor regions that the user can see into
|
|
/// </summary>
|
|
public Dictionary<ulong, string> ChildrenCapSeeds;
|
|
|
|
/// <summary>
|
|
/// Root agent, or Child agent
|
|
/// </summary>
|
|
public bool child;
|
|
|
|
/// <summary>
|
|
/// Number given to the client when they log-in that they provide
|
|
/// as credentials to the UDP server
|
|
/// </summary>
|
|
public uint circuitcode;
|
|
|
|
/// <summary>
|
|
/// How this agent got here
|
|
/// </summary>
|
|
public uint teleportFlags;
|
|
|
|
/// <summary>
|
|
/// Agent's account first name
|
|
/// </summary>
|
|
public string firstname;
|
|
public UUID InventoryFolder;
|
|
|
|
/// <summary>
|
|
/// Agent's account last name
|
|
/// </summary>
|
|
public string lastname;
|
|
|
|
/// <summary>
|
|
/// Agent's full name.
|
|
/// </summary>
|
|
public string Name { get { return string.Format("{0} {1}", firstname, lastname); } }
|
|
|
|
/// <summary>
|
|
/// Random Unique GUID for this session. Client gets this at login and it's
|
|
/// only supposed to be disclosed over secure channels
|
|
/// </summary>
|
|
public UUID SecureSessionID;
|
|
|
|
/// <summary>
|
|
/// Non secure Session ID
|
|
/// </summary>
|
|
public UUID SessionID;
|
|
|
|
/// <summary>
|
|
/// Hypergrid service token; generated by the user domain, consumed by the receiving grid.
|
|
/// There is one such unique token for each grid visited.
|
|
/// </summary>
|
|
public string ServiceSessionID = string.Empty;
|
|
|
|
/// <summary>
|
|
/// The client's IP address, as captured by the login service
|
|
/// </summary>
|
|
public string IPAddress;
|
|
|
|
/// <summary>
|
|
/// Viewer's version string as reported by the viewer at login
|
|
/// </summary>
|
|
private string m_viewerInternal;
|
|
|
|
/// <summary>
|
|
/// Viewer's version string
|
|
/// </summary>
|
|
public string Viewer
|
|
{
|
|
set { m_viewerInternal = value; }
|
|
|
|
// Try to return consistent viewer string taking into account
|
|
// that viewers have chaagned how version is reported
|
|
// See http://opensimulator.org/mantis/view.php?id=6851
|
|
get
|
|
{
|
|
// Old style version string contains viewer name followed by a space followed by a version number
|
|
if (m_viewerInternal == null || m_viewerInternal.Contains(" "))
|
|
{
|
|
return m_viewerInternal;
|
|
}
|
|
else // New style version contains no spaces, just version number
|
|
{
|
|
return Channel + " " + m_viewerInternal;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The channel strinf sent by the viewer at login
|
|
/// </summary>
|
|
public string Channel;
|
|
|
|
/// <summary>
|
|
/// The Mac address as reported by the viewer at login
|
|
/// </summary>
|
|
public string Mac;
|
|
|
|
/// <summary>
|
|
/// The id0 as reported by the viewer at login
|
|
/// </summary>
|
|
public string Id0;
|
|
|
|
/// <summary>
|
|
/// Position the Agent's Avatar starts in the region
|
|
/// </summary>
|
|
public Vector3 startpos;
|
|
public float startfar = -1.0f;
|
|
|
|
public Dictionary<string, object> ServiceURLs;
|
|
|
|
public AgentCircuitData()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pack AgentCircuitData into an OSDMap for transmission over LLSD XML or LLSD json
|
|
/// </summary>
|
|
/// <returns>map of the agent circuit data</returns>
|
|
public OSDMap PackAgentCircuitData(EntityTransferContext ctx)
|
|
{
|
|
OSDMap args = new OSDMap();
|
|
args["agent_id"] = OSD.FromUUID(AgentID);
|
|
args["base_folder"] = OSD.FromUUID(BaseFolder);
|
|
args["caps_path"] = OSD.FromString(CapsPath);
|
|
|
|
if (ChildrenCapSeeds != null)
|
|
{
|
|
OSDArray childrenSeeds = new OSDArray(ChildrenCapSeeds.Count);
|
|
foreach (KeyValuePair<ulong, string> kvp in ChildrenCapSeeds)
|
|
{
|
|
OSDMap pair = new OSDMap();
|
|
pair["handle"] = OSD.FromString(kvp.Key.ToString());
|
|
pair["seed"] = OSD.FromString(kvp.Value);
|
|
childrenSeeds.Add(pair);
|
|
}
|
|
if (ChildrenCapSeeds.Count > 0)
|
|
args["children_seeds"] = childrenSeeds;
|
|
}
|
|
args["child"] = OSD.FromBoolean(child);
|
|
args["circuit_code"] = OSD.FromString(circuitcode.ToString());
|
|
args["first_name"] = OSD.FromString(firstname);
|
|
args["last_name"] = OSD.FromString(lastname);
|
|
args["inventory_folder"] = OSD.FromUUID(InventoryFolder);
|
|
args["secure_session_id"] = OSD.FromUUID(SecureSessionID);
|
|
args["session_id"] = OSD.FromUUID(SessionID);
|
|
|
|
args["service_session_id"] = OSD.FromString(ServiceSessionID);
|
|
args["start_pos"] = OSD.FromString(startpos.ToString());
|
|
args["client_ip"] = OSD.FromString(IPAddress);
|
|
args["viewer"] = OSD.FromString(Viewer);
|
|
args["channel"] = OSD.FromString(Channel);
|
|
args["mac"] = OSD.FromString(Mac);
|
|
args["id0"] = OSD.FromString(Id0);
|
|
if(startfar > 0)
|
|
args["far"] = OSD.FromReal(startfar);
|
|
|
|
if (Appearance != null)
|
|
{
|
|
args["appearance_serial"] = OSD.FromInteger(Appearance.Serial);
|
|
|
|
OSDMap appmap = Appearance.Pack(ctx);
|
|
args["packed_appearance"] = appmap;
|
|
}
|
|
|
|
// Old, bad way. Keeping it fow now for backwards compatibility
|
|
// OBSOLETE -- soon to be deleted
|
|
if (ServiceURLs != null && ServiceURLs.Count > 0)
|
|
{
|
|
OSDArray urls = new OSDArray(ServiceURLs.Count * 2);
|
|
foreach (KeyValuePair<string, object> kvp in ServiceURLs)
|
|
{
|
|
//System.Console.WriteLine("XXX " + kvp.Key + "=" + kvp.Value);
|
|
urls.Add(OSD.FromString(kvp.Key));
|
|
urls.Add(OSD.FromString((kvp.Value == null) ? string.Empty : kvp.Value.ToString()));
|
|
}
|
|
args["service_urls"] = urls;
|
|
}
|
|
|
|
// again, this time the right way
|
|
if (ServiceURLs != null && ServiceURLs.Count > 0)
|
|
{
|
|
OSDMap urls = new OSDMap();
|
|
foreach (KeyValuePair<string, object> kvp in ServiceURLs)
|
|
{
|
|
//System.Console.WriteLine("XXX " + kvp.Key + "=" + kvp.Value);
|
|
urls[kvp.Key] = OSD.FromString((kvp.Value == null) ? string.Empty : kvp.Value.ToString());
|
|
}
|
|
args["serviceurls"] = urls;
|
|
}
|
|
|
|
|
|
return args;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unpack agent circuit data map into an AgentCiruitData object
|
|
/// </summary>
|
|
/// <param name="args"></param>
|
|
public void UnpackAgentCircuitData(OSDMap args)
|
|
{
|
|
OSD tmpOSD;
|
|
if (args.TryGetValue("agent_id", out tmpOSD))
|
|
AgentID = tmpOSD.AsUUID();
|
|
if (args.TryGetValue("base_folder", out tmpOSD))
|
|
BaseFolder =tmpOSD.AsUUID();
|
|
if (args.TryGetValue("caps_path", out tmpOSD))
|
|
CapsPath = tmpOSD.AsString();
|
|
|
|
if ((args.TryGetValue("children_seeds", out tmpOSD) && tmpOSD is OSDArray))
|
|
{
|
|
OSDArray childrenSeeds = (OSDArray)tmpOSD;
|
|
ChildrenCapSeeds = new Dictionary<ulong, string>();
|
|
foreach (OSD o in childrenSeeds)
|
|
{
|
|
if (o.Type == OSDType.Map)
|
|
{
|
|
ulong handle = 0;
|
|
string seed = "";
|
|
OSDMap pair = (OSDMap)o;
|
|
if (pair.TryGetValue("handle", out tmpOSD))
|
|
{
|
|
if (!UInt64.TryParse(tmpOSD.AsString(), out handle))
|
|
continue;
|
|
}
|
|
if (!ChildrenCapSeeds.ContainsKey(handle))
|
|
{
|
|
if (pair.TryGetValue("seed", out tmpOSD))
|
|
{
|
|
seed = tmpOSD.AsString();
|
|
ChildrenCapSeeds.Add(handle, seed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
ChildrenCapSeeds = new Dictionary<ulong, string>();
|
|
|
|
if (args.TryGetValue("child", out tmpOSD))
|
|
child = tmpOSD.AsBoolean();
|
|
if (args.TryGetValue("circuit_code", out tmpOSD))
|
|
UInt32.TryParse(tmpOSD.AsString(), out circuitcode);
|
|
if (args.TryGetValue("first_name", out tmpOSD))
|
|
firstname = tmpOSD.AsString();
|
|
if (args.TryGetValue("last_name", out tmpOSD))
|
|
lastname = tmpOSD.AsString();
|
|
if (args.TryGetValue("inventory_folder", out tmpOSD))
|
|
InventoryFolder = tmpOSD.AsUUID();
|
|
if (args.TryGetValue("secure_session_id", out tmpOSD))
|
|
SecureSessionID = tmpOSD.AsUUID();
|
|
if (args.TryGetValue("session_id", out tmpOSD))
|
|
SessionID = tmpOSD.AsUUID();
|
|
if (args.TryGetValue("service_session_id", out tmpOSD))
|
|
ServiceSessionID = tmpOSD.AsString();
|
|
if (args.TryGetValue("client_ip", out tmpOSD))
|
|
IPAddress = tmpOSD.AsString();
|
|
if (args.TryGetValue("viewer", out tmpOSD))
|
|
Viewer = tmpOSD.AsString();
|
|
if (args.TryGetValue("channel", out tmpOSD))
|
|
Channel = tmpOSD.AsString();
|
|
if (args.TryGetValue("mac", out tmpOSD))
|
|
Mac = tmpOSD.AsString();
|
|
if (args.TryGetValue("id0", out tmpOSD))
|
|
Id0 = tmpOSD.AsString();
|
|
if (args.TryGetValue("teleport_flags", out tmpOSD))
|
|
teleportFlags = tmpOSD.AsUInteger();
|
|
|
|
if (args.TryGetValue("start_pos", out tmpOSD))
|
|
Vector3.TryParse(tmpOSD.AsString(), out startpos);
|
|
|
|
if(args.TryGetValue("far", out tmpOSD))
|
|
startfar = (float)tmpOSD.AsReal();
|
|
|
|
//m_log.InfoFormat("[AGENTCIRCUITDATA]: agentid={0}, child={1}, startpos={2}", AgentID, child, startpos);
|
|
|
|
try
|
|
{
|
|
// Unpack various appearance elements
|
|
Appearance = new AvatarAppearance();
|
|
|
|
// Eventually this code should be deprecated, use full appearance
|
|
// packing in packed_appearance
|
|
if (args.TryGetValue("appearance_serial", out tmpOSD))
|
|
Appearance.Serial = tmpOSD.AsInteger();
|
|
|
|
if (args.TryGetValue("packed_appearance", out tmpOSD) && (tmpOSD is OSDMap))
|
|
{
|
|
Appearance.Unpack((OSDMap)tmpOSD);
|
|
// m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance");
|
|
}
|
|
else
|
|
{
|
|
m_log.Warn("[AGENTCIRCUITDATA]: failed to find a valid packed_appearance");
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message);
|
|
}
|
|
|
|
ServiceURLs = new Dictionary<string, object>();
|
|
// Try parse the new way, OSDMap
|
|
if (args.TryGetValue("serviceurls", out tmpOSD) && (tmpOSD is OSDMap))
|
|
{
|
|
OSDMap urls = (OSDMap)tmpOSD;
|
|
foreach (KeyValuePair<String, OSD> kvp in urls)
|
|
{
|
|
ServiceURLs[kvp.Key] = kvp.Value;
|
|
//System.Console.WriteLine("XXX " + kvp.Key + "=" + ServiceURLs[kvp.Key]);
|
|
}
|
|
}
|
|
// else try the old way, OSDArray
|
|
// OBSOLETE -- soon to be deleted
|
|
else if (args.TryGetValue("service_urls", out tmpOSD) && (tmpOSD is OSDArray))
|
|
{
|
|
OSDArray urls = (OSDArray)tmpOSD;
|
|
OSD tmpOSDb;
|
|
for (int i = 0; i < urls.Count - 1; i += 2)
|
|
{
|
|
tmpOSD = urls[i];
|
|
tmpOSDb = urls[i + 1];
|
|
ServiceURLs[tmpOSD.AsString()] = tmpOSDb.AsString();
|
|
//System.Console.WriteLine("XXX " + urls[i * 2].AsString() + "=" + urls[(i * 2) + 1].AsString());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|