mirror of
https://github.com/opensim/opensim.git
synced 2026-08-07 01:35:46 +08:00
Merge branch 'master' into careminster-presence-refactor
This commit is contained in:
@@ -65,6 +65,10 @@ namespace OpenSim.Server.Base
|
||||
/// <returns></returns>
|
||||
public static T LoadPlugin<T>(string dllName, Object[] args) where T:class
|
||||
{
|
||||
// This is good to debug configuration problems
|
||||
//if (dllName == string.Empty)
|
||||
// Util.PrintCallStack();
|
||||
|
||||
string[] parts = dllName.Split(new char[] {':'});
|
||||
|
||||
dllName = parts[0];
|
||||
@@ -124,6 +128,13 @@ namespace OpenSim.Server.Base
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (ReflectionTypeLoadException rtle)
|
||||
{
|
||||
m_log.Error(string.Format("Error loading plugin from {0}:\n{1}", dllName,
|
||||
String.Join("\n", Array.ConvertAll(rtle.LoaderExceptions, e => e.ToString()))),
|
||||
rtle);
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("Error loading plugin from {0}", dllName), e);
|
||||
|
||||
@@ -46,14 +46,14 @@ namespace OpenSim.Server.Handlers.Friends
|
||||
if (serverConfig == null)
|
||||
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
||||
|
||||
string gridService = serverConfig.GetString("LocalServiceModule",
|
||||
string theService = serverConfig.GetString("LocalServiceModule",
|
||||
String.Empty);
|
||||
|
||||
if (gridService == String.Empty)
|
||||
if (theService == String.Empty)
|
||||
throw new Exception("No LocalServiceModule in config file");
|
||||
|
||||
Object[] args = new Object[] { config };
|
||||
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(gridService, args);
|
||||
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
|
||||
|
||||
server.AddStreamHandler(new FriendsServerPostHandler(m_FriendsService));
|
||||
}
|
||||
|
||||
@@ -82,12 +82,18 @@ namespace OpenSim.Server.Handlers.Friends
|
||||
case "getfriends":
|
||||
return GetFriends(request);
|
||||
|
||||
case "getfriends_string":
|
||||
return GetFriendsString(request);
|
||||
|
||||
case "storefriend":
|
||||
return StoreFriend(request);
|
||||
|
||||
case "deletefriend":
|
||||
return DeleteFriend(request);
|
||||
|
||||
case "deletefriend_string":
|
||||
return DeleteFriendString(request);
|
||||
|
||||
}
|
||||
m_log.DebugFormat("[FRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
|
||||
}
|
||||
@@ -111,7 +117,25 @@ namespace OpenSim.Server.Handlers.Friends
|
||||
m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends");
|
||||
|
||||
FriendInfo[] finfos = m_FriendsService.GetFriends(principalID);
|
||||
//m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count);
|
||||
|
||||
return PackageFriends(finfos);
|
||||
}
|
||||
|
||||
byte[] GetFriendsString(Dictionary<string, object> request)
|
||||
{
|
||||
string principalID = string.Empty;
|
||||
if (request.ContainsKey("PRINCIPALID"))
|
||||
principalID = request["PRINCIPALID"].ToString();
|
||||
else
|
||||
m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends");
|
||||
|
||||
FriendInfo[] finfos = m_FriendsService.GetFriends(principalID);
|
||||
|
||||
return PackageFriends(finfos);
|
||||
}
|
||||
|
||||
private byte[] PackageFriends(FriendInfo[] finfos)
|
||||
{
|
||||
|
||||
Dictionary<string, object> result = new Dictionary<string, object>();
|
||||
if ((finfos == null) || ((finfos != null) && (finfos.Length == 0)))
|
||||
@@ -136,9 +160,9 @@ namespace OpenSim.Server.Handlers.Friends
|
||||
|
||||
byte[] StoreFriend(Dictionary<string, object> request)
|
||||
{
|
||||
FriendInfo friend = new FriendInfo(request);
|
||||
|
||||
bool success = m_FriendsService.StoreFriend(friend.PrincipalID, friend.Friend, friend.MyFlags);
|
||||
string principalID = string.Empty, friend = string.Empty; int flags = 0;
|
||||
FromKeyValuePairs(request, out principalID, out friend, out flags);
|
||||
bool success = m_FriendsService.StoreFriend(principalID, friend, flags);
|
||||
|
||||
if (success)
|
||||
return SuccessResult();
|
||||
@@ -163,7 +187,25 @@ namespace OpenSim.Server.Handlers.Friends
|
||||
else
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
|
||||
byte[] DeleteFriendString(Dictionary<string, object> request)
|
||||
{
|
||||
string principalID = string.Empty;
|
||||
if (request.ContainsKey("PRINCIPALID"))
|
||||
principalID = request["PRINCIPALID"].ToString();
|
||||
else
|
||||
m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to delete friend");
|
||||
string friend = string.Empty;
|
||||
if (request.ContainsKey("FRIEND"))
|
||||
friend = request["FRIEND"].ToString();
|
||||
|
||||
bool success = m_FriendsService.Delete(principalID, friend);
|
||||
if (success)
|
||||
return SuccessResult();
|
||||
else
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
@@ -233,6 +275,19 @@ namespace OpenSim.Server.Handlers.Friends
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
void FromKeyValuePairs(Dictionary<string, object> kvp, out string principalID, out string friend, out int flags)
|
||||
{
|
||||
principalID = string.Empty;
|
||||
if (kvp.ContainsKey("PrincipalID") && kvp["PrincipalID"] != null)
|
||||
principalID = kvp["PrincipalID"].ToString();
|
||||
friend = string.Empty;
|
||||
if (kvp.ContainsKey("Friend") && kvp["Friend"] != null)
|
||||
friend = kvp["Friend"].ToString();
|
||||
flags = 0;
|
||||
if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null)
|
||||
Int32.TryParse(kvp["MyFlags"].ToString(), out flags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
71
OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs
Normal file
71
OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 Nini.Config;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Server.Handlers.Base;
|
||||
|
||||
namespace OpenSim.Server.Handlers.Hypergrid
|
||||
{
|
||||
public class HGFriendsServerConnector : ServiceConnector
|
||||
{
|
||||
private IFriendsService m_FriendsService;
|
||||
private IUserAgentService m_UserAgentService;
|
||||
private string m_ConfigName = "HGFriendsService";
|
||||
|
||||
public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||
base(config, server, configName)
|
||||
{
|
||||
if (configName != string.Empty)
|
||||
m_ConfigName = configName;
|
||||
|
||||
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||
if (serverConfig == null)
|
||||
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
||||
|
||||
string theService = serverConfig.GetString("LocalServiceModule",
|
||||
String.Empty);
|
||||
|
||||
if (theService == String.Empty)
|
||||
throw new Exception("No LocalServiceModule in config file");
|
||||
|
||||
Object[] args = new Object[] { config };
|
||||
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
|
||||
|
||||
theService = serverConfig.GetString("UserAgentService", string.Empty);
|
||||
if (theService == String.Empty)
|
||||
throw new Exception("No UserAgentService in " + m_ConfigName);
|
||||
|
||||
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(theService, args);
|
||||
|
||||
server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService));
|
||||
}
|
||||
}
|
||||
}
|
||||
320
OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
Normal file
320
OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* 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 Nini.Config;
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Server.Handlers.Hypergrid
|
||||
{
|
||||
public class HGFriendsServerPostHandler : BaseStreamHandler
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private IFriendsService m_FriendsService;
|
||||
private IUserAgentService m_UserAgentService;
|
||||
|
||||
public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) :
|
||||
base("POST", "/hgfriends")
|
||||
{
|
||||
m_FriendsService = service;
|
||||
m_UserAgentService = uservice;
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On");
|
||||
}
|
||||
|
||||
public override byte[] Handle(string path, Stream requestData,
|
||||
OSHttpRequest httpRequest, OSHttpResponse httpResponse)
|
||||
{
|
||||
StreamReader sr = new StreamReader(requestData);
|
||||
string body = sr.ReadToEnd();
|
||||
sr.Close();
|
||||
body = body.Trim();
|
||||
|
||||
//m_log.DebugFormat("[XXX]: query String: {0}", body);
|
||||
|
||||
try
|
||||
{
|
||||
Dictionary<string, object> request =
|
||||
ServerUtils.ParseQueryString(body);
|
||||
|
||||
if (!request.ContainsKey("METHOD"))
|
||||
return FailureResult();
|
||||
|
||||
string method = request["METHOD"].ToString();
|
||||
|
||||
switch (method)
|
||||
{
|
||||
case "getfriendperms":
|
||||
return GetFriendPerms(request);
|
||||
|
||||
case "newfriendship":
|
||||
return NewFriendship(request);
|
||||
|
||||
case "deletefriendship":
|
||||
return DeleteFriendship(request);
|
||||
}
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: Exception {0}", e);
|
||||
}
|
||||
|
||||
return FailureResult();
|
||||
|
||||
}
|
||||
|
||||
#region Method-specific handlers
|
||||
|
||||
byte[] GetFriendPerms(Dictionary<string, object> request)
|
||||
{
|
||||
if (!VerifyServiceKey(request))
|
||||
return FailureResult();
|
||||
|
||||
UUID principalID = UUID.Zero;
|
||||
if (request.ContainsKey("PRINCIPALID"))
|
||||
UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID);
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms");
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
UUID friendID = UUID.Zero;
|
||||
if (request.ContainsKey("FRIENDID"))
|
||||
UUID.TryParse(request["FRIENDID"].ToString(), out friendID);
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms");
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
string perms = "0";
|
||||
FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID);
|
||||
foreach (FriendInfo finfo in friendsInfo)
|
||||
{
|
||||
if (finfo.Friend.StartsWith(friendID.ToString()))
|
||||
return SuccessResult(finfo.TheirFlags.ToString());
|
||||
}
|
||||
|
||||
return FailureResult("Friend not found");
|
||||
}
|
||||
|
||||
byte[] NewFriendship(Dictionary<string, object> request)
|
||||
{
|
||||
if (!VerifyServiceKey(request))
|
||||
return FailureResult();
|
||||
|
||||
// OK, can proceed
|
||||
FriendInfo friend = new FriendInfo(request);
|
||||
UUID friendID;
|
||||
string tmp = string.Empty;
|
||||
if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
|
||||
return FailureResult();
|
||||
|
||||
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend);
|
||||
|
||||
// If the friendship already exists, return fail
|
||||
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
|
||||
foreach (FriendInfo finfo in finfos)
|
||||
if (finfo.Friend.StartsWith(friendID.ToString()))
|
||||
return FailureResult();
|
||||
|
||||
// the user needs to confirm when he gets home
|
||||
bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0);
|
||||
|
||||
if (success)
|
||||
return SuccessResult();
|
||||
else
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
byte[] DeleteFriendship(Dictionary<string, object> request)
|
||||
{
|
||||
FriendInfo friend = new FriendInfo(request);
|
||||
string secret = string.Empty;
|
||||
if (request.ContainsKey("SECRET"))
|
||||
secret = request["SECRET"].ToString();
|
||||
|
||||
if (secret == string.Empty)
|
||||
return FailureResult();
|
||||
|
||||
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
|
||||
foreach (FriendInfo finfo in finfos)
|
||||
{
|
||||
// We check the secret here
|
||||
if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret))
|
||||
{
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend);
|
||||
m_FriendsService.Delete(friend.PrincipalID, finfo.Friend);
|
||||
m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString());
|
||||
|
||||
return SuccessResult();
|
||||
}
|
||||
}
|
||||
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
|
||||
private bool VerifyServiceKey(Dictionary<string, object> request)
|
||||
{
|
||||
if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID"))
|
||||
{
|
||||
m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID");
|
||||
return false;
|
||||
}
|
||||
|
||||
string serviceKey = request["KEY"].ToString();
|
||||
string sessionStr = request["SESSIONID"].ToString();
|
||||
UUID sessionID;
|
||||
UUID.TryParse(sessionStr, out sessionID);
|
||||
|
||||
if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey))
|
||||
{
|
||||
m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: Verification ok");
|
||||
return true;
|
||||
}
|
||||
|
||||
private byte[] SuccessResult()
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
|
||||
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||
"", "");
|
||||
|
||||
doc.AppendChild(xmlnode);
|
||||
|
||||
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
|
||||
"");
|
||||
|
||||
doc.AppendChild(rootElement);
|
||||
|
||||
XmlElement result = doc.CreateElement("", "Result", "");
|
||||
result.AppendChild(doc.CreateTextNode("Success"));
|
||||
|
||||
rootElement.AppendChild(result);
|
||||
|
||||
return DocToBytes(doc);
|
||||
}
|
||||
|
||||
private byte[] SuccessResult(string value)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
|
||||
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||
"", "");
|
||||
|
||||
doc.AppendChild(xmlnode);
|
||||
|
||||
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
|
||||
"");
|
||||
|
||||
doc.AppendChild(rootElement);
|
||||
|
||||
XmlElement result = doc.CreateElement("", "Result", "");
|
||||
result.AppendChild(doc.CreateTextNode("Success"));
|
||||
|
||||
rootElement.AppendChild(result);
|
||||
|
||||
XmlElement message = doc.CreateElement("", "Value", "");
|
||||
message.AppendChild(doc.CreateTextNode(value));
|
||||
|
||||
rootElement.AppendChild(message);
|
||||
|
||||
return DocToBytes(doc);
|
||||
}
|
||||
|
||||
|
||||
private byte[] FailureResult()
|
||||
{
|
||||
return FailureResult(String.Empty);
|
||||
}
|
||||
|
||||
private byte[] FailureResult(string msg)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
|
||||
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||
"", "");
|
||||
|
||||
doc.AppendChild(xmlnode);
|
||||
|
||||
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
|
||||
"");
|
||||
|
||||
doc.AppendChild(rootElement);
|
||||
|
||||
XmlElement result = doc.CreateElement("", "Result", "");
|
||||
result.AppendChild(doc.CreateTextNode("Failure"));
|
||||
|
||||
rootElement.AppendChild(result);
|
||||
|
||||
XmlElement message = doc.CreateElement("", "Message", "");
|
||||
message.AppendChild(doc.CreateTextNode(msg));
|
||||
|
||||
rootElement.AppendChild(message);
|
||||
|
||||
return DocToBytes(doc);
|
||||
}
|
||||
|
||||
private byte[] DocToBytes(XmlDocument doc)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream();
|
||||
XmlTextWriter xw = new XmlTextWriter(ms, null);
|
||||
xw.Formatting = Formatting.Indented;
|
||||
doc.WriteTo(xw);
|
||||
xw.Flush();
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
|
||||
using Nini.Config;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Server.Base;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using OpenSim.Framework.Servers.HttpServer;
|
||||
using OpenSim.Server.Handlers.Base;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
||||
using log4net;
|
||||
using Nwc.XmlRpc;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Server.Handlers.Hypergrid
|
||||
{
|
||||
public class InstantMessageServerConnector : ServiceConnector
|
||||
{
|
||||
private static readonly ILog m_log =
|
||||
LogManager.GetLogger(
|
||||
MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private IInstantMessage m_IMService;
|
||||
|
||||
public InstantMessageServerConnector(IConfigSource config, IHttpServer server) :
|
||||
this(config, server, null)
|
||||
{
|
||||
}
|
||||
|
||||
public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) :
|
||||
base(config, server, String.Empty)
|
||||
{
|
||||
IConfig gridConfig = config.Configs["HGInstantMessageService"];
|
||||
if (gridConfig != null)
|
||||
{
|
||||
string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty);
|
||||
|
||||
Object[] args = new Object[] { config, simConnector };
|
||||
m_IMService = ServerUtils.LoadPlugin<IInstantMessage>(serviceDll, args);
|
||||
}
|
||||
if (m_IMService == null)
|
||||
throw new Exception("InstantMessage server connector cannot proceed because of missing service");
|
||||
|
||||
server.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false);
|
||||
|
||||
}
|
||||
|
||||
public IInstantMessage GetService()
|
||||
{
|
||||
return m_IMService;
|
||||
}
|
||||
|
||||
protected virtual XmlRpcResponse ProcessInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
bool successful = false;
|
||||
|
||||
try
|
||||
{
|
||||
// various rational defaults
|
||||
UUID fromAgentID = UUID.Zero;
|
||||
UUID toAgentID = UUID.Zero;
|
||||
UUID imSessionID = UUID.Zero;
|
||||
uint timestamp = 0;
|
||||
string fromAgentName = "";
|
||||
string message = "";
|
||||
byte dialog = (byte)0;
|
||||
bool fromGroup = false;
|
||||
byte offline = (byte)0;
|
||||
uint ParentEstateID = 0;
|
||||
Vector3 Position = Vector3.Zero;
|
||||
UUID RegionID = UUID.Zero;
|
||||
byte[] binaryBucket = new byte[0];
|
||||
|
||||
float pos_x = 0;
|
||||
float pos_y = 0;
|
||||
float pos_z = 0;
|
||||
//m_log.Info("Processing IM");
|
||||
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
// Check if it's got all the data
|
||||
if (requestData.ContainsKey("from_agent_id")
|
||||
&& requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id")
|
||||
&& requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name")
|
||||
&& requestData.ContainsKey("message") && requestData.ContainsKey("dialog")
|
||||
&& requestData.ContainsKey("from_group")
|
||||
&& requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id")
|
||||
&& requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y")
|
||||
&& requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
|
||||
&& requestData.ContainsKey("binary_bucket"))
|
||||
{
|
||||
// Do the easy way of validating the UUIDs
|
||||
UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
|
||||
UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
|
||||
UUID.TryParse((string)requestData["im_session_id"], out imSessionID);
|
||||
UUID.TryParse((string)requestData["region_id"], out RegionID);
|
||||
try
|
||||
{
|
||||
timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
}
|
||||
|
||||
fromAgentName = (string)requestData["from_agent_name"];
|
||||
message = (string)requestData["message"];
|
||||
if (message == null)
|
||||
message = string.Empty;
|
||||
|
||||
// Bytes don't transfer well over XMLRPC, so, we Base64 Encode them.
|
||||
string requestData1 = (string)requestData["dialog"];
|
||||
if (string.IsNullOrEmpty(requestData1))
|
||||
{
|
||||
dialog = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] dialogdata = Convert.FromBase64String(requestData1);
|
||||
dialog = dialogdata[0];
|
||||
}
|
||||
|
||||
if ((string)requestData["from_group"] == "TRUE")
|
||||
fromGroup = true;
|
||||
|
||||
string requestData2 = (string)requestData["offline"];
|
||||
if (String.IsNullOrEmpty(requestData2))
|
||||
{
|
||||
offline = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] offlinedata = Convert.FromBase64String(requestData2);
|
||||
offline = offlinedata[0];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
}
|
||||
|
||||
float.TryParse((string)requestData["position_x"], out pos_x);
|
||||
float.TryParse((string)requestData["position_y"], out pos_y);
|
||||
float.TryParse((string)requestData["position_z"], out pos_z);
|
||||
|
||||
Position = new Vector3(pos_x, pos_y, pos_z);
|
||||
|
||||
string requestData3 = (string)requestData["binary_bucket"];
|
||||
if (string.IsNullOrEmpty(requestData3))
|
||||
{
|
||||
binaryBucket = new byte[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
binaryBucket = Convert.FromBase64String(requestData3);
|
||||
}
|
||||
|
||||
// Create a New GridInstantMessageObject the the data
|
||||
GridInstantMessage gim = new GridInstantMessage();
|
||||
gim.fromAgentID = fromAgentID.Guid;
|
||||
gim.fromAgentName = fromAgentName;
|
||||
gim.fromGroup = fromGroup;
|
||||
gim.imSessionID = imSessionID.Guid;
|
||||
gim.RegionID = RegionID.Guid;
|
||||
gim.timestamp = timestamp;
|
||||
gim.toAgentID = toAgentID.Guid;
|
||||
gim.message = message;
|
||||
gim.dialog = dialog;
|
||||
gim.offline = offline;
|
||||
gim.ParentEstateID = ParentEstateID;
|
||||
gim.Position = Position;
|
||||
gim.binaryBucket = binaryBucket;
|
||||
|
||||
successful = m_IMService.IncomingInstantMessage(gim);
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e);
|
||||
successful = false;
|
||||
}
|
||||
|
||||
//Send response back to region calling if it was successful
|
||||
// calling region uses this to know when to look up a user's location again.
|
||||
XmlRpcResponse resp = new XmlRpcResponse();
|
||||
Hashtable respdata = new Hashtable();
|
||||
if (successful)
|
||||
respdata["success"] = "TRUE";
|
||||
else
|
||||
respdata["success"] = "FALSE";
|
||||
resp.Value = respdata;
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -52,15 +52,24 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private IUserAgentService m_HomeUsersService;
|
||||
private string[] m_AuthorizedCallers;
|
||||
|
||||
private bool m_VerifyCallers = false;
|
||||
|
||||
public UserAgentServerConnector(IConfigSource config, IHttpServer server) :
|
||||
this(config, server, null)
|
||||
{
|
||||
}
|
||||
|
||||
public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) :
|
||||
base(config, server, String.Empty)
|
||||
{
|
||||
IConfig gridConfig = config.Configs["UserAgentService"];
|
||||
if (gridConfig != null)
|
||||
{
|
||||
string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty);
|
||||
Object[] args = new Object[] { config };
|
||||
|
||||
Object[] args = new Object[] { config, friendsConnector };
|
||||
m_HomeUsersService = ServerUtils.LoadPlugin<IUserAgentService>(serviceDll, args);
|
||||
}
|
||||
if (m_HomeUsersService == null)
|
||||
@@ -69,12 +78,24 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||
string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1");
|
||||
bool proxy = gridConfig.GetBoolean("HasProxy", false);
|
||||
|
||||
m_VerifyCallers = gridConfig.GetBoolean("VerifyCallers", false);
|
||||
string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1");
|
||||
csv = csv.Replace(" ", "");
|
||||
m_AuthorizedCallers = csv.Split(',');
|
||||
|
||||
server.AddXmlRPCHandler("agent_is_coming_home", AgentIsComingHome, false);
|
||||
server.AddXmlRPCHandler("get_home_region", GetHomeRegion, false);
|
||||
server.AddXmlRPCHandler("verify_agent", VerifyAgent, false);
|
||||
server.AddXmlRPCHandler("verify_client", VerifyClient, false);
|
||||
server.AddXmlRPCHandler("logout_agent", LogoutAgent, false);
|
||||
|
||||
server.AddXmlRPCHandler("status_notification", StatusNotification, false);
|
||||
server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false);
|
||||
server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false);
|
||||
|
||||
server.AddXmlRPCHandler("locate_user", LocateUser, false);
|
||||
server.AddXmlRPCHandler("get_uui", GetUUI, false);
|
||||
|
||||
server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler);
|
||||
}
|
||||
|
||||
@@ -194,5 +215,201 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||
|
||||
}
|
||||
|
||||
public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
hash["result"] = "false";
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID") && requestData.ContainsKey("online"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
List<string> ids = new List<string>();
|
||||
foreach (object key in requestData.Keys)
|
||||
{
|
||||
if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
|
||||
ids.Add(requestData[key].ToString());
|
||||
}
|
||||
bool online = false;
|
||||
bool.TryParse(requestData["online"].ToString(), out online);
|
||||
|
||||
// let's spawn a thread for this, because it may take a long time...
|
||||
List<UUID> friendsOnline = m_HomeUsersService.StatusNotification(ids, userID, online);
|
||||
if (friendsOnline.Count > 0)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (UUID id in friendsOnline)
|
||||
{
|
||||
hash["friend_" + i.ToString()] = id.ToString();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
hash["result"] = "No Friends Online";
|
||||
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
List<string> ids = new List<string>();
|
||||
foreach (object key in requestData.Keys)
|
||||
{
|
||||
if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
|
||||
ids.Add(requestData[key].ToString());
|
||||
}
|
||||
|
||||
//List<UUID> online = m_HomeUsersService.GetOnlineFriends(userID, ids);
|
||||
//if (online.Count > 0)
|
||||
//{
|
||||
// int i = 0;
|
||||
// foreach (UUID id in online)
|
||||
// {
|
||||
// hash["friend_" + i.ToString()] = id.ToString();
|
||||
// i++;
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
// hash["result"] = "No Friends Online";
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
public XmlRpcResponse GetServerURLs(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
|
||||
Dictionary<string, object> serverURLs = m_HomeUsersService.GetServerURLs(userID);
|
||||
if (serverURLs.Count > 0)
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in serverURLs)
|
||||
hash["SRV_" + kvp.Key] = kvp.Value.ToString();
|
||||
}
|
||||
else
|
||||
hash["result"] = "No Service URLs";
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates the user.
|
||||
/// This is a sensitive operation, only authorized IP addresses can perform it.
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <returns></returns>
|
||||
public XmlRpcResponse LocateUser(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
|
||||
bool authorized = true;
|
||||
if (m_VerifyCallers)
|
||||
{
|
||||
authorized = false;
|
||||
foreach (string s in m_AuthorizedCallers)
|
||||
if (s == remoteClient.Address.ToString())
|
||||
{
|
||||
authorized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (authorized)
|
||||
{
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
|
||||
string url = m_HomeUsersService.LocateUser(userID);
|
||||
if (url != string.Empty)
|
||||
hash["URL"] = url;
|
||||
else
|
||||
hash["result"] = "Unable to locate user";
|
||||
}
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates the user.
|
||||
/// This is a sensitive operation, only authorized IP addresses can perform it.
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="remoteClient"></param>
|
||||
/// <returns></returns>
|
||||
public XmlRpcResponse GetUUI(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID") && requestData.ContainsKey("targetUserID"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
|
||||
string tuserID_str = (string)requestData["targetUserID"];
|
||||
UUID targetUserID = UUID.Zero;
|
||||
UUID.TryParse(tuserID_str, out targetUserID);
|
||||
string uui = m_HomeUsersService.GetUUI(userID, targetUserID);
|
||||
if (uui != string.Empty)
|
||||
hash["UUI"] = uui;
|
||||
else
|
||||
hash["result"] = "User unknown";
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user