diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index a3413a1c53..8e49fad4fc 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -35,7 +35,7 @@ Patches
* BigFootAg
* CharlieO
-* jhurliman (LLSD Login)
+* jhurliman
* kinoc (Daxtron Labs)
* dmiles (Daxtron Labs)
* daTwitch
diff --git a/OpenSim/Framework/AgentCircuitManager.cs b/OpenSim/Framework/AgentCircuitManager.cs
index 426e8e2ae1..80e2f87afd 100644
--- a/OpenSim/Framework/AgentCircuitManager.cs
+++ b/OpenSim/Framework/AgentCircuitManager.cs
@@ -103,10 +103,41 @@ namespace OpenSim.Framework
AgentCircuits[(uint) agentData.circuitcode].firstname = agentData.firstname;
AgentCircuits[(uint) agentData.circuitcode].lastname = agentData.lastname;
AgentCircuits[(uint) agentData.circuitcode].startpos = agentData.startpos;
+
+ // Updated for when we don't know them before calling Scene.NewUserConnection
+ AgentCircuits[(uint) agentData.circuitcode].SecureSessionID = agentData.SecureSessionID;
+ AgentCircuits[(uint) agentData.circuitcode].SessionID = agentData.SessionID;
+
// Console.WriteLine("update user start pos is " + agentData.startpos.X + " , " + agentData.startpos.Y + " , " + agentData.startpos.Z);
}
}
+
+ ///
+ /// Sometimes the circuitcode may not be known before setting up the connection
+ ///
+ ///
+ ///
+
+ public bool TryChangeCiruitCode(uint circuitcode, uint newcircuitcode)
+ {
+ lock (AgentCircuits)
+ {
+ if (AgentCircuits.ContainsKey((uint)circuitcode) && !AgentCircuits.ContainsKey((uint)newcircuitcode))
+ {
+ AgentCircuitData agentData = AgentCircuits[(uint)circuitcode];
+
+ agentData.circuitcode = newcircuitcode;
+
+ AgentCircuits.Remove((uint)circuitcode);
+ AgentCircuits.Add(newcircuitcode, agentData);
+ return true;
+ }
+ }
+ return false;
+
+ }
+
public void UpdateAgentChildStatus(uint circuitcode, bool childstatus)
{
if (AgentCircuits.ContainsKey(circuitcode))
diff --git a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs
index 4e3840b597..3b02c888b9 100644
--- a/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs
+++ b/OpenSim/Framework/Communications/Cache/UserProfileCacheService.cs
@@ -159,6 +159,31 @@ namespace OpenSim.Framework.Communications.Cache
}
}
+ ///
+ /// Preloads User data into the region cache. Modules may use this service to add non-standard clients
+ ///
+ ///
+ ///
+ public void PreloadUserCache(LLUUID userID, UserProfileData userData)
+ {
+ if (userID == LLUUID.Zero)
+ return;
+
+ lock (m_userProfiles)
+ {
+ if (m_userProfiles.ContainsKey(userID))
+ {
+ return;
+ }
+ else
+ {
+
+ CachedUserInfo userInfo = new CachedUserInfo(m_commsManager, userData);
+ m_userProfiles.Add(userID, userInfo);
+ }
+ }
+ }
+
///
/// Handle an inventory folder creation request from the client.
///
diff --git a/OpenSim/Framework/Communications/Capabilities/LLSDMethodString.cs b/OpenSim/Framework/Communications/Capabilities/LLSDMethodString.cs
new file mode 100644
index 0000000000..31325d802c
--- /dev/null
+++ b/OpenSim/Framework/Communications/Capabilities/LLSDMethodString.cs
@@ -0,0 +1,31 @@
+/*
+ * 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 OpenSim 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.
+ */
+
+namespace OpenSim.Framework.Communications.Capabilities
+{
+ public delegate TResponse LLSDMethodString(TRequest request, string path);
+}
diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs
index fd02382896..a35ed725a2 100644
--- a/OpenSim/Framework/Communications/UserManagerBase.cs
+++ b/OpenSim/Framework/Communications/UserManagerBase.cs
@@ -339,6 +339,11 @@ namespace OpenSim.Framework.Communications
public void ClearUserAgent(LLUUID agentID)
{
UserProfileData profile = GetUserProfile(agentID);
+
+ if (profile == null)
+ {
+ return;
+ }
profile.CurrentAgent = null;
UpdateUserProfile(profile);
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index b2d13c7874..f43790252d 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -349,6 +349,11 @@ namespace OpenSim.Framework
set;
}
+ bool SendLogoutPacketWhenClosing
+ {
+ set;
+ }
+
// [Obsolete("LLClientView Specific - Circuits are unique to LLClientView")]
uint CircuitCode { get; }
// [Obsolete("LLClientView Specific - Replace with more bare-bones arguments.")]
@@ -741,5 +746,6 @@ namespace OpenSim.Framework
void SendRegionHandle(LLUUID regoinID, ulong handle);
void SendParcelInfo(RegionInfo info, LandData land, LLUUID parcelID, uint x, uint y);
+ void KillEndDone();
}
}
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs
index 23c28e6328..7b2b599be6 100644
--- a/OpenSim/Framework/Servers/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/BaseHttpServer.cs
@@ -47,8 +47,9 @@ namespace OpenSim.Framework.Servers
protected Thread m_workerThread;
protected HttpListener m_httpListener;
- protected Dictionary m_rpcHandlers = new Dictionary();
- protected LLSDMethod m_llsdHandler = null;
+ protected Dictionary m_rpcHandlers = new Dictionary();
+ protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/
+ protected Dictionary m_llsdHandlers = new Dictionary();
protected Dictionary m_streamHandlers = new Dictionary();
protected Dictionary m_HTTPHandlers = new Dictionary();
protected Dictionary m_agentHandlers = new Dictionary();
@@ -148,9 +149,28 @@ namespace OpenSim.Framework.Servers
return false;
}
- public bool SetLLSDHandler(LLSDMethod handler)
+ ///
+ /// Adds a LLSD handler, yay.
+ ///
+ /// /resource/ path
+ /// handle the LLSD response
+ ///
+ public bool AddLLSDHandler(string path, LLSDMethod handler)
{
- m_llsdHandler = handler;
+ lock (m_llsdHandlers)
+ {
+ if (!m_llsdHandlers.ContainsKey(path))
+ {
+ m_llsdHandlers.Add(path, handler);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public bool SetDefaultLLSDHandler(DefaultLLSDMethod handler)
+ {
+ m_defaultLlsdHandler = handler;
return true;
}
@@ -239,20 +259,21 @@ namespace OpenSim.Framework.Servers
switch (request.ContentType)
{
- case null:
- case "text/html":
- HandleHTTPRequest(request, response);
- return;
+ case null:
+ case "text/html":
+ HandleHTTPRequest(request, response);
+ return;
- case "application/xml+llsd":
- HandleLLSDRequests(request, response);
- return;
+ case "application/llsd+xml":
+ case "application/xml+llsd":
+ HandleLLSDRequests(request, response);
+ return;
- case "text/xml":
- case "application/xml":
- default:
- HandleXmlRpcRequests(request, response);
- return;
+ case "text/xml":
+ case "application/xml":
+ default:
+ HandleXmlRpcRequests(request, response);
+ return;
}
}
catch (SocketException e)
@@ -456,17 +477,37 @@ namespace OpenSim.Framework.Servers
m_log.Warn("[HTTPD]: Error - " + ex.Message);
}
- if (llsdRequest != null && m_llsdHandler != null)
+ if (llsdRequest != null)// && m_defaultLlsdHandler != null)
{
- llsdResponse = m_llsdHandler(llsdRequest);
+
+ LLSDMethod llsdhandler = null;
+
+ if (TryGetLLSDHandler(request.RawUrl, out llsdhandler))
+ {
+ // we found a registered llsd handler to service this request
+ llsdResponse = llsdhandler(request.RawUrl, llsdRequest, request.RemoteIPEndPoint.ToString());
+ }
+ else
+ {
+ // we didn't find a registered llsd handler to service this request
+ // check if we have a default llsd handler
+
+ if (m_defaultLlsdHandler != null)
+ {
+ // LibOMV path
+ llsdResponse = m_defaultLlsdHandler(llsdRequest);
+ }
+ else
+ {
+ // Oops, no handler for this.. give em the failed message
+ llsdResponse = GenerateNoLLSDHandlerResponse();
+ }
+ }
+
}
else
{
- LLSDMap map = new LLSDMap();
- map["reason"] = LLSD.FromString("LLSDRequest");
- map["message"] = LLSD.FromString("No handler registered for LLSD Requests");
- map["login"] = LLSD.FromString("false");
- llsdResponse = map;
+ llsdResponse = GenerateNoLLSDHandlerResponse();
}
response.ContentType = "application/xml+llsd";
@@ -491,6 +532,68 @@ namespace OpenSim.Framework.Servers
}
}
+ private bool TryGetLLSDHandler(string path, out LLSDMethod llsdHandler)
+ {
+ llsdHandler = null;
+ // Pull out the first part of the path
+ // splitting the path by '/' means we'll get the following return..
+ // {0}/{1}/{2}
+ // where {0} isn't something we really control 100%
+
+ string[] pathbase = path.Split('/');
+ string searchquery = "/";
+
+ if (pathbase.Length < 1)
+ return false;
+
+ for (int i=1; i bestMatch.Length)
+ {
+ bestMatch = pattern;
+ }
+ }
+ }
+
+ if (String.IsNullOrEmpty(bestMatch))
+ {
+ llsdHandler = null;
+ return false;
+ }
+ else
+ {
+ llsdHandler = m_llsdHandlers[bestMatch];
+ return true;
+ }
+ }
+
+ private LLSDMap GenerateNoLLSDHandlerResponse()
+ {
+ LLSDMap map = new LLSDMap();
+ map["reason"] = LLSD.FromString("LLSDRequest");
+ map["message"] = LLSD.FromString("No handler registered for LLSD Requests");
+ map["login"] = LLSD.FromString("false");
+ return map;
+ }
///
/// A specific agent handler was provided. Such a handler is expecetd to have an
/// intimate, and highly specific relationship with the client. Consequently,
@@ -809,6 +912,25 @@ namespace OpenSim.Framework.Servers
return false;
}
+ public bool RemoveLLSDHandler(string path, LLSDMethod handler)
+ {
+
+ try
+ {
+ if (handler == m_llsdHandlers[path])
+ {
+ m_llsdHandlers.Remove(path);
+ return true;
+ }
+ }
+ catch (KeyNotFoundException)
+ {
+ // This is an exception to prevent crashing because of invalid code
+ }
+
+ return false;
+ }
+
public string GetHTTP404(string host)
{
diff --git a/OpenSim/Framework/Servers/LLSDMethod.cs b/OpenSim/Framework/Servers/LLSDMethod.cs
index 05c23b0530..7bb946efd4 100644
--- a/OpenSim/Framework/Servers/LLSDMethod.cs
+++ b/OpenSim/Framework/Servers/LLSDMethod.cs
@@ -29,5 +29,6 @@ using libsecondlife.StructuredData;
namespace OpenSim.Framework.Servers
{
- public delegate LLSD LLSDMethod(LLSD request);
+ public delegate LLSD LLSDMethod( string path, LLSD request, string endpoint );
+ public delegate LLSD DefaultLLSDMethod(LLSD request);
}
diff --git a/OpenSim/Framework/Servers/LLSDMethodString.cs b/OpenSim/Framework/Servers/LLSDMethodString.cs
new file mode 100644
index 0000000000..8d20b6991b
--- /dev/null
+++ b/OpenSim/Framework/Servers/LLSDMethodString.cs
@@ -0,0 +1,33 @@
+/*
+ * 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 OpenSim 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 libsecondlife.StructuredData;
+
+namespace OpenSim.Framework.Servers
+{
+ public delegate LLSD LLSDMethodString(LLSD request, string thePath);
+}
diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs
index 9a3e4318c4..20d0cbf445 100644
--- a/OpenSim/Grid/UserServer/Main.cs
+++ b/OpenSim/Grid/UserServer/Main.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Grid.UserServer
if (Cfg.EnableLLSDLogin)
{
- m_httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod);
+ m_httpServer.SetDefaultLLSDHandler(m_loginService.LLSDLoginMethod);
}
m_httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName);
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 0dd037d0be..78064dafad 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -384,7 +384,7 @@ namespace OpenSim
m_httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin);
// Provides the LLSD login
- m_httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod);
+ m_httpServer.SetDefaultLLSDHandler(m_loginService.LLSDLoginMethod);
// provide grid info
// m_gridInfoService = new GridInfoService(m_config.Source.Configs["Startup"].GetString("inifile", Path.Combine(Util.configDir(), "OpenSim.ini")));
diff --git a/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs
new file mode 100644
index 0000000000..dfdabc8e5b
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using libsecondlife.Packets;
+
+namespace OpenSim.Region.ClientStack.LindenUDP
+{
+ class KillPacket : Packet
+ {
+ private Header header;
+ public override void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
+ {
+
+ }
+
+ public override void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer)
+ {
+
+ }
+
+ public override Header Header { get { return header; } set { header = value; }}
+
+ public override byte[] ToBytes()
+ {
+ return new byte[0];
+ }
+ public KillPacket()
+ {
+ Header = new LowHeader();
+ Header.ID = 65531;
+ Header.Reliable = true;
+ }
+
+ public override PacketType Type
+ {
+ get
+ {
+ return PacketType.UseCircuitCode;
+ }
+ }
+ }
+}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 7c531f3efb..8214045833 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -92,6 +92,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
private Dictionary m_defaultAnimations = new Dictionary();
+ private bool m_SendLogoutPacketWhenClosing = true;
+
/* protected variables */
protected static Dictionary PacketHandlers =
@@ -368,6 +370,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
set { m_IsActive = value; }
}
+ public bool SendLogoutPacketWhenClosing
+ {
+ set { m_SendLogoutPacketWhenClosing = value; }
+ }
+
/* METHODS */
public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer,
@@ -451,7 +458,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (!(shutdownCircuit))
{
GC.Collect();
- m_clientThread.Abort();
+
+ // Sends a KillPacket object, with which, the
+ // blockingqueue dequeues and sees it's a killpacket
+ // and terminates within the context of the client thread.
+ // This ensures that it's done from within the context
+ // of the client thread regardless of where Close() is called.
+ KillEndDone();
}
}
@@ -752,7 +765,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
ClientLoop();
}
}
- catch (Exception e)
+ catch (System.Exception e)
{
if (e is ThreadAbortException)
throw e;
@@ -3740,6 +3753,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_PacketHandler.InPacket((Packet) NewPack);
}
+
///
/// The dreaded OutPacket. This should only be called from within
/// the ClientStack itself right now
@@ -6093,15 +6107,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendLogoutPacket()
{
- LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
- // TODO: don't create new blocks if recycling an old packet
- logReply.AgentData.AgentID = AgentId;
- logReply.AgentData.SessionID = SessionId;
- logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
- logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
- logReply.InventoryData[0].ItemID = LLUUID.Zero;
+ // I know this is a bit of a hack, however there are times when you don't
+ // want to send this, but still need to do the rest of the shutdown process
+ // this method gets called from the packet server.. which makes it practically
+ // impossible to do any other way.
- OutPacket(logReply, ThrottleOutPacketType.Task);
+ if (m_SendLogoutPacketWhenClosing)
+ {
+ LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
+ // TODO: don't create new blocks if recycling an old packet
+ logReply.AgentData.AgentID = AgentId;
+ logReply.AgentData.SessionID = SessionId;
+ logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
+ logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
+ logReply.InventoryData[0].ItemID = LLUUID.Zero;
+
+ OutPacket(logReply, ThrottleOutPacketType.Task);
+ }
}
public void SendHealth(float health)
@@ -6443,5 +6465,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
OutPacket(reply, ThrottleOutPacketType.Land);
}
+
+ public void KillEndDone()
+ {
+ KillPacket kp = new KillPacket();
+ OutPacket(kp, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority);
+ }
}
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
index 209ec36b7a..830074a374 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
@@ -30,6 +30,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
+using System.Threading;
using System.Timers;
using System.Reflection;
using libsecondlife;
@@ -233,6 +234,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// to. Packet drop notifies will not be triggered in this
// configuration!
//
+
if ((m_SynchronizeClient != null) && (!m_Client.IsActive))
{
if (m_SynchronizeClient(m_Client.Scene, packet,
@@ -744,6 +746,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
+ // If we sent a killpacket
+ if (packet is KillPacket)
+ Thread.CurrentThread.Abort();
+
// Actually make the byte array and send it
byte[] sendbuffer = packet.ToBytes();
diff --git a/OpenSim/Region/Communications/Local/LocalBackEndServices.cs b/OpenSim/Region/Communications/Local/LocalBackEndServices.cs
index a2e1e0c83a..a2c3c2cc3e 100644
--- a/OpenSim/Region/Communications/Local/LocalBackEndServices.cs
+++ b/OpenSim/Region/Communications/Local/LocalBackEndServices.cs
@@ -107,7 +107,7 @@ namespace OpenSim.Region.Communications.Local
// connectivity errors.
// Don't change this line below to 'm_regions[regionInfo.RegionHandle] = regionInfo' unless you
// *REALLY* know what you are doing here.
- m_regions.Remove(regionInfo.RegionHandle);
+ m_regions[regionInfo.RegionHandle] = regionInfo;
m_log.Warn("[INTERREGION STANDALONE]: Region registered twice. Region went down and came back up.");
diff --git a/OpenSim/Region/Communications/Local/LocalInventoryService.cs b/OpenSim/Region/Communications/Local/LocalInventoryService.cs
index 4f6046258d..6e7ace51e2 100644
--- a/OpenSim/Region/Communications/Local/LocalInventoryService.cs
+++ b/OpenSim/Region/Communications/Local/LocalInventoryService.cs
@@ -49,6 +49,9 @@ namespace OpenSim.Region.Communications.Local
m_log.InfoFormat("[LOCAL INVENTORY SERVICE]: Requesting inventory for user {0}", userID);
List skeletonFolders = GetInventorySkeleton(userID);
+ if (skeletonFolders == null)
+ return;
+
InventoryFolderImpl rootFolder = null;
List folders = new List();
diff --git a/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs
new file mode 100644
index 0000000000..f6f0e8f3c9
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/InterGrid/OpenGridProtocolModule.cs
@@ -0,0 +1,881 @@
+/*
+ * 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 OpenSim 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.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.Net.Sockets;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Threading;
+
+using libsecondlife;
+using libsecondlife.StructuredData;
+
+using log4net;
+using Nini.Config;
+using Nwc.XmlRpc;
+
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Scenes;
+using OpenSim.Framework.Communications.Cache;
+using OpenSim.Framework.Communications.Capabilities;
+using OpenSim.Framework.Statistics;
+using LLSD = libsecondlife.StructuredData.LLSD;
+using LLSDMap = libsecondlife.StructuredData.LLSDMap;
+using LLSDArray = libsecondlife.StructuredData.LLSDArray;
+
+namespace OpenSim.Region.Environment.Modules.InterGrid
+{
+ public struct OGPState
+ {
+ public string first_name;
+ public string last_name;
+ public LLUUID agent_id;
+ public LLUUID local_agent_id;
+ public LLUUID region_id;
+ public uint circuit_code;
+ public LLUUID secure_session_id;
+ public LLUUID session_id;
+ public bool agent_access;
+ public string sim_access;
+ public uint god_level;
+ public bool god_overide;
+ public bool identified;
+ public bool transacted;
+ public bool age_verified;
+ public bool allow_redirect;
+ public int limited_to_estate;
+ public string inventory_host;
+ public bool src_can_see_mainland;
+ public int src_estate_id;
+ }
+
+
+ public class OpenGridProtocolModule : IRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ private List m_scene = new List();
+
+ private Dictionary CapsLoginID = new Dictionary();
+ private Dictionary m_OGPState = new Dictionary();
+
+
+
+ #region IRegionModule Members
+
+ public void Initialise(Scene scene, IConfigSource config)
+ {
+ bool enabled = false;
+ IConfig cfg = null;
+ try
+ {
+ cfg = config.Configs["OpenGridProtocol"];
+ } catch (NullReferenceException)
+ {
+ enabled = false;
+ }
+ if (cfg != null)
+ {
+ enabled = cfg.GetBoolean("ogp_enabled", false);
+ if (enabled)
+ {
+ m_log.Warn("[OGP]: Open Grid Protocol is on, Listening for Clients on /agent/");
+ lock (m_scene)
+ {
+ if (m_scene.Count == 0)
+ {
+ scene.AddLLSDHandler("/agent/", ProcessAgentDomainMessage);
+ }
+
+ if (!m_scene.Contains(scene))
+ m_scene.Add(scene);
+ }
+ }
+ }
+ // Of interest to this module potentially
+ //scene.EventManager.OnNewClient += OnNewClient;
+ //scene.EventManager.OnGridInstantMessageToFriendsModule += OnGridInstantMessage;
+ //scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
+ //scene.EventManager.OnMakeChildAgent += MakeChildAgent;
+ //scene.EventManager.OnClientClosed += ClientLoggedOut;
+ }
+
+ public void PostInitialise()
+ {
+ }
+
+ public void Close()
+ {
+ }
+
+ public string Name
+ {
+ get { return "OpenGridProtocolModule"; }
+ }
+
+ public bool IsSharedModule
+ {
+ get { return true; }
+ }
+
+ #endregion
+
+ public LLSD ProcessAgentDomainMessage(string path, LLSD request, string endpoint)
+ {
+ // /agent/*
+
+ string[] pathSegments = path.Split('/');
+ if (pathSegments.Length < 1)
+ {
+ return GenerateNoHandlerMessage();
+ }
+
+ m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}",
+ path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]);
+
+ switch (pathSegments[pathSegments.Length - 1])
+ {
+ case "rez_avatar":
+ return RezAvatarMethod(path, request);
+ //break;
+ case "derez_avatar":
+ return DerezAvatarMethod(path, request);
+ //break;
+
+ }
+ if (path.Length < 2)
+ {
+ return GenerateNoHandlerMessage();
+ }
+
+ switch (pathSegments[pathSegments.Length - 2] + "/" + pathSegments[pathSegments.Length - 1])
+ {
+ case "rez_avatar/rez":
+ return RezAvatarMethod(path, request);
+ //break;
+ case "rez_avatar/request":
+ return RequestRezAvatarMethod(path, request);
+ //break;
+ default:
+ return GenerateNoHandlerMessage();
+ }
+ //return null;
+ }
+
+ public LLSD RequestRezAvatarMethod(string path, LLSD request)
+ {
+ m_log.WarnFormat("[REQUESTREZAVATAR]: {0}", request.ToString());
+
+ LLSDMap requestMap = (LLSDMap)request;
+
+ Scene homeScene = GetRootScene();
+
+
+
+ if (homeScene == null)
+ return GenerateNoHandlerMessage();
+
+
+ RegionInfo reg = homeScene.RegionInfo;
+ ulong regionhandle = GetOSCompatibleRegionHandle(reg);
+ string RegionURI = reg.ServerURI;
+ int RegionPort = (int)reg.HttpPort;
+
+ LLUUID RemoteAgentID = requestMap["agent_id"].AsUUID();
+
+ // will be used in the future. The client always connects with the aditi agentid currently
+ LLUUID LocalAgentID = RemoteAgentID;
+
+ string FirstName = requestMap["first_name"].AsString();
+ string LastName = requestMap["last_name"].AsString();
+
+
+ OGPState userState = GetOGPState(LocalAgentID);
+
+ userState.first_name = requestMap["first_name"].AsString();
+ userState.last_name = requestMap["last_name"].AsString();
+ userState.age_verified = requestMap["age_verified"].AsBoolean();
+ userState.transacted = requestMap["transacted"].AsBoolean();
+ userState.agent_access = requestMap["agent_access"].AsBoolean();
+ userState.allow_redirect = requestMap["allow_redirect"].AsBoolean();
+ userState.identified = requestMap["identified"].AsBoolean();
+ userState.god_level = (uint)requestMap["god_level"].AsInteger();
+ userState.sim_access = requestMap["sim_access"].AsString();
+ userState.agent_id = RemoteAgentID;
+ userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger();
+ userState.src_can_see_mainland = requestMap["src_can_see_mainland"].AsBoolean();
+ userState.src_estate_id = requestMap["src_estate_id"].AsInteger();
+ userState.local_agent_id = LocalAgentID;
+
+ UpdateOGPState(LocalAgentID, userState);
+
+ LLSDMap responseMap = new LLSDMap();
+ responseMap["sim_host"] = LLSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
+ responseMap["sim_ip"] = LLSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
+ responseMap["connect"] = LLSD.FromBoolean(true);
+ responseMap["sim_port"] = LLSD.FromInteger(reg.InternalEndPoint.Port);
+ responseMap["region_x"] = LLSD.FromInteger(reg.RegionLocX * (uint)Constants.RegionSize); // LLX
+ responseMap["region_Y"] = LLSD.FromInteger(reg.RegionLocY * (uint)Constants.RegionSize); // LLY
+ responseMap["region_id"] = LLSD.FromUUID(reg.originRegionID);
+ responseMap["sim_access"] = LLSD.FromString((reg.RegionSettings.Maturity == 1) ? "Mature" : "PG");
+
+ // Generate a dummy agent for the user so we can get back a CAPS path
+ AgentCircuitData agentData = new AgentCircuitData();
+ agentData.AgentID = LocalAgentID;
+ agentData.BaseFolder=LLUUID.Zero;
+ agentData.CapsPath=Util.GetRandomCapsPath();
+ agentData.child = false;
+ agentData.circuitcode = (uint)(Util.RandomClass.Next());
+ agentData.firstname = FirstName;
+ agentData.lastname = LastName;
+ agentData.SecureSessionID=LLUUID.Random();
+ agentData.SessionID=LLUUID.Random();
+ agentData.startpos=LLVector3.Zero;
+
+ // Pre-Fill our region cache with information on the agent.
+ UserAgentData useragent = new UserAgentData();
+ useragent.AgentIP="unknown";
+ useragent.AgentOnline=true;
+ useragent.AgentPort = (uint)0;
+ useragent.Handle = regionhandle;
+ useragent.InitialRegion = reg.originRegionID;
+ useragent.LoginTime=Util.UnixTimeSinceEpoch();
+ useragent.LogoutTime = 0;
+ useragent.Position=agentData.startpos;
+ useragent.PositionX=agentData.startpos.X;
+ useragent.PositionY=agentData.startpos.Y;
+ useragent.PositionZ=agentData.startpos.Z;
+ useragent.Region=reg.originRegionID;
+ useragent.SecureSessionID=agentData.SecureSessionID;
+ useragent.SessionID = agentData.SessionID;
+
+
+ UserProfileData userProfile = new UserProfileData();
+ userProfile.AboutText = "OGP User";
+ userProfile.CanDoMask = (uint)0;
+ userProfile.Created = Util.UnixTimeSinceEpoch();
+ userProfile.CurrentAgent = useragent;
+ userProfile.CustomType = "OGP";
+ userProfile.FirstLifeAboutText = "I'm testing OpenGrid Protocol";
+ userProfile.FirstLifeImage = LLUUID.Zero;
+ userProfile.FirstName = agentData.firstname;
+ userProfile.GodLevel = 0;
+ userProfile.HomeLocation = agentData.startpos;
+ userProfile.HomeLocationX = agentData.startpos.X;
+ userProfile.HomeLocationY = agentData.startpos.Y;
+ userProfile.HomeLocationZ = agentData.startpos.Z;
+ userProfile.HomeLookAt = LLVector3.Zero;
+ userProfile.HomeLookAtX = userProfile.HomeLookAt.X;
+ userProfile.HomeLookAtY = userProfile.HomeLookAt.Y;
+ userProfile.HomeLookAtZ = userProfile.HomeLookAt.Z;
+ userProfile.HomeRegion = reg.RegionHandle;
+ userProfile.HomeRegionID = reg.originRegionID;
+ userProfile.HomeRegionX = reg.RegionLocX;
+ userProfile.HomeRegionY = reg.RegionLocY;
+ userProfile.ID = agentData.AgentID;
+ userProfile.Image = LLUUID.Zero;
+ userProfile.LastLogin = Util.UnixTimeSinceEpoch();
+ userProfile.Partner = LLUUID.Zero;
+ userProfile.PasswordHash = "$1$";
+ userProfile.PasswordSalt = "";
+ userProfile.RootInventoryFolderID = LLUUID.Zero;
+ userProfile.SurName = agentData.lastname;
+ userProfile.UserAssetURI = homeScene.CommsManager.NetworkServersInfo.AssetURL;
+ userProfile.UserFlags = 0;
+ userProfile.UserInventoryURI = homeScene.CommsManager.NetworkServersInfo.InventoryURL;
+ userProfile.WantDoMask = 0;
+ userProfile.WebLoginKey = LLUUID.Random();
+
+ // Do caps registration
+ // get seed cap
+
+
+ // Stick our data in the cache so the region will know something about us
+ homeScene.CommsManager.UserProfileCacheService.PreloadUserCache(agentData.AgentID, userProfile);
+
+ // Call 'new user' event handler
+ homeScene.NewUserConnection(reg.RegionHandle, agentData);
+
+
+ string raCap = string.Empty;
+
+ LLUUID AvatarRezCapUUID = LLUUID.Random();
+ string rezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar";
+
+ // Get a reference to the user's cap so we can pull out the Caps Object Path
+ OpenSim.Framework.Communications.Capabilities.Caps userCap = homeScene.GetCapsHandlerForUser(agentData.AgentID);
+
+ responseMap["seed_capability"] = LLSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + "/CAPS/" + userCap.CapsObjectPath + "0000/");
+
+ responseMap["rez_avatar/rez"] = LLSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + rezAvatarPath);
+
+ // Add the user to the list of CAPS that are outstanding.
+ // well allow the caps hosts in this dictionary
+ lock (CapsLoginID)
+ {
+ if (CapsLoginID.ContainsKey(rezAvatarPath))
+ {
+ m_log.Error("[OGP]: Holy anomoly batman! Caps path already existed! All the UUID Duplication worries were founded!");
+ }
+ else
+ {
+ CapsLoginID.Add(rezAvatarPath, agentData);
+ }
+ }
+
+ return responseMap;
+ }
+
+ public LLSD RezAvatarMethod(string path, LLSD request)
+ {
+ m_log.WarnFormat("[REZAVATAR]: {0}", request.ToString());
+
+ LLSDMap responseMap = new LLSDMap();
+
+ AgentCircuitData userData = null;
+
+ // Only people we've issued a cap can go further
+ if (TryGetAgentCircuitData(path,out userData))
+ {
+ LLSDMap requestMap = (LLSDMap)request;
+
+ // take these values to start. There's a few more
+ LLUUID SecureSessionID=requestMap["secure_session_id"].AsUUID();
+ LLUUID SessionID = requestMap["session_id"].AsUUID();
+ int circuitcode = requestMap["circuit_code"].AsInteger();
+
+ //Update our Circuit data with the real values
+ userData.SecureSessionID = SecureSessionID;
+ userData.SessionID = SessionID;
+
+ // Locate a home scene suitable for the user.
+ Scene homeScene = GetRootScene();
+
+ if (homeScene != null)
+ {
+ // Get a reference to their Cap object so we can pull out the capobjectroot
+ OpenSim.Framework.Communications.Capabilities.Caps userCap =
+ homeScene.GetCapsHandlerForUser(userData.AgentID);
+
+ //Update the circuit data in the region so this user is authorized
+ homeScene.UpdateCircuitData(userData);
+ homeScene.ChangeCircuitCode(userData.circuitcode,(uint)circuitcode);
+
+ // Load state
+ OGPState userState = GetOGPState(userData.AgentID);
+
+ // Keep state changes
+ userState.first_name = requestMap["first_name"].AsString();
+ userState.secure_session_id = requestMap["secure_session_id"].AsUUID();
+ userState.age_verified = requestMap["age_verified"].AsBoolean();
+ userState.region_id = homeScene.RegionInfo.originRegionID; // replace 0000000 with our regionid
+ userState.transacted = requestMap["transacted"].AsBoolean();
+ userState.agent_access = requestMap["agent_access"].AsBoolean();
+ userState.inventory_host = requestMap["inventory_host"].AsString();
+ userState.identified = requestMap["identified"].AsBoolean();
+ userState.session_id = requestMap["session_id"].AsUUID();
+ userState.god_level = (uint)requestMap["god_level"].AsInteger();
+ userState.last_name = requestMap["last_name"].AsString();
+ userState.god_overide = requestMap["god_override"].AsBoolean();
+ userState.circuit_code = (uint)requestMap["circuit_code"].AsInteger();
+ userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger();
+
+ // Save state changes
+ UpdateOGPState(userData.AgentID, userState);
+
+ // Get the region information for the home region.
+ RegionInfo reg = homeScene.RegionInfo;
+
+ // Dummy positional and look at info.. we don't have it.
+ LLSDArray PositionArray = new LLSDArray();
+ PositionArray.Add(LLSD.FromInteger(128));
+ PositionArray.Add(LLSD.FromInteger(128));
+ PositionArray.Add(LLSD.FromInteger(40));
+
+ LLSDArray LookAtArray = new LLSDArray();
+ LookAtArray.Add(LLSD.FromInteger(1));
+ LookAtArray.Add(LLSD.FromInteger(1));
+ LookAtArray.Add(LLSD.FromInteger(1));
+
+ // Our region's X and Y position in OpenSimulator space.
+ uint fooX = reg.RegionLocX;
+ uint fooY = reg.RegionLocY;
+ m_log.InfoFormat("[OGP]: region x({0}) region y({1})", fooX, fooY);
+ m_log.InfoFormat("[OGP]: region http {0} {1}", reg.ServerURI, reg.HttpPort);
+ m_log.InfoFormat("[OGO]: region UUID {0} ", reg.RegionID);
+
+ // Convert the X and Y position to LL space
+ responseMap["region_x"] = LLSD.FromInteger(fooX * (uint)Constants.RegionSize); // convert it to LL X
+ responseMap["region_y"] = LLSD.FromInteger(fooY * (uint)Constants.RegionSize); // convert it to LL Y
+
+ // Give em a new seed capability
+ responseMap["seed_capability"] = LLSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + "/CAPS/" + userCap.CapsObjectPath + "0000/");
+ responseMap["region"] = LLSD.FromUUID(reg.originRegionID);
+ responseMap["look_at"] = LookAtArray;
+
+ responseMap["sim_port"] = LLSD.FromInteger(reg.InternalEndPoint.Port);
+ responseMap["sim_host"] = LLSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());// + ":" + reg.InternalEndPoint.Port.ToString());
+ responseMap["sim_ip"] = LLSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
+
+ responseMap["session_id"] = LLSD.FromUUID(SessionID);
+ responseMap["secure_session_id"] = LLSD.FromUUID(SecureSessionID);
+ responseMap["circuit_code"] = LLSD.FromInteger(circuitcode);
+
+ responseMap["position"] = PositionArray;
+
+ responseMap["region_id"] = LLSD.FromUUID(reg.originRegionID);
+
+ responseMap["sim_access"] = LLSD.FromString("Mature");
+
+ responseMap["connect"] = LLSD.FromBoolean(true);
+
+ m_log.InfoFormat("[OGP]: host: {0}, IP {1}", responseMap["sim_host"].ToString(), responseMap["sim_ip"].ToString());
+
+ }
+
+ }
+
+ return responseMap;
+ }
+
+
+
+ public LLSD DerezAvatarMethod(string path, LLSD request)
+ {
+
+
+ m_log.ErrorFormat("DerezPath: {0}, Request: {1}", path, request.ToString());
+
+ LLSD llsdResponse = null;
+ LLSDMap responseMap = new LLSDMap();
+
+
+
+ string[] PathArray = path.Split('/');
+ m_log.InfoFormat("[OGP]: prefix {0}, uuid {1}, suffix {2}", PathArray[1], PathArray[2], PathArray[3]);
+ string uuidString = PathArray[2];
+ m_log.InfoFormat("[OGP]: Request to Derez avatar with UUID {0}", uuidString);
+ LLUUID userUUID = LLUUID.Zero;
+ if (Helpers.TryParse(uuidString, out userUUID))
+ {
+
+ LLUUID RemoteID = uuidString;
+ LLUUID LocalID = RemoteID;
+ // FIXME: TODO: Routine to map RemoteUUIDs to LocalUUIds
+ // would be done already.. but the client connects with the Aditi UUID
+ // regardless over the UDP stack
+
+ OGPState userState = GetOGPState(LocalID);
+ if (userState.agent_id != LLUUID.Zero)
+ {
+
+ LLSDMap outboundRequestMap = new LLSDMap();
+ LLSDMap inboundRequestMap = (LLSDMap)request;
+ string rezAvatarString = inboundRequestMap["rez_avatar"].AsString();
+
+ LLSDArray LookAtArray = new LLSDArray();
+ LookAtArray.Add(LLSD.FromInteger(1));
+ LookAtArray.Add(LLSD.FromInteger(1));
+ LookAtArray.Add(LLSD.FromInteger(1));
+
+
+ LLSDArray PositionArray = new LLSDArray();
+ PositionArray.Add(LLSD.FromInteger(128));
+ PositionArray.Add(LLSD.FromInteger(128));
+ PositionArray.Add(LLSD.FromInteger(40));
+
+ LLSDArray lookArray = new LLSDArray();
+ lookArray.Add(LLSD.FromInteger(128));
+ lookArray.Add(LLSD.FromInteger(128));
+ lookArray.Add(LLSD.FromInteger(40));
+
+ responseMap["connect"] = LLSD.FromBoolean(true);// it's okay to give this user up
+ responseMap["look_at"] = LookAtArray;
+
+ m_log.WarnFormat("[OGP]: Invoking rez_avatar on host:{0} for avatar: {1} {2}", rezAvatarString, userState.first_name, userState.last_name);
+
+ LLSDMap rezResponseMap = invokeRezAvatarCap(responseMap, rezAvatarString,userState);
+
+ // If invoking it returned an error, parse and end
+ if (rezResponseMap.ContainsKey("connect"))
+ {
+ if (rezResponseMap["connect"].AsBoolean() == false)
+ {
+ return responseMap;
+ }
+ }
+
+ string rezRespSeedCap = rezResponseMap["seed_capability"].AsString();
+ string rezRespSim_ip = rezResponseMap["sim_ip"].AsString();
+ string rezRespSim_host = rezResponseMap["sim_host"].AsString();
+
+ int rrPort = rezResponseMap["sim_port"].AsInteger();
+ int rrX = rezResponseMap["region_x"].AsInteger();
+ int rrY = rezResponseMap["region_y"].AsInteger();
+ m_log.ErrorFormat("X:{0}, Y:{1}", rrX, rrY);
+ LLUUID rrRID = rezResponseMap["region_id"].AsUUID();
+
+ string rrAccess = rezResponseMap["sim_access"].AsString();
+
+ LLSDArray RezResponsePositionArray = (LLSDArray)rezResponseMap["position"];
+
+ responseMap["seed_capability"] = LLSD.FromString(rezRespSeedCap);
+ responseMap["sim_ip"] = LLSD.FromString(Util.GetHostFromDNS(rezRespSim_ip).ToString());
+ responseMap["sim_host"] = LLSD.FromString(Util.GetHostFromDNS(rezRespSim_host).ToString());
+ responseMap["sim_port"] = LLSD.FromInteger(rrPort);
+ responseMap["region_x"] = LLSD.FromInteger(rrX * (int)Constants.RegionSize);
+ responseMap["region_y"] = LLSD.FromInteger(rrY * (int)Constants.RegionSize);
+ responseMap["region_id"] = LLSD.FromUUID(rrRID);
+ responseMap["sim_access"] = LLSD.FromString(rrAccess);
+
+
+
+ responseMap["position"] = RezResponsePositionArray;
+ responseMap["look_at"] = lookArray;
+ responseMap["connect"] = LLSD.FromBoolean(true);
+
+ ShutdownConnection(LocalID,this);
+
+
+ m_log.Warn("RESPONSEDEREZ: " + responseMap.ToString());
+ return responseMap;
+
+ }
+ else
+ {
+
+ return GenerateNoHandlerMessage();
+ }
+ }
+ else
+ {
+ return GenerateNoHandlerMessage();
+ }
+
+ return responseMap;
+ }
+
+ private LLSDMap invokeRezAvatarCap(LLSDMap responseMap, string CapAddress, OGPState userState)
+ {
+
+ WebRequest DeRezRequest = WebRequest.Create(CapAddress);
+ DeRezRequest.Method = "POST";
+ DeRezRequest.ContentType = "application/xml+llsd";
+
+ LLSDMap RAMap = new LLSDMap();
+ LLSDMap AgentParms = new LLSDMap();
+ LLSDMap RegionParms = new LLSDMap();
+
+
+ AgentParms["first_name"] = LLSD.FromString(userState.first_name);
+ AgentParms["last_name"] = LLSD.FromString(userState.last_name);
+ AgentParms["agent_id"] = LLSD.FromUUID(userState.agent_id);
+ RegionParms["region_id"] = LLSD.FromUUID(userState.region_id);
+ AgentParms["circuit_code"] = LLSD.FromInteger(userState.circuit_code);
+ AgentParms["secure_session_id"] = LLSD.FromUUID(userState.secure_session_id);
+ AgentParms["session_id"] = LLSD.FromUUID(userState.session_id);
+ AgentParms["agent_access"] = LLSD.FromBoolean(userState.agent_access);
+ AgentParms["god_level"] = LLSD.FromInteger(userState.god_level);
+ AgentParms["god_overide"] = LLSD.FromBoolean(userState.god_overide);
+ AgentParms["identified"] = LLSD.FromBoolean(userState.identified);
+ AgentParms["transacted"] = LLSD.FromBoolean(userState.transacted);
+ AgentParms["age_verified"] = LLSD.FromBoolean(userState.age_verified);
+ AgentParms["limited_to_estate"] = LLSD.FromInteger(userState.limited_to_estate);
+ AgentParms["inventory_host"] = LLSD.FromString(userState.inventory_host);
+ RAMap["agent_params"] = AgentParms;
+ RAMap["region_params"] = RegionParms;
+
+ string RAMapString = AgentParms.ToString();
+ m_log.InfoFormat("[OGP] RAMap string {0}", RAMapString);
+ LLSD LLSDofRAMap = AgentParms; // RENAME if this works
+
+ m_log.InfoFormat("[OGP]: LLSD of map as string was {0}", LLSDofRAMap.ToString());
+ byte[] buffer = LLSDParser.SerializeXmlBytes(LLSDofRAMap);
+
+ //string bufferDump = System.Text.Encoding.ASCII.GetString(buffer);
+ //m_log.InfoFormat("[OGP]: buffer form is {0}",bufferDump);
+ //m_log.InfoFormat("[OGP]: LLSD of map was {0}",buffer.Length);
+
+ Stream os = null;
+ try
+ { // send the Post
+ DeRezRequest.ContentLength = buffer.Length; //Count bytes to send
+ os = DeRezRequest.GetRequestStream();
+ os.Write(buffer, 0, buffer.Length); //Send it
+ os.Close();
+ m_log.InfoFormat("[OGP]: Derez Avatar Posted Rez Avatar request to remote sim {0}", CapAddress);
+ }
+ catch (WebException ex)
+ {
+ m_log.InfoFormat("[OGP] Bad send on de_rez_avatar {0}", ex.Message);
+ responseMap["connect"] = LLSD.FromBoolean(false);
+
+ return responseMap;
+ }
+
+ m_log.Info("[OGP] waiting for a reply after rez avatar send");
+ string rez_avatar_reply = null;
+ { // get the response
+ try
+ {
+ WebResponse webResponse = DeRezRequest.GetResponse();
+ if (webResponse == null)
+ {
+ m_log.Info("[OGP:] Null reply on rez_avatar post");
+ }
+
+ StreamReader sr = new StreamReader(webResponse.GetResponseStream());
+ rez_avatar_reply = sr.ReadToEnd().Trim();
+ m_log.InfoFormat("[OGP]: rez_avatar reply was {0} ", rez_avatar_reply);
+
+ }
+ catch (WebException ex)
+ {
+ m_log.InfoFormat("[OGP]: exception on read after send of rez avatar {0}", ex.Message);
+ responseMap["connect"] = LLSD.FromBoolean(false);
+
+ return responseMap;
+ }
+ LLSD rezResponse = null;
+ try
+ {
+ rezResponse = LLSDParser.DeserializeXml(rez_avatar_reply);
+
+ responseMap = (LLSDMap)rezResponse;
+ }
+ catch (Exception ex)
+ {
+ m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message);
+ responseMap["connect"] = LLSD.FromBoolean(false);
+
+ return responseMap;
+ }
+ }
+ return responseMap;
+ }
+
+
+
+ public LLSD GenerateNoHandlerMessage()
+ {
+ LLSDMap map = new LLSDMap();
+ map["reason"] = LLSD.FromString("LLSDRequest");
+ map["message"] = LLSD.FromString("No handler registered for LLSD Requests");
+ map["login"] = LLSD.FromString("false");
+
+ return map;
+ }
+
+ private bool TryGetAgentCircuitData(string path, out AgentCircuitData userdata)
+ {
+ userdata = null;
+ lock (CapsLoginID)
+ {
+ if (CapsLoginID.ContainsKey(path))
+ {
+ userdata = CapsLoginID[path];
+ DiscardUsedCap(path);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void DiscardUsedCap(string path)
+ {
+ CapsLoginID.Remove(path);
+ }
+
+
+ private Scene GetRootScene()
+ {
+ Scene ReturnScene = null;
+ lock (m_scene)
+ {
+ if (m_scene.Count > 0)
+ {
+ ReturnScene = m_scene[0];
+ }
+ }
+
+ return ReturnScene;
+
+ }
+
+ private ulong GetOSCompatibleRegionHandle(RegionInfo reg)
+ {
+ return Util.UIntsToLong(reg.RegionLocX, reg.RegionLocY);
+ }
+
+ private ulong GetOSCompatibleRegionHandle(uint x, uint y)
+ {
+ return Util.UIntsToLong(x, y);
+ }
+
+ private ulong GetOSCompatibleRegionHandle(ulong regionhandle)
+ {
+ uint x,y;
+ Helpers.LongToUInts(regionhandle,out x, out y);
+ return GetOSCompatibleRegionHandle(x,y);
+ }
+
+
+ private ulong GetOGPCompatibleRegionHandle(RegionInfo reg)
+ {
+ return Util.UIntsToLong((reg.RegionLocX * (uint)Constants.RegionSize), (reg.RegionLocY * (uint)Constants.RegionSize));
+ }
+
+ private ulong GetOGPCompatibleRegionHandle(uint x, uint y)
+ {
+ return Util.UIntsToLong((x * (uint)Constants.RegionSize), (y * (uint)Constants.RegionSize));
+ }
+
+ private ulong GetOGPCompatibleRegionHandle(ulong regionhandle)
+ {
+ uint x, y;
+ Helpers.LongToUInts(regionhandle, out x, out y);
+ return GetOGPCompatibleRegionHandle(x, y);
+ }
+
+ private OGPState InitializeNewState()
+ {
+ OGPState returnState = new OGPState();
+ returnState.first_name = "";
+ returnState.last_name = "";
+ returnState.agent_id = LLUUID.Zero;
+ returnState.local_agent_id = LLUUID.Zero;
+ returnState.region_id = LLUUID.Zero;
+ returnState.circuit_code = 0;
+ returnState.secure_session_id = LLUUID.Zero;
+ returnState.session_id = LLUUID.Zero;
+ returnState.agent_access = true;
+ returnState.god_level = 0;
+ returnState.god_overide = false;
+ returnState.identified = false;
+ returnState.transacted = false;
+ returnState.age_verified = false;
+ returnState.limited_to_estate = 1;
+ returnState.inventory_host = "http://inv4.mysql.aditi.lindenlab.com";
+ returnState.allow_redirect = true;
+ returnState.sim_access = "";
+ returnState.src_can_see_mainland = true;
+ returnState.src_estate_id = 1;
+
+ return returnState;
+ }
+
+ private OGPState GetOGPState(LLUUID agentId)
+ {
+ lock (m_OGPState)
+ {
+ if (m_OGPState.ContainsKey(agentId))
+ {
+ return m_OGPState[agentId];
+ }
+ else
+ {
+ return InitializeNewState();
+ }
+ }
+ }
+
+ public void DeleteOGPState(LLUUID agentId)
+ {
+ lock (m_OGPState)
+ if (m_OGPState.ContainsKey(agentId))
+ m_OGPState.Remove(agentId);
+
+ }
+
+ private void UpdateOGPState(LLUUID agentId, OGPState state)
+ {
+ lock (m_OGPState)
+ {
+ if (m_OGPState.ContainsKey(agentId))
+ {
+ m_OGPState[agentId] = state;
+ }
+ else
+ {
+ m_OGPState.Add(agentId,state);
+ }
+ }
+ }
+ public void ShutdownConnection(LLUUID avatarId, OpenGridProtocolModule mod)
+ {
+ Scene homeScene = GetRootScene();
+ ScenePresence avatar = null;
+ if (homeScene.TryGetAvatar(avatarId,out avatar))
+ {
+ KillAUser ku = new KillAUser(avatar,mod);
+ Thread ta = new Thread(ku.ShutdownNoLogout);
+ ta.IsBackground = true;
+ ta.Name = "ShutdownThread";
+ ta.Start();
+ }
+ }
+ }
+
+ public class KillAUser
+ {
+ private ScenePresence avToBeKilled = null;
+ private OpenGridProtocolModule m_mod = null;
+
+ public KillAUser(ScenePresence avatar, OpenGridProtocolModule mod)
+ {
+ avToBeKilled = avatar;
+ m_mod = mod;
+ }
+
+ public void ShutdownNoLogout()
+ {
+ LLUUID avUUID = LLUUID.Zero;
+
+ if (avToBeKilled != null)
+ {
+ avUUID = avToBeKilled.UUID;
+ avToBeKilled.MakeChildAgent();
+
+ avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false;
+
+ Thread.Sleep(30000);
+
+ // test for child agent because they might have come back
+ if (avToBeKilled.IsChildAgent)
+ {
+ m_mod.DeleteOGPState(avUUID);
+ avToBeKilled.ControllingClient.Close(true);
+ }
+ }
+ }
+
+ }
+}
diff --git a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
index 4754a04ae1..2d27b11920 100644
--- a/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/Environment/Modules/World/NPC/NPCAvatar.cs
@@ -43,6 +43,7 @@ namespace OpenSim.Region.Environment.Modules.World.NPC
private readonly LLUUID m_uuid = LLUUID.Random();
private readonly Scene m_scene;
+
public NPCAvatar(string firstname, string lastname, LLVector3 position, Scene scene)
{
m_firstname = firstname;
@@ -124,6 +125,11 @@ namespace OpenSim.Region.Environment.Modules.World.NPC
set { m_scene.Entities[m_uuid].AbsolutePosition = value; }
}
+ public bool SendLogoutPacketWhenClosing
+ {
+ set { }
+ }
+
#region Internal Functions
private void SendOnChatFromViewer(string message, ChatTypeEnum chatType)
@@ -857,5 +863,9 @@ namespace OpenSim.Region.Environment.Modules.World.NPC
public void SendParcelInfo (RegionInfo info, LandData land, LLUUID parcelID, uint x, uint y)
{
}
+
+ public void KillEndDone()
+ {
+ }
}
}
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index a21f701724..6f3267a895 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -2599,6 +2599,17 @@ namespace OpenSim.Region.Environment.Scenes
"[CONNECTION DEBUGGING]: Skipping this region for welcoming avatar {0} [{1}] at {2}",
agent.AgentID, regionHandle, RegionInfo.RegionName);
}
+
+ }
+
+ public void UpdateCircuitData(AgentCircuitData data)
+ {
+ m_authenticateHandler.UpdateAgentData(data);
+ }
+
+ public bool ChangeCircuitCode(uint oldcc, uint newcc)
+ {
+ return m_authenticateHandler.TryChangeCiruitCode(oldcc, newcc);
}
protected void HandleLogOffUserFromGrid(ulong regionHandle, LLUUID AvatarID, LLUUID RegionSecret, string message)
@@ -2664,6 +2675,18 @@ namespace OpenSim.Region.Environment.Scenes
m_capsHandlers[agentId] = cap;
}
+ public Caps GetCapsHandlerForUser(LLUUID agentId)
+ {
+ lock (m_capsHandlers)
+ {
+ if (m_capsHandlers.ContainsKey(agentId))
+ {
+ return m_capsHandlers[agentId];
+ }
+ }
+ return null;
+ }
+
///
/// Remove the caps handler for a given agent.
///
@@ -3838,6 +3861,12 @@ namespace OpenSim.Region.Environment.Scenes
m_httpListener.AddStreamHandler(handler);
}
+ public bool AddLLSDHandler(string path, LLSDMethod handler)
+ {
+ return m_httpListener.AddLLSDHandler(path, handler);
+ }
+
+
public void RemoveStreamHandler(string httpMethod, string path)
{
m_httpListener.RemoveStreamHandler(httpMethod, path);
@@ -3848,6 +3877,11 @@ namespace OpenSim.Region.Environment.Scenes
m_httpListener.RemoveHTTPHandler(httpMethod, path);
}
+ public bool RemoveLLSDHandler(string path, LLSDMethod handler)
+ {
+ return m_httpListener.RemoveLLSDHandler(path, handler);
+ }
+
#endregion
#region Avatar Appearance Default
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 655dfe4098..3ea518fffe 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -302,6 +302,11 @@ namespace OpenSim.Region.Examples.SimpleModule
get { return m_scene; }
}
+ public bool SendLogoutPacketWhenClosing
+ {
+ set { }
+ }
+
public virtual void ActivateGesture(LLUUID assetId, LLUUID gestureId)
{
}
@@ -855,5 +860,9 @@ namespace OpenSim.Region.Examples.SimpleModule
public void SendParcelInfo (RegionInfo info, LandData land, LLUUID parcelID, uint x, uint y)
{
}
+
+ public void KillEndDone()
+ {
+ }
}
}
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index eb1cc0ba80..f0e7d5f753 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -697,3 +697,8 @@ help = http://127.0.0.1/help
; password help: optional: page providing password assistance for users of your grid
password = http://127.0.0.1/password
+
+;These are the settings for the Open Grid Protocol.. the Agent Domain, Region Domain, you know..
+[OpenGridProtocol]
+;On/true or Off/false
+ogp_enabled=false
\ No newline at end of file