aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Grid/GridServer/GridXmlRpcModule.cs
diff options
context:
space:
mode:
authorMW2009-02-21 13:44:03 +0000
committerMW2009-02-21 13:44:03 +0000
commit25661b611d241534e5e8d7ce1731de8506481a7d (patch)
treed61ae89bcb909225c6aef295bf6bddb21668b718 /OpenSim/Grid/GridServer/GridXmlRpcModule.cs
parentAllow entry of '?' in http URIs. If the field being typed begins with (diff)
downloadopensim-SC-25661b611d241534e5e8d7ce1731de8506481a7d.zip
opensim-SC-25661b611d241534e5e8d7ce1731de8506481a7d.tar.gz
opensim-SC-25661b611d241534e5e8d7ce1731de8506481a7d.tar.bz2
opensim-SC-25661b611d241534e5e8d7ce1731de8506481a7d.tar.xz
Refactored the GridServer into a GridDBService and a set of "modules".
Currently they aren't plugin modules as the support for dynamically loading them isn't complete.
Diffstat (limited to '')
-rw-r--r--OpenSim/Grid/GridServer/GridXmlRpcModule.cs (renamed from OpenSim/Grid/GridServer/GridManager.cs)2126
1 files changed, 844 insertions, 1282 deletions
diff --git a/OpenSim/Grid/GridServer/GridManager.cs b/OpenSim/Grid/GridServer/GridXmlRpcModule.cs
index 5dc186c..0eb7d1f 100644
--- a/OpenSim/Grid/GridServer/GridManager.cs
+++ b/OpenSim/Grid/GridServer/GridXmlRpcModule.cs
@@ -1,1282 +1,844 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the 12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Xml; 33using System.Xml;
34using log4net; 34using log4net;
35using Nwc.XmlRpc; 35using Nwc.XmlRpc;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenSim.Data; 37using OpenSim.Data;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Communications; 39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41 41
42namespace OpenSim.Grid.GridServer 42namespace OpenSim.Grid.GridServer
43{ 43{
44 public class GridManager 44 public class GridXmlRpcModule
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 private List<IGridDataPlugin> _plugins = new List<IGridDataPlugin>(); 48 private GridDBService m_gridDBService;
49 private List<ILogDataPlugin> _logplugins = new List<ILogDataPlugin>(); 49 private IGridCore m_gridCore;
50 50
51 // This is here so that the grid server can hand out MessageServer settings to regions on registration 51 protected GridConfig m_config;
52 private List<MessageServerInfo> _MessageServers = new List<MessageServerInfo>(); 52
53 53 /// <value>
54 public GridConfig Config; 54 /// Used to notify old regions as to which OpenSim version to upgrade to
55 55 /// </value>
56 /// <value> 56 private string m_opensimVersion;
57 /// Used to notify old regions as to which OpenSim version to upgrade to 57
58 /// </value> 58 protected BaseHttpServer m_httpServer;
59 private string m_opensimVersion; 59
60 60 /// <summary>
61 /// <summary> 61 /// Constructor
62 /// Constructor 62 /// </summary>
63 /// </summary> 63 /// <param name="opensimVersion">
64 /// <param name="opensimVersion"> 64 /// Used to notify old regions as to which OpenSim version to upgrade to
65 /// Used to notify old regions as to which OpenSim version to upgrade to 65 /// </param>
66 /// </param> 66 public GridXmlRpcModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config)
67 public GridManager(string opensimVersion) 67 {
68 { 68 m_opensimVersion = opensimVersion;
69 m_opensimVersion = opensimVersion; 69 m_gridDBService = gridDBService;
70 } 70 m_gridCore = gridCore;
71 71 m_config = config;
72 /// <summary> 72 m_httpServer = m_gridCore.GetHttpServer();
73 /// Adds a list of grid and log data plugins, as described by 73 }
74 /// `provider' and `connect', to `_plugins' and `_logplugins', 74
75 /// respectively. 75 public void Initialise()
76 /// </summary> 76 {
77 /// <param name="provider"> 77 m_httpServer.AddXmlRPCHandler("simulator_login", XmlRpcSimulatorLoginMethod);
78 /// The filename of the inventory server plugin DLL. 78 m_httpServer.AddXmlRPCHandler("simulator_data_request", XmlRpcSimulatorDataRequestMethod);
79 /// </param> 79 m_httpServer.AddXmlRPCHandler("simulator_after_region_moved", XmlRpcDeleteRegionMethod);
80 /// <param name="connect"> 80 m_httpServer.AddXmlRPCHandler("map_block", XmlRpcMapBlockMethod);
81 /// The connection string for the storage backend. 81 m_httpServer.AddXmlRPCHandler("search_for_region_by_name", XmlRpcSearchForRegionMethod);
82 /// </param> 82 }
83 public void AddPlugin(string provider, string connect) 83
84 { 84 /// <summary>
85 _plugins = DataPluginFactory.LoadDataPlugins<IGridDataPlugin>(provider, connect); 85 /// Returns a XML String containing a list of the neighbouring regions
86 _logplugins = DataPluginFactory.LoadDataPlugins<ILogDataPlugin>(provider, connect); 86 /// </summary>
87 } 87 /// <param name="reqhandle">The regionhandle for the center sim</param>
88 88 /// <returns>An XML string containing neighbour entities</returns>
89 /// <summary> 89 public string GetXMLNeighbours(ulong reqhandle)
90 /// Logs a piece of information to the database 90 {
91 /// </summary> 91 string response = String.Empty;
92 /// <param name="target">What you were operating on (in grid server, this will likely be the region UUIDs)</param> 92 RegionProfileData central_region = m_gridDBService.GetRegion(reqhandle);
93 /// <param name="method">Which method is being called?</param> 93 RegionProfileData neighbour;
94 /// <param name="args">What arguments are being passed?</param> 94 for (int x = -1; x < 2; x++)
95 /// <param name="priority">How high priority is this? 1 = Max, 6 = Verbose</param> 95 {
96 /// <param name="message">The message to log</param> 96 for (int y = -1; y < 2; y++)
97 private void logToDB(string target, string method, string args, int priority, string message) 97 {
98 { 98 if (
99 foreach (ILogDataPlugin plugin in _logplugins) 99 m_gridDBService.GetRegion(
100 { 100 Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize),
101 try 101 (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null)
102 { 102 {
103 plugin.saveLog("Gridserver", target, method, args, priority, message); 103 neighbour =
104 } 104 m_gridDBService.GetRegion(
105 catch (Exception) 105 Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize),
106 { 106 (uint)(central_region.regionLocY + y) * Constants.RegionSize));
107 m_log.Warn("[storage]: Unable to write log via " + plugin.Name); 107
108 } 108 response += "<neighbour>";
109 } 109 response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>";
110 } 110 response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>";
111 111 response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>";
112 /// <summary> 112 response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>";
113 /// Returns a region by argument 113 response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>";
114 /// </summary> 114 response += "</neighbour>";
115 /// <param name="uuid">A UUID key of the region to return</param> 115 }
116 /// <returns>A SimProfileData for the region</returns> 116 }
117 public RegionProfileData GetRegion(UUID uuid) 117 }
118 { 118 return response;
119 foreach (IGridDataPlugin plugin in _plugins) 119 }
120 { 120
121 try 121 /// <summary>
122 { 122 /// Checks that it's valid to replace the existing region data with new data
123 return plugin.GetProfileByUUID(uuid); 123 ///
124 } 124 /// Currently, this means ensure that the keys passed in by the new region
125 catch (Exception e) 125 /// match those in the original region. (XXX Is this correct? Shouldn't we simply check
126 { 126 /// against the keys in the current configuration?)
127 m_log.Warn("[storage]: GetRegion - " + e.Message); 127 /// </summary>
128 } 128 /// <param name="sim"></param>
129 } 129 /// <returns></returns>
130 return null; 130 protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim)
131 } 131 {
132 132 if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey))
133 /// <summary> 133 {
134 /// Returns a region by argument 134 throw new LoginException(
135 /// </summary> 135 String.Format(
136 /// <param name="uuid">A regionHandle of the region to return</param> 136 "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}"
137 /// <returns>A SimProfileData for the region</returns> 137 + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})",
138 public RegionProfileData GetRegion(ulong handle) 138 sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName,
139 { 139 sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey),
140 foreach (IGridDataPlugin plugin in _plugins) 140 "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys.");
141 { 141 }
142 try 142 }
143 { 143
144 return plugin.GetProfileByHandle(handle); 144 /// <summary>
145 } 145 /// Checks that the new region data is valid.
146 catch (Exception ex) 146 ///
147 { 147 /// Currently, this means checking that the keys passed in by the new region
148 m_log.Debug("[storage]: " + ex.Message); 148 /// match those in the grid server's configuration.
149 m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + plugin.Name); 149 /// </summary>
150 } 150 ///
151 } 151 /// <param name="sim"></param>
152 return null; 152 /// <exception cref="LoginException">Thrown if region login failed</exception>
153 } 153 protected virtual void ValidateNewRegionKeys(RegionProfileData sim)
154 154 {
155 /// <summary> 155 if (!(sim.regionRecvKey == m_config.SimSendKey && sim.regionSendKey == m_config.SimRecvKey))
156 /// Returns a region by argument 156 {
157 /// </summary> 157 throw new LoginException(
158 /// <param name="regionName">A partial regionName of the region to return</param> 158 String.Format(
159 /// <returns>A SimProfileData for the region</returns> 159 "Authentication failed when trying to login new region {0} at location {1} {2}"
160 public RegionProfileData GetRegion(string regionName) 160 + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})",
161 { 161 sim.regionName, sim.regionLocX, sim.regionLocY,
162 foreach (IGridDataPlugin plugin in _plugins) 162 sim.regionSendKey, m_config.SimRecvKey, sim.regionRecvKey, m_config.SimSendKey),
163 { 163 "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys.");
164 try 164 }
165 { 165 }
166 return plugin.GetProfileByString(regionName); 166
167 } 167 /// <summary>
168 catch 168 /// Check that a region's http uri is externally contactable.
169 { 169 /// </summary>
170 m_log.Warn("[storage]: Unable to find region " + regionName + " via " + plugin.Name); 170 /// <param name="sim"></param>
171 } 171 /// <exception cref="LoginException">Thrown if the region is not contactable</exception>
172 } 172 protected virtual void ValidateRegionContactable(RegionProfileData sim)
173 return null; 173 {
174 } 174 string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/");
175 175 string regionStatusResponse;
176 public List<RegionProfileData> GetRegions(uint xmin, uint ymin, uint xmax, uint ymax) 176
177 { 177 RestClient rc = new RestClient(regionStatusUrl);
178 List<RegionProfileData> regions = new List<RegionProfileData>(); 178 rc.RequestMethod = "GET";
179 179
180 foreach (IGridDataPlugin plugin in _plugins) 180 m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName);
181 { 181
182 try 182 try
183 { 183 {
184 regions.AddRange(plugin.GetProfilesInRange(xmin, ymin, xmax, ymax)); 184 Stream rs = rc.Request();
185 } 185 StreamReader sr = new StreamReader(rs);
186 catch 186 regionStatusResponse = sr.ReadToEnd();
187 { 187 sr.Close();
188 m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); 188 }
189 } 189 catch (Exception e)
190 } 190 {
191 191 throw new LoginException(
192 return regions; 192 String.Format("Region status request to {0} failed", regionStatusUrl),
193 } 193 String.Format(
194 194 "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service",
195 public List<RegionProfileData> GetRegions(string name, int maxNum) 195 regionStatusUrl),
196 { 196 e);
197 List<RegionProfileData> regions = new List<RegionProfileData>(); 197 }
198 foreach (IGridDataPlugin plugin in _plugins) 198
199 { 199 if (!regionStatusResponse.Equals("OK"))
200 try 200 {
201 { 201 throw new LoginException(
202 int num = maxNum - regions.Count; 202 String.Format(
203 List <RegionProfileData> profiles = plugin.GetRegionsByName(name, (uint)num); 203 "Region {0} at {1} returned status response {2} rather than {3}",
204 if (profiles != null) regions.AddRange(profiles); 204 sim.regionName, regionStatusUrl, regionStatusResponse, "OK"),
205 } 205 String.Format(
206 catch 206 "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status",
207 { 207 regionStatusResponse, "OK"));
208 m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); 208 }
209 } 209 }
210 } 210
211 211 /// <summary>
212 return regions; 212 /// Construct an XMLRPC error response
213 } 213 /// </summary>
214 214 /// <param name="error"></param>
215 /// <summary> 215 /// <returns></returns>
216 /// Returns a XML String containing a list of the neighbouring regions 216 public static XmlRpcResponse ErrorResponse(string error)
217 /// </summary> 217 {
218 /// <param name="reqhandle">The regionhandle for the center sim</param> 218 XmlRpcResponse errorResponse = new XmlRpcResponse();
219 /// <returns>An XML string containing neighbour entities</returns> 219 Hashtable errorResponseData = new Hashtable();
220 public string GetXMLNeighbours(ulong reqhandle) 220 errorResponse.Value = errorResponseData;
221 { 221 errorResponseData["error"] = error;
222 string response = String.Empty; 222 return errorResponse;
223 RegionProfileData central_region = GetRegion(reqhandle); 223 }
224 RegionProfileData neighbour; 224
225 for (int x = -1; x < 2; x++) 225 /// <summary>
226 { 226 /// Performed when a region connects to the grid server initially.
227 for (int y = -1; y < 2; y++) 227 /// </summary>
228 { 228 /// <param name="request">The XML RPC Request</param>
229 if ( 229 /// <returns>Startup parameters</returns>
230 GetRegion( 230 public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request)
231 Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), 231 {
232 (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) 232 RegionProfileData sim;
233 { 233 RegionProfileData existingSim;
234 neighbour = 234
235 GetRegion( 235 Hashtable requestData = (Hashtable)request.Params[0];
236 Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), 236 UUID uuid;
237 (uint)(central_region.regionLocY + y) * Constants.RegionSize)); 237
238 238 if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid))
239 response += "<neighbour>"; 239 {
240 response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>"; 240 m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response.");
241 response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>"; 241 return ErrorResponse("No UUID passed to grid server - unable to connect you");
242 response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>"; 242 }
243 response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>"; 243
244 response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>"; 244 try
245 response += "</neighbour>"; 245 {
246 } 246 sim = RegionFromRequest(requestData);
247 } 247 }
248 } 248 catch (FormatException e)
249 return response; 249 {
250 } 250 m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response.");
251 251 return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString());
252 /// <summary> 252 }
253 /// Checks that it's valid to replace the existing region data with new data 253
254 /// 254 m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName);
255 /// Currently, this means ensure that the keys passed in by the new region 255
256 /// match those in the original region. (XXX Is this correct? Shouldn't we simply check 256 if (!m_config.AllowRegionRegistration)
257 /// against the keys in the current configuration?) 257 {
258 /// </summary> 258 m_log.DebugFormat(
259 /// <param name="sim"></param> 259 "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}",
260 /// <returns></returns> 260 sim.regionName);
261 protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) 261
262 { 262 return ErrorResponse("This grid is currently not accepting region registrations.");
263 if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) 263 }
264 { 264
265 throw new LoginException( 265 int majorInterfaceVersion = 0;
266 String.Format( 266 if (requestData.ContainsKey("major_interface_version"))
267 "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" 267 int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion);
268 + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", 268
269 sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, 269 if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion)
270 sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), 270 {
271 "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); 271 return ErrorResponse(
272 } 272 String.Format(
273 } 273 "Your region service implements OGS1 interface version {0}"
274 274 + " but this grid requires that the region implement OGS1 interface version {1} to connect."
275 /// <summary> 275 + " Try changing to OpenSimulator {2}",
276 /// Checks that the new region data is valid. 276 majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion));
277 /// 277 }
278 /// Currently, this means checking that the keys passed in by the new region 278
279 /// match those in the grid server's configuration. 279 existingSim = m_gridDBService.GetRegion(sim.regionHandle);
280 /// </summary> 280
281 /// 281 if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID)
282 /// <param name="sim"></param> 282 {
283 /// <exception cref="LoginException">Thrown if region login failed</exception> 283 try
284 protected virtual void ValidateNewRegionKeys(RegionProfileData sim) 284 {
285 { 285 if (existingSim == null)
286 if (!(sim.regionRecvKey == Config.SimSendKey && sim.regionSendKey == Config.SimRecvKey)) 286 {
287 { 287 ValidateNewRegionKeys(sim);
288 throw new LoginException( 288 }
289 String.Format( 289 else
290 "Authentication failed when trying to login new region {0} at location {1} {2}" 290 {
291 + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", 291 ValidateOverwriteKeys(sim, existingSim);
292 sim.regionName, sim.regionLocX, sim.regionLocY, 292 }
293 sim.regionSendKey, Config.SimRecvKey, sim.regionRecvKey, Config.SimSendKey), 293
294 "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); 294 ValidateRegionContactable(sim);
295 } 295 }
296 } 296 catch (LoginException e)
297 297 {
298 /// <summary> 298 string logMsg = e.Message;
299 /// Check that a region's http uri is externally contactable. 299 if (e.InnerException != null)
300 /// </summary> 300 logMsg += ", " + e.InnerException.Message;
301 /// <param name="sim"></param> 301
302 /// <exception cref="LoginException">Thrown if the region is not contactable</exception> 302 m_log.WarnFormat("[LOGIN END]: {0}", logMsg);
303 protected virtual void ValidateRegionContactable(RegionProfileData sim) 303
304 { 304 return e.XmlRpcErrorResponse;
305 string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); 305 }
306 string regionStatusResponse; 306
307 307 m_gridDBService.LoginRegion(sim, existingSim);
308 RestClient rc = new RestClient(regionStatusUrl); 308
309 rc.RequestMethod = "GET"; 309 XmlRpcResponse response = CreateLoginResponse(sim);
310 310
311 m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); 311 return response;
312 312 }
313 try 313 else
314 { 314 {
315 Stream rs = rc.Request(); 315 m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName);
316 StreamReader sr = new StreamReader(rs); 316 return ErrorResponse("Another region already exists at that location. Please try another.");
317 regionStatusResponse = sr.ReadToEnd(); 317 }
318 sr.Close(); 318 }
319 } 319
320 catch (Exception e) 320 /// <summary>
321 { 321 /// Construct a successful response to a simulator's login attempt.
322 throw new LoginException( 322 /// </summary>
323 String.Format("Region status request to {0} failed", regionStatusUrl), 323 /// <param name="sim"></param>
324 String.Format( 324 /// <returns></returns>
325 "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", 325 private XmlRpcResponse CreateLoginResponse(RegionProfileData sim)
326 regionStatusUrl), 326 {
327 e); 327 XmlRpcResponse response = new XmlRpcResponse();
328 } 328 Hashtable responseData = new Hashtable();
329 329 response.Value = responseData;
330 if (!regionStatusResponse.Equals("OK")) 330
331 { 331 ArrayList SimNeighboursData = GetSimNeighboursData(sim);
332 throw new LoginException( 332
333 String.Format( 333 responseData["UUID"] = sim.UUID.ToString();
334 "Region {0} at {1} returned status response {2} rather than {3}", 334 responseData["region_locx"] = sim.regionLocX.ToString();
335 sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), 335 responseData["region_locy"] = sim.regionLocY.ToString();
336 String.Format( 336 responseData["regionname"] = sim.regionName;
337 "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", 337 responseData["estate_id"] = "1";
338 regionStatusResponse, "OK")); 338 responseData["neighbours"] = SimNeighboursData;
339 } 339
340 } 340 responseData["sim_ip"] = sim.serverIP;
341 341 responseData["sim_port"] = sim.serverPort.ToString();
342 /// <summary> 342 responseData["asset_url"] = sim.regionAssetURI;
343 /// Construct an XMLRPC error response 343 responseData["asset_sendkey"] = sim.regionAssetSendKey;
344 /// </summary> 344 responseData["asset_recvkey"] = sim.regionAssetRecvKey;
345 /// <param name="error"></param> 345 responseData["user_url"] = sim.regionUserURI;
346 /// <returns></returns> 346 responseData["user_sendkey"] = sim.regionUserSendKey;
347 public static XmlRpcResponse ErrorResponse(string error) 347 responseData["user_recvkey"] = sim.regionUserRecvKey;
348 { 348 responseData["authkey"] = sim.regionSecret;
349 XmlRpcResponse errorResponse = new XmlRpcResponse(); 349
350 Hashtable errorResponseData = new Hashtable(); 350 // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap)
351 errorResponse.Value = errorResponseData; 351 responseData["data_uri"] = sim.regionDataURI;
352 errorResponseData["error"] = error; 352
353 return errorResponse; 353 responseData["allow_forceful_banlines"] = m_config.AllowForcefulBanlines;
354 } 354
355 355 // Instead of sending a multitude of message servers to the registering sim
356 /// <summary> 356 // we should probably be sending a single one and parhaps it's backup
357 /// Performed when a region connects to the grid server initially. 357 // that has responsibility over routing it's messages.
358 /// </summary> 358
359 /// <param name="request">The XML RPC Request</param> 359 // The Sim won't be contacting us again about any of the message server stuff during it's time up.
360 /// <returns>Startup parameters</returns> 360
361 public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) 361 responseData["messageserver_count"] = 0;
362 { 362
363 RegionProfileData sim; 363 IGridMessagingModule messagingModule;
364 RegionProfileData existingSim; 364 if (m_gridCore.TryGet<IGridMessagingModule>(out messagingModule))
365 365 {
366 Hashtable requestData = (Hashtable)request.Params[0]; 366 List<MessageServerInfo> messageServers = messagingModule.MessageServers;
367 UUID uuid; 367 responseData["messageserver_count"] = messageServers.Count;
368 368
369 if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) 369 for (int i = 0; i < messageServers.Count; i++)
370 { 370 {
371 m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); 371 responseData["messageserver_uri" + i] = messageServers[i].URI;
372 return ErrorResponse("No UUID passed to grid server - unable to connect you"); 372 responseData["messageserver_sendkey" + i] = messageServers[i].sendkey;
373 } 373 responseData["messageserver_recvkey" + i] = messageServers[i].recvkey;
374 374 }
375 try 375 }
376 { 376 return response;
377 sim = RegionFromRequest(requestData); 377 }
378 } 378
379 catch (FormatException e) 379 private ArrayList GetSimNeighboursData(RegionProfileData sim)
380 { 380 {
381 m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); 381 ArrayList SimNeighboursData = new ArrayList();
382 return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); 382
383 } 383 RegionProfileData neighbour;
384 384 Hashtable NeighbourBlock;
385 m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); 385
386 386 //First use the fast method. (not implemented in SQLLite)
387 if (!Config.AllowRegionRegistration) 387 List<RegionProfileData> neighbours = m_gridDBService.GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1);
388 { 388
389 m_log.DebugFormat( 389 if (neighbours.Count > 0)
390 "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", 390 {
391 sim.regionName); 391 foreach (RegionProfileData aSim in neighbours)
392 392 {
393 return ErrorResponse("This grid is currently not accepting region registrations."); 393 NeighbourBlock = new Hashtable();
394 } 394 NeighbourBlock["sim_ip"] = aSim.serverIP;
395 395 NeighbourBlock["sim_port"] = aSim.serverPort.ToString();
396 int majorInterfaceVersion = 0; 396 NeighbourBlock["region_locx"] = aSim.regionLocX.ToString();
397 if (requestData.ContainsKey("major_interface_version")) 397 NeighbourBlock["region_locy"] = aSim.regionLocY.ToString();
398 int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); 398 NeighbourBlock["UUID"] = aSim.ToString();
399 399 NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString();
400 if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) 400
401 { 401 if (aSim.UUID != sim.UUID)
402 return ErrorResponse( 402 {
403 String.Format( 403 SimNeighboursData.Add(NeighbourBlock);
404 "Your region service implements OGS1 interface version {0}" 404 }
405 + " but this grid requires that the region implement OGS1 interface version {1} to connect." 405 }
406 + " Try changing to OpenSimulator {2}", 406 }
407 majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); 407 else
408 } 408 {
409 409 for (int x = -1; x < 2; x++)
410 existingSim = GetRegion(sim.regionHandle); 410 {
411 411 for (int y = -1; y < 2; y++)
412 if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) 412 {
413 { 413 if (
414 try 414 m_gridDBService.GetRegion(
415 { 415 Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize),
416 if (existingSim == null) 416 (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null)
417 { 417 {
418 ValidateNewRegionKeys(sim); 418 neighbour =
419 } 419 m_gridDBService.GetRegion(
420 else 420 Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize),
421 { 421 (uint)(sim.regionLocY + y) * Constants.RegionSize));
422 ValidateOverwriteKeys(sim, existingSim); 422
423 } 423 NeighbourBlock = new Hashtable();
424 424 NeighbourBlock["sim_ip"] = neighbour.serverIP;
425 ValidateRegionContactable(sim); 425 NeighbourBlock["sim_port"] = neighbour.serverPort.ToString();
426 } 426 NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString();
427 catch (LoginException e) 427 NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString();
428 { 428 NeighbourBlock["UUID"] = neighbour.UUID.ToString();
429 string logMsg = e.Message; 429 NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString();
430 if (e.InnerException != null) 430
431 logMsg += ", " + e.InnerException.Message; 431 if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock);
432 432 }
433 m_log.WarnFormat("[LOGIN END]: {0}", logMsg); 433 }
434 434 }
435 return e.XmlRpcErrorResponse; 435 }
436 } 436 return SimNeighboursData;
437 437 }
438 foreach (IGridDataPlugin plugin in _plugins) 438
439 { 439 /// <summary>
440 try 440 /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region
441 { 441 /// </summary>
442 DataResponse insertResponse; 442 /// <param name="requestData"></param>
443 443 /// <returns></returns>
444 if (existingSim == null) 444 private RegionProfileData RegionFromRequest(Hashtable requestData)
445 { 445 {
446 insertResponse = plugin.AddProfile(sim); 446 RegionProfileData sim;
447 } 447 sim = new RegionProfileData();
448 else 448
449 { 449 sim.UUID = new UUID((string)requestData["UUID"]);
450 insertResponse = plugin.UpdateProfile(sim); 450 sim.originUUID = new UUID((string)requestData["originUUID"]);
451 } 451
452 452 sim.regionRecvKey = String.Empty;
453 switch (insertResponse) 453 sim.regionSendKey = String.Empty;
454 { 454
455 case DataResponse.RESPONSE_OK: 455 if (requestData.ContainsKey("region_secret"))
456 m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); 456 {
457 break; 457 string regionsecret = (string)requestData["region_secret"];
458 case DataResponse.RESPONSE_ERROR: 458 if (regionsecret.Length > 0)
459 m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); 459 sim.regionSecret = regionsecret;
460 break; 460 else
461 case DataResponse.RESPONSE_INVALIDCREDENTIALS: 461 sim.regionSecret = m_config.SimRecvKey;
462 m_log.Warn("[LOGIN END]: " + 462
463 "Sim login failed (Invalid Credentials): " + sim.regionName); 463 }
464 break; 464 else
465 case DataResponse.RESPONSE_AUTHREQUIRED: 465 {
466 m_log.Warn("[LOGIN END]: " + 466 sim.regionSecret = m_config.SimRecvKey;
467 "Sim login failed (Authentication Required): " + 467 }
468 sim.regionName); 468
469 break; 469 sim.regionDataURI = String.Empty;
470 } 470 sim.regionAssetURI = m_config.DefaultAssetServer;
471 } 471 sim.regionAssetRecvKey = m_config.AssetRecvKey;
472 catch (Exception e) 472 sim.regionAssetSendKey = m_config.AssetSendKey;
473 { 473 sim.regionUserURI = m_config.DefaultUserServer;
474 m_log.Warn("[LOGIN END]: " + 474 sim.regionUserSendKey = m_config.UserSendKey;
475 "Unable to login region " + sim.ToString() + " via " + plugin.Name); 475 sim.regionUserRecvKey = m_config.UserRecvKey;
476 m_log.Warn("[LOGIN END]: " + e.ToString()); 476
477 } 477 sim.serverIP = (string)requestData["sim_ip"];
478 } 478 sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]);
479 479 sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]);
480 XmlRpcResponse response = CreateLoginResponse(sim); 480 sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]);
481 481 sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]);
482 return response; 482 sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]);
483 } 483 sim.regionLocZ = 0;
484 else 484
485 { 485 UUID textureID;
486 m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); 486 if (UUID.TryParse((string)requestData["map-image-id"], out textureID))
487 return ErrorResponse("Another region already exists at that location. Please try another."); 487 {
488 } 488 sim.regionMapTextureID = textureID;
489 } 489 }
490 490
491 /// <summary> 491 // part of an initial brutish effort to provide accurate information (as per the xml region spec)
492 /// Construct a successful response to a simulator's login attempt. 492 // wrt the ownership of a given region
493 /// </summary> 493 // the (very bad) assumption is that this value is being read and handled inconsistently or
494 /// <param name="sim"></param> 494 // not at all. Current strategy is to put the code in place to support the validity of this information
495 /// <returns></returns> 495 // and to roll forward debugging any issues from that point
496 private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) 496 //
497 { 497 // this particular section of the mod attempts to receive a value from the region's xml file by way of
498 XmlRpcResponse response = new XmlRpcResponse(); 498 // OSG1GridServices for the region's owner
499 Hashtable responseData = new Hashtable(); 499 sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"];
500 response.Value = responseData; 500
501 501 try
502 ArrayList SimNeighboursData = GetSimNeighboursData(sim); 502 {
503 503 sim.regionRecvKey = (string)requestData["recvkey"];
504 responseData["UUID"] = sim.UUID.ToString(); 504 sim.regionSendKey = (string)requestData["authkey"];
505 responseData["region_locx"] = sim.regionLocX.ToString(); 505 }
506 responseData["region_locy"] = sim.regionLocY.ToString(); 506 catch (KeyNotFoundException) { }
507 responseData["regionname"] = sim.regionName; 507
508 responseData["estate_id"] = "1"; 508 sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize));
509 responseData["neighbours"] = SimNeighboursData; 509 sim.serverURI = (string)requestData["server_uri"];
510 510
511 responseData["sim_ip"] = sim.serverIP; 511 sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/";
512 responseData["sim_port"] = sim.serverPort.ToString(); 512
513 responseData["asset_url"] = sim.regionAssetURI; 513 sim.regionName = (string)requestData["sim_name"];
514 responseData["asset_sendkey"] = sim.regionAssetSendKey; 514 return sim;
515 responseData["asset_recvkey"] = sim.regionAssetRecvKey; 515 }
516 responseData["user_url"] = sim.regionUserURI; 516
517 responseData["user_sendkey"] = sim.regionUserSendKey; 517 /// <summary>
518 responseData["user_recvkey"] = sim.regionUserRecvKey; 518 /// Returns an XML RPC response to a simulator profile request
519 responseData["authkey"] = sim.regionSecret; 519 /// Performed after moving a region.
520 520 /// </summary>
521 // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) 521 /// <param name="request"></param>
522 responseData["data_uri"] = sim.regionDataURI; 522 /// <returns></returns>
523 523 /// <param name="request">The XMLRPC Request</param>
524 responseData["allow_forceful_banlines"] = Config.AllowForcefulBanlines; 524 /// <returns>Processing parameters</returns>
525 525 public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request)
526 // Instead of sending a multitude of message servers to the registering sim 526 {
527 // we should probably be sending a single one and parhaps it's backup 527 XmlRpcResponse response = new XmlRpcResponse();
528 // that has responsibility over routing it's messages. 528 Hashtable responseData = new Hashtable();
529 529 response.Value = responseData;
530 // The Sim won't be contacting us again about any of the message server stuff during it's time up. 530
531 531 //RegionProfileData TheSim = null;
532 responseData["messageserver_count"] = _MessageServers.Count; 532 string uuid;
533 533 Hashtable requestData = (Hashtable)request.Params[0];
534 for (int i = 0; i < _MessageServers.Count; i++) 534
535 { 535 if (requestData.ContainsKey("UUID"))
536 responseData["messageserver_uri" + i] = _MessageServers[i].URI; 536 {
537 responseData["messageserver_sendkey" + i] = _MessageServers[i].sendkey; 537 //TheSim = GetRegion(new UUID((string) requestData["UUID"]));
538 responseData["messageserver_recvkey" + i] = _MessageServers[i].recvkey; 538 uuid = requestData["UUID"].ToString();
539 } 539 m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid);
540 return response; 540// logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID.");
541 } 541 }
542 542 else
543 private ArrayList GetSimNeighboursData(RegionProfileData sim) 543 {
544 { 544 responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete";
545 ArrayList SimNeighboursData = new ArrayList(); 545 return response;
546 546 }
547 RegionProfileData neighbour; 547
548 Hashtable NeighbourBlock; 548 DataResponse insertResponse = m_gridDBService.DeleteRegion(uuid);
549 549
550 //First use the fast method. (not implemented in SQLLite) 550 string insertResp = "";
551 List<RegionProfileData> neighbours = GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); 551 switch (insertResponse)
552 552 {
553 if (neighbours.Count > 0) 553 case DataResponse.RESPONSE_OK:
554 { 554 //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid);
555 foreach (RegionProfileData aSim in neighbours) 555 insertResp = "Deleting region successful: " + uuid;
556 { 556 break;
557 NeighbourBlock = new Hashtable(); 557 case DataResponse.RESPONSE_ERROR:
558 NeighbourBlock["sim_ip"] = aSim.serverIP; 558 //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid);
559 NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); 559 insertResp = "Deleting region failed (Error): " + uuid;
560 NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); 560 break;
561 NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); 561 case DataResponse.RESPONSE_INVALIDCREDENTIALS:
562 NeighbourBlock["UUID"] = aSim.ToString(); 562 //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid);
563 NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); 563 insertResp = "Deleting region (Invalid Credentials): " + uuid;
564 564 break;
565 if (aSim.UUID != sim.UUID) 565 case DataResponse.RESPONSE_AUTHREQUIRED:
566 { 566 //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid);
567 SimNeighboursData.Add(NeighbourBlock); 567 insertResp = "Deleting region (Authentication Required): " + uuid;
568 } 568 break;
569 } 569 }
570 } 570
571 else 571 responseData["status"] = insertResp;
572 { 572
573 for (int x = -1; x < 2; x++) 573 return response;
574 { 574 }
575 for (int y = -1; y < 2; y++) 575
576 { 576 /// <summary>
577 if ( 577 /// Returns an XML RPC response to a simulator profile request
578 GetRegion( 578 /// </summary>
579 Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), 579 /// <param name="request"></param>
580 (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) 580 /// <returns></returns>
581 { 581 public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request)
582 neighbour = 582 {
583 GetRegion( 583 Hashtable requestData = (Hashtable)request.Params[0];
584 Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), 584 Hashtable responseData = new Hashtable();
585 (uint)(sim.regionLocY + y) * Constants.RegionSize)); 585 RegionProfileData simData = null;
586 586 if (requestData.ContainsKey("region_UUID"))
587 NeighbourBlock = new Hashtable(); 587 {
588 NeighbourBlock["sim_ip"] = neighbour.serverIP; 588 UUID regionID = new UUID((string)requestData["region_UUID"]);
589 NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); 589 simData = m_gridDBService.GetRegion(regionID);
590 NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); 590 if (simData == null)
591 NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); 591 {
592 NeighbourBlock["UUID"] = neighbour.UUID.ToString(); 592 m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}",
593 NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); 593 regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source");
594 594 }
595 if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); 595 }
596 } 596 else if (requestData.ContainsKey("region_handle"))
597 } 597 {
598 } 598 //CFK: The if/else below this makes this message redundant.
599 } 599 //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]);
600 return SimNeighboursData; 600 ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]);
601 } 601 simData = m_gridDBService.GetRegion(regionHandle);
602 602 if (simData == null)
603 /// <summary> 603 {
604 /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region 604 m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}",
605 /// </summary> 605 regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source");
606 /// <param name="requestData"></param> 606 }
607 /// <returns></returns> 607 }
608 private RegionProfileData RegionFromRequest(Hashtable requestData) 608 else if (requestData.ContainsKey("region_name_search"))
609 { 609 {
610 RegionProfileData sim; 610 string regionName = (string)requestData["region_name_search"];
611 sim = new RegionProfileData(); 611 simData = m_gridDBService.GetRegion(regionName);
612 612 if (simData == null)
613 sim.UUID = new UUID((string)requestData["UUID"]); 613 {
614 sim.originUUID = new UUID((string)requestData["originUUID"]); 614 m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}",
615 615 regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source");
616 sim.regionRecvKey = String.Empty; 616 }
617 sim.regionSendKey = String.Empty; 617 }
618 618 else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame");
619 if (requestData.ContainsKey("region_secret")) 619
620 { 620 if (simData == null)
621 string regionsecret = (string)requestData["region_secret"]; 621 {
622 if (regionsecret.Length > 0) 622 //Sim does not exist
623 sim.regionSecret = regionsecret; 623 responseData["error"] = "Sim does not exist";
624 else 624 }
625 sim.regionSecret = Config.SimRecvKey; 625 else
626 626 {
627 } 627 m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " +
628 else 628 (string)requestData["region_handle"]);
629 { 629 responseData["sim_ip"] = simData.serverIP;
630 sim.regionSecret = Config.SimRecvKey; 630 responseData["sim_port"] = simData.serverPort.ToString();
631 } 631 responseData["server_uri"] = simData.serverURI;
632 632 responseData["http_port"] = simData.httpPort.ToString();
633 sim.regionDataURI = String.Empty; 633 responseData["remoting_port"] = simData.remotingPort.ToString();
634 sim.regionAssetURI = Config.DefaultAssetServer; 634 responseData["region_locx"] = simData.regionLocX.ToString();
635 sim.regionAssetRecvKey = Config.AssetRecvKey; 635 responseData["region_locy"] = simData.regionLocY.ToString();
636 sim.regionAssetSendKey = Config.AssetSendKey; 636 responseData["region_UUID"] = simData.UUID.Guid.ToString();
637 sim.regionUserURI = Config.DefaultUserServer; 637 responseData["region_name"] = simData.regionName;
638 sim.regionUserSendKey = Config.UserSendKey; 638 responseData["regionHandle"] = simData.regionHandle.ToString();
639 sim.regionUserRecvKey = Config.UserRecvKey; 639 }
640 640
641 sim.serverIP = (string)requestData["sim_ip"]; 641 XmlRpcResponse response = new XmlRpcResponse();
642 sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); 642 response.Value = responseData;
643 sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); 643 return response;
644 sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); 644 }
645 sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); 645
646 sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); 646 public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request)
647 sim.regionLocZ = 0; 647 {
648 648 int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020;
649 UUID textureID; 649
650 if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) 650 Hashtable requestData = (Hashtable)request.Params[0];
651 { 651 if (requestData.ContainsKey("xmin"))
652 sim.regionMapTextureID = textureID; 652 {
653 } 653 xmin = (Int32)requestData["xmin"];
654 654 }
655 // part of an initial brutish effort to provide accurate information (as per the xml region spec) 655 if (requestData.ContainsKey("ymin"))
656 // wrt the ownership of a given region 656 {
657 // the (very bad) assumption is that this value is being read and handled inconsistently or 657 ymin = (Int32)requestData["ymin"];
658 // not at all. Current strategy is to put the code in place to support the validity of this information 658 }
659 // and to roll forward debugging any issues from that point 659 if (requestData.ContainsKey("xmax"))
660 // 660 {
661 // this particular section of the mod attempts to receive a value from the region's xml file by way of 661 xmax = (Int32)requestData["xmax"];
662 // OSG1GridServices for the region's owner 662 }
663 sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; 663 if (requestData.ContainsKey("ymax"))
664 664 {
665 try 665 ymax = (Int32)requestData["ymax"];
666 { 666 }
667 sim.regionRecvKey = (string)requestData["recvkey"]; 667 //CFK: The second log is more meaningful and either standard or fast generally occurs.
668 sim.regionSendKey = (string)requestData["authkey"]; 668 //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
669 } 669
670 catch (KeyNotFoundException) { } 670 XmlRpcResponse response = new XmlRpcResponse();
671 671 Hashtable responseData = new Hashtable();
672 sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); 672 response.Value = responseData;
673 sim.serverURI = (string)requestData["server_uri"]; 673 IList simProfileList = new ArrayList();
674 674
675 sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; 675 bool fastMode = (m_config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || m_config.DatabaseProvider == "OpenSim.Data.MSSQL.dll");
676 676
677 sim.regionName = (string)requestData["sim_name"]; 677 if (fastMode)
678 return sim; 678 {
679 } 679 List<RegionProfileData> neighbours = m_gridDBService.GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax);
680 680
681 /// <summary> 681 foreach (RegionProfileData aSim in neighbours)
682 /// Returns an XML RPC response to a simulator profile request 682 {
683 /// Performed after moving a region. 683 Hashtable simProfileBlock = new Hashtable();
684 /// </summary> 684 simProfileBlock["x"] = aSim.regionLocX.ToString();
685 /// <param name="request"></param> 685 simProfileBlock["y"] = aSim.regionLocY.ToString();
686 /// <returns></returns> 686 //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY);
687 /// <param name="request">The XMLRPC Request</param> 687 simProfileBlock["name"] = aSim.regionName;
688 /// <returns>Processing parameters</returns> 688 simProfileBlock["access"] = 21;
689 public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request) 689 simProfileBlock["region-flags"] = 512;
690 { 690 simProfileBlock["water-height"] = 0;
691 XmlRpcResponse response = new XmlRpcResponse(); 691 simProfileBlock["agents"] = 1;
692 Hashtable responseData = new Hashtable(); 692 simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString();
693 response.Value = responseData; 693
694 694 // For Sugilite compatibility
695 //RegionProfileData TheSim = null; 695 simProfileBlock["regionhandle"] = aSim.regionHandle.ToString();
696 string uuid; 696 simProfileBlock["sim_ip"] = aSim.serverIP;
697 Hashtable requestData = (Hashtable)request.Params[0]; 697 simProfileBlock["sim_port"] = aSim.serverPort.ToString();
698 698 simProfileBlock["sim_uri"] = aSim.serverURI.ToString();
699 if (requestData.ContainsKey("UUID")) 699 simProfileBlock["uuid"] = aSim.UUID.ToString();
700 { 700 simProfileBlock["remoting_port"] = aSim.remotingPort.ToString();
701 //TheSim = GetRegion(new UUID((string) requestData["UUID"])); 701 simProfileBlock["http_port"] = aSim.httpPort.ToString();
702 uuid = requestData["UUID"].ToString(); 702
703 m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); 703 simProfileList.Add(simProfileBlock);
704// logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); 704 }
705 } 705 m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() +
706 else 706 " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
707 { 707 }
708 responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; 708 else
709 return response; 709 {
710 } 710 RegionProfileData simProfile;
711 711 for (int x = xmin; x < xmax + 1; x++)
712 foreach (IGridDataPlugin plugin in _plugins) 712 {
713 { 713 for (int y = ymin; y < ymax + 1; y++)
714 //OpenSim.Data.MySQL.MySQLGridData dbengine = new OpenSim.Data.MySQL.MySQLGridData(); 714 {
715 try 715 ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize));
716 { 716 simProfile = m_gridDBService.GetRegion(regHandle);
717 //Nice are we not using multiple databases? 717 if (simProfile != null)
718 //MySQLGridData mysqldata = (MySQLGridData)(plugin); 718 {
719 719 Hashtable simProfileBlock = new Hashtable();
720 //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim); 720 simProfileBlock["x"] = x;
721 DataResponse insertResponse = plugin.DeleteProfile(uuid); 721 simProfileBlock["y"] = y;
722 722 simProfileBlock["name"] = simProfile.regionName;
723 switch (insertResponse) 723 simProfileBlock["access"] = 0;
724 { 724 simProfileBlock["region-flags"] = 0;
725 case DataResponse.RESPONSE_OK: 725 simProfileBlock["water-height"] = 20;
726 //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); 726 simProfileBlock["agents"] = 1;
727 responseData["status"] = "Deleting region successful: " + uuid; 727 simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString();
728 break; 728
729 case DataResponse.RESPONSE_ERROR: 729 // For Sugilite compatibility
730 //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); 730 simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString();
731 responseData["status"] = "Deleting region failed (Error): " + uuid; 731 simProfileBlock["sim_ip"] = simProfile.serverIP.ToString();
732 break; 732 simProfileBlock["sim_port"] = simProfile.serverPort.ToString();
733 case DataResponse.RESPONSE_INVALIDCREDENTIALS: 733 simProfileBlock["sim_uri"] = simProfile.serverURI.ToString();
734 //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); 734 simProfileBlock["uuid"] = simProfile.UUID.ToString();
735 responseData["status"] = "Deleting region (Invalid Credentials): " + uuid; 735 simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString();
736 break; 736 simProfileBlock["http_port"] = simProfile.httpPort;
737 case DataResponse.RESPONSE_AUTHREQUIRED: 737
738 //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); 738 simProfileList.Add(simProfileBlock);
739 responseData["status"] = "Deleting region (Authentication Required): " + uuid; 739 }
740 break; 740 }
741 } 741 }
742 } 742 m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() +
743 catch (Exception) 743 " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
744 { 744 }
745 m_log.Error("storage Unable to delete region " + uuid + " via " + plugin.Name); 745
746 //MainLog.Instance.Warn("storage", e.ToString()); 746 responseData["sim-profiles"] = simProfileList;
747 } 747
748 } 748 return response;
749 749 }
750 return response; 750
751 } 751 /// <summary>
752 752 /// Returns up to <code>maxNumber</code> profiles of regions that have a name starting with <code>name</code>
753 /// <summary> 753 /// </summary>
754 /// Returns an XML RPC response to a simulator profile request 754 /// <param name="request"></param>
755 /// </summary> 755 /// <returns></returns>
756 /// <param name="request"></param> 756 public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request)
757 /// <returns></returns> 757 {
758 public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) 758 Hashtable requestData = (Hashtable)request.Params[0];
759 { 759
760 Hashtable requestData = (Hashtable)request.Params[0]; 760 if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber"))
761 Hashtable responseData = new Hashtable(); 761 {
762 RegionProfileData simData = null; 762 m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber");
763 if (requestData.ContainsKey("region_UUID")) 763 return new XmlRpcResponse(500, "Missing name or maxNumber in region search request");
764 { 764 }
765 UUID regionID = new UUID((string)requestData["region_UUID"]); 765
766 simData = GetRegion(regionID); 766 Hashtable responseData = new Hashtable();
767 if (simData == null) 767
768 { 768 string name = (string)requestData["name"];
769 m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", 769 int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]);
770 regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); 770 if (maxNumber == 0 || name.Length < 3)
771 } 771 {
772 } 772 // either we didn't want any, or we were too unspecific
773 else if (requestData.ContainsKey("region_handle")) 773 responseData["numFound"] = 0;
774 { 774 }
775 //CFK: The if/else below this makes this message redundant. 775 else
776 //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); 776 {
777 ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); 777 List<RegionProfileData> sims = m_gridDBService.GetRegions(name, maxNumber);
778 simData = GetRegion(regionHandle); 778
779 if (simData == null) 779 responseData["numFound"] = sims.Count;
780 { 780 for (int i = 0; i < sims.Count; ++i)
781 m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", 781 {
782 regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); 782 RegionProfileData sim = sims[i];
783 } 783 string prefix = "region" + i + ".";
784 } 784 responseData[prefix + "region_name"] = sim.regionName;
785 else if (requestData.ContainsKey("region_name_search")) 785 responseData[prefix + "region_UUID"] = sim.UUID.ToString();
786 { 786 responseData[prefix + "region_locx"] = sim.regionLocX.ToString();
787 string regionName = (string)requestData["region_name_search"]; 787 responseData[prefix + "region_locy"] = sim.regionLocY.ToString();
788 simData = GetRegion(regionName); 788 responseData[prefix + "sim_ip"] = sim.serverIP.ToString();
789 if (simData == null) 789 responseData[prefix + "sim_port"] = sim.serverPort.ToString();
790 { 790 responseData[prefix + "remoting_port"] = sim.remotingPort.ToString();
791 m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", 791 responseData[prefix + "http_port"] = sim.httpPort.ToString();
792 regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); 792 responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString();
793 } 793 }
794 } 794 }
795 else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); 795
796 796 XmlRpcResponse response = new XmlRpcResponse();
797 if (simData == null) 797 response.Value = responseData;
798 { 798 return response;
799 //Sim does not exist 799 }
800 responseData["error"] = "Sim does not exist"; 800
801 } 801 /// <summary>
802 else 802 /// Construct an XMLRPC registration disabled response
803 { 803 /// </summary>
804 m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + 804 /// <param name="error"></param>
805 (string)requestData["region_handle"]); 805 /// <returns></returns>
806 responseData["sim_ip"] = simData.serverIP; 806 public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error)
807 responseData["sim_port"] = simData.serverPort.ToString(); 807 {
808 responseData["server_uri"] = simData.serverURI; 808 XmlRpcResponse errorResponse = new XmlRpcResponse();
809 responseData["http_port"] = simData.httpPort.ToString(); 809 Hashtable errorResponseData = new Hashtable();
810 responseData["remoting_port"] = simData.remotingPort.ToString(); 810 errorResponse.Value = errorResponseData;
811 responseData["region_locx"] = simData.regionLocX.ToString(); 811 errorResponseData["restricted"] = error;
812 responseData["region_locy"] = simData.regionLocY.ToString(); 812 return errorResponse;
813 responseData["region_UUID"] = simData.UUID.Guid.ToString(); 813 }
814 responseData["region_name"] = simData.regionName; 814 }
815 responseData["regionHandle"] = simData.regionHandle.ToString(); 815
816 } 816 /// <summary>
817 817 /// Exception generated when a simulator fails to login to the grid
818 XmlRpcResponse response = new XmlRpcResponse(); 818 /// </summary>
819 response.Value = responseData; 819 public class LoginException : Exception
820 return response; 820 {
821 } 821 /// <summary>
822 822 /// Return an XmlRpcResponse version of the exception message suitable for sending to a client
823 public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) 823 /// </summary>
824 { 824 /// <param name="message"></param>
825 int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; 825 /// <param name="xmlRpcMessage"></param>
826 826 public XmlRpcResponse XmlRpcErrorResponse
827 Hashtable requestData = (Hashtable)request.Params[0]; 827 {
828 if (requestData.ContainsKey("xmin")) 828 get { return m_xmlRpcErrorResponse; }
829 { 829 }
830 xmin = (Int32)requestData["xmin"]; 830 private XmlRpcResponse m_xmlRpcErrorResponse;
831 } 831
832 if (requestData.ContainsKey("ymin")) 832 public LoginException(string message, string xmlRpcMessage) : base(message)
833 { 833 {
834 ymin = (Int32)requestData["ymin"]; 834 // FIXME: Might be neater to refactor and put the method inside here
835 } 835 m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage);
836 if (requestData.ContainsKey("xmax")) 836 }
837 { 837
838 xmax = (Int32)requestData["xmax"]; 838 public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e)
839 } 839 {
840 if (requestData.ContainsKey("ymax")) 840 // FIXME: Might be neater to refactor and put the method inside here
841 { 841 m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage);
842 ymax = (Int32)requestData["ymax"]; 842 }
843 } 843 }
844 //CFK: The second log is more meaningful and either standard or fast generally occurs. 844}
845 //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
846
847 XmlRpcResponse response = new XmlRpcResponse();
848 Hashtable responseData = new Hashtable();
849 response.Value = responseData;
850 IList simProfileList = new ArrayList();
851
852 bool fastMode = (Config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || Config.DatabaseProvider == "OpenSim.Data.MSSQL.dll");
853
854 if (fastMode)
855 {
856 List<RegionProfileData> neighbours = GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax);
857
858 foreach (RegionProfileData aSim in neighbours)
859 {
860 Hashtable simProfileBlock = new Hashtable();
861 simProfileBlock["x"] = aSim.regionLocX.ToString();
862 simProfileBlock["y"] = aSim.regionLocY.ToString();
863 //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY);
864 simProfileBlock["name"] = aSim.regionName;
865 simProfileBlock["access"] = 21;
866 simProfileBlock["region-flags"] = 512;
867 simProfileBlock["water-height"] = 0;
868 simProfileBlock["agents"] = 1;
869 simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString();
870
871 // For Sugilite compatibility
872 simProfileBlock["regionhandle"] = aSim.regionHandle.ToString();
873 simProfileBlock["sim_ip"] = aSim.serverIP;
874 simProfileBlock["sim_port"] = aSim.serverPort.ToString();
875 simProfileBlock["sim_uri"] = aSim.serverURI.ToString();
876 simProfileBlock["uuid"] = aSim.UUID.ToString();
877 simProfileBlock["remoting_port"] = aSim.remotingPort.ToString();
878 simProfileBlock["http_port"] = aSim.httpPort.ToString();
879
880 simProfileList.Add(simProfileBlock);
881 }
882 m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() +
883 " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
884 }
885 else
886 {
887 RegionProfileData simProfile;
888 for (int x = xmin; x < xmax + 1; x++)
889 {
890 for (int y = ymin; y < ymax + 1; y++)
891 {
892 ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize));
893 simProfile = GetRegion(regHandle);
894 if (simProfile != null)
895 {
896 Hashtable simProfileBlock = new Hashtable();
897 simProfileBlock["x"] = x;
898 simProfileBlock["y"] = y;
899 simProfileBlock["name"] = simProfile.regionName;
900 simProfileBlock["access"] = 0;
901 simProfileBlock["region-flags"] = 0;
902 simProfileBlock["water-height"] = 20;
903 simProfileBlock["agents"] = 1;
904 simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString();
905
906 // For Sugilite compatibility
907 simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString();
908 simProfileBlock["sim_ip"] = simProfile.serverIP.ToString();
909 simProfileBlock["sim_port"] = simProfile.serverPort.ToString();
910 simProfileBlock["sim_uri"] = simProfile.serverURI.ToString();
911 simProfileBlock["uuid"] = simProfile.UUID.ToString();
912 simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString();
913 simProfileBlock["http_port"] = simProfile.httpPort;
914
915 simProfileList.Add(simProfileBlock);
916 }
917 }
918 }
919 m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() +
920 " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
921 }
922
923 responseData["sim-profiles"] = simProfileList;
924
925 return response;
926 }
927
928 /// <summary>
929 /// Returns up to <code>maxNumber</code> profiles of regions that have a name starting with <code>name</code>
930 /// </summary>
931 /// <param name="request"></param>
932 /// <returns></returns>
933 public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request)
934 {
935 Hashtable requestData = (Hashtable)request.Params[0];
936
937 if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber"))
938 {
939 m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber");
940 return new XmlRpcResponse(500, "Missing name or maxNumber in region search request");
941 }
942
943 Hashtable responseData = new Hashtable();
944
945 string name = (string)requestData["name"];
946 int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]);
947 if (maxNumber == 0 || name.Length < 3)
948 {
949 // either we didn't want any, or we were too unspecific
950 responseData["numFound"] = 0;
951 }
952 else
953 {
954 List<RegionProfileData> sims = GetRegions(name, maxNumber);
955
956 responseData["numFound"] = sims.Count;
957 for (int i = 0; i < sims.Count; ++i)
958 {
959 RegionProfileData sim = sims[i];
960 string prefix = "region" + i + ".";
961 responseData[prefix + "region_name"] = sim.regionName;
962 responseData[prefix + "region_UUID"] = sim.UUID.ToString();
963 responseData[prefix + "region_locx"] = sim.regionLocX.ToString();
964 responseData[prefix + "region_locy"] = sim.regionLocY.ToString();
965 responseData[prefix + "sim_ip"] = sim.serverIP.ToString();
966 responseData[prefix + "sim_port"] = sim.serverPort.ToString();
967 responseData[prefix + "remoting_port"] = sim.remotingPort.ToString();
968 responseData[prefix + "http_port"] = sim.httpPort.ToString();
969 responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString();
970 }
971 }
972
973 XmlRpcResponse response = new XmlRpcResponse();
974 response.Value = responseData;
975 return response;
976 }
977
978 /// <summary>
979 /// Performs a REST Get Operation
980 /// </summary>
981 /// <param name="request"></param>
982 /// <param name="path"></param>
983 /// <param name="param"></param>
984 /// <param name="httpRequest">HTTP request header object</param>
985 /// <param name="httpResponse">HTTP response header object</param>
986 /// <returns></returns>
987 public string RestGetRegionMethod(string request, string path, string param,
988 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
989 {
990 return RestGetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse);
991 }
992
993 /// <summary>
994 /// Performs a REST Set Operation
995 /// </summary>
996 /// <param name="request"></param>
997 /// <param name="path"></param>
998 /// <param name="param"></param>
999 /// <param name="httpRequest">HTTP request header object</param>
1000 /// <param name="httpResponse">HTTP response header object</param>
1001 /// <returns></returns>
1002 public string RestSetRegionMethod(string request, string path, string param,
1003 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
1004 {
1005 return RestSetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse);
1006 }
1007
1008 /// <summary>
1009 /// Returns information about a sim via a REST Request
1010 /// </summary>
1011 /// <param name="request"></param>
1012 /// <param name="path"></param>
1013 /// <param name="param">A string representing the sim's UUID</param>
1014 /// <param name="httpRequest">HTTP request header object</param>
1015 /// <param name="httpResponse">HTTP response header object</param>
1016 /// <returns>Information about the sim in XML</returns>
1017 public string RestGetSimMethod(string request, string path, string param,
1018 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
1019 {
1020 string respstring = String.Empty;
1021
1022 RegionProfileData TheSim;
1023
1024 UUID UUID;
1025 if (UUID.TryParse(param, out UUID))
1026 {
1027 TheSim = GetRegion(UUID);
1028
1029 if (!(TheSim == null))
1030 {
1031 respstring = "<Root>";
1032 respstring += "<authkey>" + TheSim.regionSendKey + "</authkey>";
1033 respstring += "<sim>";
1034 respstring += "<uuid>" + TheSim.UUID.ToString() + "</uuid>";
1035 respstring += "<regionname>" + TheSim.regionName + "</regionname>";
1036 respstring += "<sim_ip>" + TheSim.serverIP + "</sim_ip>";
1037 respstring += "<sim_port>" + TheSim.serverPort.ToString() + "</sim_port>";
1038 respstring += "<region_locx>" + TheSim.regionLocX.ToString() + "</region_locx>";
1039 respstring += "<region_locy>" + TheSim.regionLocY.ToString() + "</region_locy>";
1040 respstring += "<estate_id>1</estate_id>";
1041 respstring += "</sim>";
1042 respstring += "</Root>";
1043 }
1044 }
1045 else
1046 {
1047 respstring = "<Root>";
1048 respstring += "<error>Param must be a UUID</error>";
1049 respstring += "</Root>";
1050 }
1051
1052 return respstring;
1053 }
1054
1055 /// <summary>
1056 /// Creates or updates a sim via a REST Method Request
1057 /// BROKEN with SQL Update
1058 /// </summary>
1059 /// <param name="request"></param>
1060 /// <param name="path"></param>
1061 /// <param name="param"></param>
1062 /// <param name="httpRequest">HTTP request header object</param>
1063 /// <param name="httpResponse">HTTP response header object</param>
1064 /// <returns>"OK" or an error</returns>
1065 public string RestSetSimMethod(string request, string path, string param,
1066 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
1067 {
1068 Console.WriteLine("Processing region update via REST method");
1069 RegionProfileData theSim;
1070 theSim = GetRegion(new UUID(param));
1071 if (theSim == null)
1072 {
1073 theSim = new RegionProfileData();
1074 UUID UUID = new UUID(param);
1075 theSim.UUID = UUID;
1076 theSim.regionRecvKey = Config.SimRecvKey;
1077 }
1078
1079 XmlDocument doc = new XmlDocument();
1080 doc.LoadXml(request);
1081 XmlNode rootnode = doc.FirstChild;
1082 XmlNode authkeynode = rootnode.ChildNodes[0];
1083 if (authkeynode.Name != "authkey")
1084 {
1085 return "ERROR! bad XML - expected authkey tag";
1086 }
1087
1088 XmlNode simnode = rootnode.ChildNodes[1];
1089 if (simnode.Name != "sim")
1090 {
1091 return "ERROR! bad XML - expected sim tag";
1092 }
1093
1094 //theSim.regionSendKey = Cfg;
1095 theSim.regionRecvKey = Config.SimRecvKey;
1096 theSim.regionSendKey = Config.SimSendKey;
1097 theSim.regionSecret = Config.SimRecvKey;
1098 theSim.regionDataURI = String.Empty;
1099 theSim.regionAssetURI = Config.DefaultAssetServer;
1100 theSim.regionAssetRecvKey = Config.AssetRecvKey;
1101 theSim.regionAssetSendKey = Config.AssetSendKey;
1102 theSim.regionUserURI = Config.DefaultUserServer;
1103 theSim.regionUserSendKey = Config.UserSendKey;
1104 theSim.regionUserRecvKey = Config.UserRecvKey;
1105
1106 for (int i = 0; i < simnode.ChildNodes.Count; i++)
1107 {
1108 switch (simnode.ChildNodes[i].Name)
1109 {
1110 case "regionname":
1111 theSim.regionName = simnode.ChildNodes[i].InnerText;
1112 break;
1113
1114 case "sim_ip":
1115 theSim.serverIP = simnode.ChildNodes[i].InnerText;
1116 break;
1117
1118 case "sim_port":
1119 theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText);
1120 break;
1121
1122 case "region_locx":
1123 theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText);
1124 theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize));
1125 break;
1126
1127 case "region_locy":
1128 theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText);
1129 theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize));
1130 break;
1131 }
1132 }
1133
1134 theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/";
1135 bool requirePublic = false;
1136 bool requireValid = true;
1137
1138 if (requirePublic &&
1139 (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") ||
1140 theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") ||
1141 theSim.serverIP.StartsWith("255.")))
1142 {
1143 return "ERROR! Servers must register with public addresses.";
1144 }
1145
1146 if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255.")))
1147 {
1148 return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again";
1149 }
1150
1151 try
1152 {
1153 m_log.Info("[DATA]: " +
1154 "Updating / adding via " + _plugins.Count + " storage provider(s) registered.");
1155
1156 foreach (IGridDataPlugin plugin in _plugins)
1157 {
1158 try
1159 {
1160 //Check reservations
1161 ReservationData reserveData =
1162 plugin.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY);
1163 if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) ||
1164 (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey))
1165 {
1166 plugin.AddProfile(theSim);
1167 m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")");
1168 logToDB(theSim.ToString(), "RestSetSimMethod", String.Empty, 5,
1169 "Region successfully updated and connected to grid.");
1170 }
1171 else
1172 {
1173 m_log.Warn("[grid]: " +
1174 "Unable to update region (RestSetSimMethod): Incorrect reservation auth key.");
1175 // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + ".");
1176 return "Unable to update region (RestSetSimMethod): Incorrect auth key.";
1177 }
1178 }
1179 catch (Exception e)
1180 {
1181 m_log.Warn("[GRID]: GetRegionPlugin Handle " + plugin.Name + " unable to add new sim: " +
1182 e.ToString());
1183 }
1184 }
1185 return "OK";
1186 }
1187 catch (Exception e)
1188 {
1189 return "ERROR! Could not save to database! (" + e.ToString() + ")";
1190 }
1191 }
1192
1193 public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request)
1194 {
1195 XmlRpcResponse response = new XmlRpcResponse();
1196 Hashtable requestData = (Hashtable)request.Params[0];
1197 Hashtable responseData = new Hashtable();
1198
1199 if (requestData.Contains("uri"))
1200 {
1201 string URI = (string)requestData["URI"];
1202 string sendkey = (string)requestData["sendkey"];
1203 string recvkey = (string)requestData["recvkey"];
1204 MessageServerInfo m = new MessageServerInfo();
1205 m.URI = URI;
1206 m.sendkey = sendkey;
1207 m.recvkey = recvkey;
1208 if (!_MessageServers.Contains(m))
1209 _MessageServers.Add(m);
1210 responseData["responsestring"] = "TRUE";
1211 response.Value = responseData;
1212 }
1213 return response;
1214 }
1215
1216 public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request)
1217 {
1218 XmlRpcResponse response = new XmlRpcResponse();
1219 Hashtable requestData = (Hashtable)request.Params[0];
1220 Hashtable responseData = new Hashtable();
1221
1222 if (requestData.Contains("uri"))
1223 {
1224 string URI = (string)requestData["uri"];
1225 string sendkey = (string)requestData["sendkey"];
1226 string recvkey = (string)requestData["recvkey"];
1227 MessageServerInfo m = new MessageServerInfo();
1228 m.URI = URI;
1229 m.sendkey = sendkey;
1230 m.recvkey = recvkey;
1231 if (_MessageServers.Contains(m))
1232 _MessageServers.Remove(m);
1233 responseData["responsestring"] = "TRUE";
1234 response.Value = responseData;
1235 }
1236 return response;
1237 }
1238
1239 /// <summary>
1240 /// Construct an XMLRPC registration disabled response
1241 /// </summary>
1242 /// <param name="error"></param>
1243 /// <returns></returns>
1244 public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error)
1245 {
1246 XmlRpcResponse errorResponse = new XmlRpcResponse();
1247 Hashtable errorResponseData = new Hashtable();
1248 errorResponse.Value = errorResponseData;
1249 errorResponseData["restricted"] = error;
1250 return errorResponse;
1251 }
1252 }
1253
1254 /// <summary>
1255 /// Exception generated when a simulator fails to login to the grid
1256 /// </summary>
1257 public class LoginException : Exception
1258 {
1259 /// <summary>
1260 /// Return an XmlRpcResponse version of the exception message suitable for sending to a client
1261 /// </summary>
1262 /// <param name="message"></param>
1263 /// <param name="xmlRpcMessage"></param>
1264 public XmlRpcResponse XmlRpcErrorResponse
1265 {
1266 get { return m_xmlRpcErrorResponse; }
1267 }
1268 private XmlRpcResponse m_xmlRpcErrorResponse;
1269
1270 public LoginException(string message, string xmlRpcMessage) : base(message)
1271 {
1272 // FIXME: Might be neater to refactor and put the method inside here
1273 m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage);
1274 }
1275
1276 public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e)
1277 {
1278 // FIXME: Might be neater to refactor and put the method inside here
1279 m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage);
1280 }
1281 }
1282}