diff --git a/OpenSim/Framework/Communications/LoginResponse.cs b/OpenSim/Framework/Communications/LoginResponse.cs
index 954aecbd43..2239a9cc49 100644
--- a/OpenSim/Framework/Communications/LoginResponse.cs
+++ b/OpenSim/Framework/Communications/LoginResponse.cs
@@ -30,6 +30,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using libsecondlife;
+using libsecondlife.StructuredData;
using Nwc.XmlRpc;
using OpenSim.Framework.Console;
@@ -197,11 +198,31 @@ namespace OpenSim.Framework.UserManagement
return (xmlRpcResponse);
} // GenerateResponse
+ public LLSD GenerateFailureResponseLLSD(string reason, string message, string login)
+ {
+ LLSDMap map = new LLSDMap();
+
+ // Ensure Login Failed message/reason;
+ ErrorMessage = message;
+ ErrorReason = reason;
+
+ map["reason"] = LLSD.FromString(ErrorReason);
+ map["message"] = LLSD.FromString(ErrorMessage);
+ map["login"] = LLSD.FromString(login);
+
+ return map;
+ }
+
public XmlRpcResponse CreateFailedResponse()
{
return (CreateLoginFailedResponse());
} // CreateErrorConnectingToGridResponse()
+ public LLSD CreateFailedResponseLLSD()
+ {
+ return CreateLoginFailedResponseLLSD();
+ }
+
public XmlRpcResponse CreateLoginFailedResponse()
{
return
@@ -210,6 +231,14 @@ namespace OpenSim.Framework.UserManagement
"false"));
} // LoginFailedResponse
+ public LLSD CreateLoginFailedResponseLLSD()
+ {
+ return GenerateFailureResponseLLSD(
+ "key",
+ "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.",
+ "false");
+ }
+
public XmlRpcResponse CreateAlreadyLoggedInResponse()
{
return
@@ -218,6 +247,14 @@ namespace OpenSim.Framework.UserManagement
"false"));
} // CreateAlreadyLoggedInResponse()
+ public LLSD CreateAlreadyLoggedInResponseLLSD()
+ {
+ return GenerateFailureResponseLLSD(
+ "presence",
+ "You appear to be already logged in, if this is not the case please wait for your session to timeout, if this takes longer than a few minutes please contact the grid owner",
+ "false");
+ }
+
public XmlRpcResponse CreateDeadRegionResponse()
{
return
@@ -226,6 +263,14 @@ namespace OpenSim.Framework.UserManagement
"false"));
}
+ public LLSD CreateDeadRegionResponseLLSD()
+ {
+ return GenerateFailureResponseLLSD(
+ "key",
+ "The region you are attempting to log into is not responding. Please select another region and try again.",
+ "false");
+ }
+
public XmlRpcResponse CreateGridErrorResponse()
{
return
@@ -234,6 +279,14 @@ namespace OpenSim.Framework.UserManagement
"false"));
}
+ public LLSD CreateGridErrorResponseLLSD()
+ {
+ return GenerateFailureResponseLLSD(
+ "key",
+ "Error connecting to grid. Could not percieve credentials from login XML.",
+ "false");
+ }
+
#endregion
public XmlRpcResponse ToXmlRpcResponse()
@@ -317,6 +370,112 @@ namespace OpenSim.Framework.UserManagement
}
} // ToXmlRpcResponse
+ public LLSD ToLLSDResponse()
+ {
+ try
+ {
+ LLSDMap map = new LLSDMap();
+
+ map["first_name"] = LLSD.FromString(Firstname);
+ map["last_name"] = LLSD.FromString(Lastname);
+ map["agent_access"] = LLSD.FromString(agentAccess);
+
+ map["sim_port"] = LLSD.FromInteger(SimPort);
+ map["sim_ip"] = LLSD.FromString(SimAddress);
+
+ map["agent_id"] = LLSD.FromUUID(AgentID);
+ map["session_id"] = LLSD.FromUUID(SessionID);
+ map["secure_session_id"] = LLSD.FromUUID(SecureSessionID);
+ map["circuit_code"] = LLSD.FromInteger(CircuitCode);
+ map["seconds_since_epoch"] = LLSD.FromInteger((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
+
+ #region Login Flags
+
+ LLSDMap loginFlagsLLSD = new LLSDMap();
+ loginFlagsLLSD["daylight_savings"] = LLSD.FromString(DST);
+ loginFlagsLLSD["stipend_since_login"] = LLSD.FromString(StipendSinceLogin);
+ loginFlagsLLSD["gendered"] = LLSD.FromString(Gendered);
+ loginFlagsLLSD["ever_logged_in"] = LLSD.FromString(EverLoggedIn);
+ map["login-flags"] = WrapLLSDMap(loginFlagsLLSD);
+
+ #endregion Login Flags
+
+ #region Global Textures
+
+ LLSDMap globalTexturesLLSD = new LLSDMap();
+ globalTexturesLLSD["sun_texture_id"] = LLSD.FromString(SunTexture);
+ globalTexturesLLSD["cloud_texture_id"] = LLSD.FromString(CloudTexture);
+ globalTexturesLLSD["moon_texture_id"] = LLSD.FromString(MoonTexture);
+
+ map["global-textures"] = WrapLLSDMap(globalTexturesLLSD);
+
+ #endregion Global Textures
+
+ map["seed_capability"] = LLSD.FromString(seedCapability);
+
+ // FIXME: Need a function that will convert these ArrayLists in to LLSDArrays,
+ // and convert the data inside them to LLSD objects as well
+
+ //map["event_categories"] = eventCategories;
+ //map["event_notifications"] = new LLSDArray(); // todo
+ //map["classified_categories"] = classifiedCategories;
+
+ #region UI Config
+
+ LLSDMap uiConfigLLSD = new LLSDMap();
+ uiConfigLLSD["allow_first_life"] = LLSD.FromString(allowFirstLife);
+ map["ui-config"] = WrapLLSDMap(uiConfigLLSD);
+
+ #endregion UI Config
+
+ #region Inventory
+
+ //map["inventory-skeleton"] = agentInventory;
+ //map["inventory-skel-lib"] = inventoryLibrary;
+ //map["inventory-root"] = inventoryRoot;
+ //map["inventory-lib-root"] = inventoryLibRoot;
+ //map["inventory-lib-owner"] = inventoryLibraryOwner;
+
+ #endregion Inventory
+
+ map["gestures"] = new LLSDArray(); // todo
+
+ //responseData["initial-outfit"] = initialOutfit;
+ //responseData["start_location"] = startLocation;
+
+ map["seed_capability"] = LLSD.FromString(seedCapability);
+ map["home"] = LLSD.FromString(home);
+ map["look_at"] = LLSD.FromString(lookAt);
+ map["message"] = LLSD.FromString(welcomeMessage);
+ map["region_x"] = LLSD.FromInteger(RegionX * 256);
+ map["region_y"] = LLSD.FromInteger(RegionY * 256);
+
+ if (m_buddyList != null)
+ {
+ //map["buddy-list"] = m_buddyList.ToArray();
+ }
+
+ map["login"] = LLSD.FromString("true");
+
+ return map;
+ }
+ catch (Exception e)
+ {
+ MainLog.Instance.Warn(
+ "CLIENT",
+ "LoginResponse: Error creating XML-RPC Response: " + e.Message
+ );
+ return GenerateFailureResponseLLSD("Internal Error", "Error generating Login Response", "false");
+ }
+ }
+
+ private LLSDArray WrapLLSDMap(LLSDMap wrapMe)
+ {
+ LLSDArray array = new LLSDArray();
+ array.Add(wrapMe);
+ return array;
+ }
+
public void SetEventCategories(string category, string value)
{
// this.eventCategoriesHash[category] = value;
@@ -591,4 +750,4 @@ namespace OpenSim.Framework.UserManagement
}
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Framework/Communications/LoginService.cs b/OpenSim/Framework/Communications/LoginService.cs
index 0531d6a786..9cfac1c285 100644
--- a/OpenSim/Framework/Communications/LoginService.cs
+++ b/OpenSim/Framework/Communications/LoginService.cs
@@ -31,6 +31,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Threading;
using libsecondlife;
+using libsecondlife.StructuredData;
using Nwc.XmlRpc;
using OpenSim.Framework.Communications.Cache;
@@ -198,6 +199,132 @@ namespace OpenSim.Framework.UserManagement
}
}
+ public LLSD LLSDLoginMethod(LLSD request)
+ {
+ // Temporary fix
+ m_loginMutex.WaitOne();
+
+ try
+ {
+ bool GoodLogin = false;
+
+ UserProfileData userProfile = null;
+ LoginResponse logResponse = new LoginResponse();
+
+ if (request.Type == LLSDType.Map)
+ {
+ LLSDMap map = (LLSDMap)request;
+
+ if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd"))
+ {
+ string firstname = map["first"].AsString();
+ string lastname = map["last"].AsString();
+ string passwd = map["passwd"].AsString();
+
+ userProfile = GetTheUser(firstname, lastname);
+ if (userProfile == null)
+ {
+ MainLog.Instance.Verbose(
+ "LOGIN",
+ "Could not find a profile for " + firstname + " " + lastname);
+
+ return logResponse.CreateLoginFailedResponseLLSD();
+ }
+
+ GoodLogin = AuthenticateUser(userProfile, passwd);
+ }
+ }
+
+ if (!GoodLogin)
+ {
+ return logResponse.CreateLoginFailedResponseLLSD();
+ }
+ else
+ {
+ // If we already have a session...
+ if (userProfile.currentAgent != null && userProfile.currentAgent.agentOnline)
+ {
+ userProfile.currentAgent = null;
+ m_userManager.CommitAgent(ref userProfile);
+
+ // Reject the login
+ return logResponse.CreateAlreadyLoggedInResponseLLSD();
+ }
+
+ // Otherwise...
+ // Create a new agent session
+ CreateAgent(userProfile, request);
+
+ try
+ {
+ LLUUID agentID = userProfile.UUID;
+
+ // Inventory Library Section
+ InventoryData inventData = CreateInventoryData(agentID);
+ ArrayList AgentInventoryArray = inventData.InventoryArray;
+
+ Hashtable InventoryRootHash = new Hashtable();
+ InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
+ ArrayList InventoryRoot = new ArrayList();
+ InventoryRoot.Add(InventoryRootHash);
+ userProfile.rootInventoryFolderID = inventData.RootFolderID;
+
+ // Circuit Code
+ uint circode = (uint)(Util.RandomClass.Next());
+
+ logResponse.Lastname = userProfile.surname;
+ logResponse.Firstname = userProfile.username;
+ logResponse.AgentID = agentID.ToString();
+ logResponse.SessionID = userProfile.currentAgent.sessionID.ToString();
+ logResponse.SecureSessionID = userProfile.currentAgent.secureSessionID.ToString();
+ logResponse.InventoryRoot = InventoryRoot;
+ logResponse.InventorySkeleton = AgentInventoryArray;
+ logResponse.InventoryLibrary = GetInventoryLibrary();
+
+ Hashtable InventoryLibRootHash = new Hashtable();
+ InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
+ ArrayList InventoryLibRoot = new ArrayList();
+ InventoryLibRoot.Add(InventoryLibRootHash);
+ logResponse.InventoryLibRoot = InventoryLibRoot;
+
+ logResponse.InventoryLibraryOwner = GetLibraryOwner();
+ logResponse.CircuitCode = (Int32)circode;
+ //logResponse.RegionX = 0; //overwritten
+ //logResponse.RegionY = 0; //overwritten
+ logResponse.Home = "!!null temporary value {home}!!"; // Overwritten
+ //logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n";
+ //logResponse.SimAddress = "127.0.0.1"; //overwritten
+ //logResponse.SimPort = 0; //overwritten
+ logResponse.Message = GetMessage();
+ logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
+
+ try
+ {
+ CustomiseResponse(logResponse, userProfile);
+ }
+ catch (Exception ex)
+ {
+ MainLog.Instance.Verbose("LOGIN", ex.ToString());
+ return logResponse.CreateDeadRegionResponseLLSD();
+ }
+
+ CommitAgent(ref userProfile);
+
+ return logResponse.ToLLSDResponse();
+ }
+ catch (Exception ex)
+ {
+ MainLog.Instance.Verbose("LOGIN", ex.ToString());
+ return logResponse.CreateFailedResponseLLSD();
+ }
+ }
+ }
+ finally
+ {
+ m_loginMutex.ReleaseMutex();
+ }
+ }
+
///
/// Customises the login response and fills in missing values.
///
@@ -246,6 +373,11 @@ namespace OpenSim.Framework.UserManagement
m_userManager.CreateAgent(profile, request);
}
+ public void CreateAgent(UserProfileData profile, LLSD request)
+ {
+ m_userManager.CreateAgent(profile, request);
+ }
+
///
///
///
diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs
index 5d62e5ee47..bea56ea0e7 100644
--- a/OpenSim/Framework/Communications/UserManagerBase.cs
+++ b/OpenSim/Framework/Communications/UserManagerBase.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Security.Cryptography;
using libsecondlife;
+using libsecondlife.StructuredData;
using Nwc.XmlRpc;
using OpenSim.Framework.Console;
@@ -394,6 +395,41 @@ namespace OpenSim.Framework.UserManagement
profile.currentAgent = agent;
}
+ public void CreateAgent(UserProfileData profile, LLSD request)
+ {
+ UserAgentData agent = new UserAgentData();
+
+ // User connection
+ agent.agentOnline = true;
+
+ // Generate sessions
+ RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
+ byte[] randDataS = new byte[16];
+ byte[] randDataSS = new byte[16];
+ rand.GetBytes(randDataS);
+ rand.GetBytes(randDataSS);
+
+ agent.secureSessionID = new LLUUID(randDataSS, 0);
+ agent.sessionID = new LLUUID(randDataS, 0);
+
+ // Profile UUID
+ agent.UUID = profile.UUID;
+
+ // Current position (from Home)
+ agent.currentHandle = profile.homeRegion;
+ agent.currentPos = profile.homeLocation;
+
+ // What time did the user login?
+ agent.loginTime = Util.UnixTimeSinceEpoch();
+ agent.logoutTime = 0;
+
+ // Current location
+ agent.regionID = LLUUID.Zero; // Fill in later
+ agent.currentRegion = LLUUID.Zero; // Fill in later
+
+ profile.currentAgent = agent;
+ }
+
///
/// Saves a target agent to the database
///
@@ -445,4 +481,4 @@ namespace OpenSim.Framework.UserManagement
public abstract UserProfileData SetupMasterUser(string firstName, string lastName, string password);
public abstract UserProfileData SetupMasterUser(LLUUID uuid);
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs
index af2b27c9bc..b36cc8a7b1 100644
--- a/OpenSim/Framework/Servers/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/BaseHttpServer.cs
@@ -34,6 +34,7 @@ using System.Text;
using System.Threading;
using System.Xml;
using Nwc.XmlRpc;
+using libsecondlife.StructuredData;
using OpenSim.Framework.Console;
namespace OpenSim.Framework.Servers
@@ -43,6 +44,7 @@ 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_streamHandlers = new Dictionary();
protected uint m_port;
protected bool m_ssl = false;
@@ -90,6 +92,11 @@ namespace OpenSim.Framework.Servers
return false;
}
+ public bool SetLLSDHandler(LLSDMethod handler)
+ {
+ m_llsdHandler = handler;
+ return true;
+ }
public virtual void HandleRequest(Object stateinfo)
{
@@ -136,7 +143,17 @@ namespace OpenSim.Framework.Servers
}
else
{
- HandleXmlRpcRequests(request, response);
+ switch (request.ContentType)
+ {
+ //case "application/xml+llsd":
+ //HandleLLSDRequests(request, response);
+ //break;
+ case "text/xml":
+ case "application/xml":
+ default:
+ HandleXmlRpcRequests(request, response);
+ break;
+ }
}
}
@@ -242,7 +259,7 @@ namespace OpenSim.Framework.Servers
}
}
- response.AddHeader("Content-type", "text/xml");
+ response.ContentType = "text/xml";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
@@ -263,6 +280,58 @@ namespace OpenSim.Framework.Servers
}
}
+ private void HandleLLSDRequests(HttpListenerRequest request, HttpListenerResponse response)
+ {
+ Stream requestStream = request.InputStream;
+
+ Encoding encoding = Encoding.UTF8;
+ StreamReader reader = new StreamReader(requestStream, encoding);
+
+ string requestBody = reader.ReadToEnd();
+ reader.Close();
+ requestStream.Close();
+
+ LLSD llsdRequest = null;
+ LLSD llsdResponse = null;
+
+ try { llsdRequest = LLSDParser.DeserializeXml(requestBody); }
+ catch (Exception ex) { MainLog.Instance.Warn("HTTPD", "Error - " + ex.Message); }
+
+ if (llsdRequest != null && m_llsdHandler != null)
+ {
+ llsdResponse = m_llsdHandler(llsdRequest);
+ }
+ 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;
+ }
+
+ response.ContentType = "application/xml+llsd";
+
+ byte[] buffer = LLSDParser.SerializeXmlBytes(llsdResponse);
+
+ response.SendChunked = false;
+ response.ContentLength64 = buffer.Length;
+ response.ContentEncoding = Encoding.UTF8;
+
+ try
+ {
+ response.OutputStream.Write(buffer, 0, buffer.Length);
+ }
+ catch (Exception ex)
+ {
+ MainLog.Instance.Warn("HTTPD", "Error - " + ex.Message);
+ }
+ finally
+ {
+ response.OutputStream.Close();
+ }
+ }
+
public void HandleHTTPRequest(Hashtable keysvals, HttpListenerRequest request, HttpListenerResponse response)
{
// This is a test. There's a workable alternative.. as this way sucks.
@@ -436,4 +505,4 @@ namespace OpenSim.Framework.Servers
m_streamHandlers.Remove(GetHandlerKey(httpMethod, path));
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Framework/Servers/LLSDMethod.cs b/OpenSim/Framework/Servers/LLSDMethod.cs
new file mode 100644
index 0000000000..5cd225b535
--- /dev/null
+++ b/OpenSim/Framework/Servers/LLSDMethod.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 LLSDMethod(LLSD request);
+}
diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs
index 4645c7e885..5264870ec9 100644
--- a/OpenSim/Grid/UserServer/Main.cs
+++ b/OpenSim/Grid/UserServer/Main.cs
@@ -97,6 +97,7 @@ namespace OpenSim.Grid.UserServer
BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort);
httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod);
+ httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod);
httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName);
httpServer.AddXmlRPCHandler("get_user_by_uuid", m_userManager.XmlRPCGetUserMethodUUID);
@@ -223,4 +224,4 @@ namespace OpenSim.Grid.UserServer
{
}
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs
index 0e8d71aeee..831db22ea2 100644
--- a/OpenSim/Region/Application/OpenSimMain.cs
+++ b/OpenSim/Region/Application/OpenSimMain.cs
@@ -312,6 +312,7 @@ namespace OpenSim
m_loginService.OnLoginToRegion += backendService.AddNewSession;
m_httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod);
+ m_httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod);
if (m_standaloneAuthenticate)
{