aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenGridServices/OpenGridServices.GridServer/GridManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenGridServices/OpenGridServices.GridServer/GridManager.cs')
-rw-r--r--OpenGridServices/OpenGridServices.GridServer/GridManager.cs575
1 files changed, 575 insertions, 0 deletions
diff --git a/OpenGridServices/OpenGridServices.GridServer/GridManager.cs b/OpenGridServices/OpenGridServices.GridServer/GridManager.cs
new file mode 100644
index 0000000..10cbf82
--- /dev/null
+++ b/OpenGridServices/OpenGridServices.GridServer/GridManager.cs
@@ -0,0 +1,575 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
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
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
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Text;
32using System.Reflection;
33using OpenGrid.Framework.Data;
34using OpenSim.Framework.Utilities;
35using OpenSim.Framework.Console;
36using OpenSim.Framework.Sims;
37using libsecondlife;
38using Nwc.XmlRpc;
39using System.Xml;
40
41namespace OpenGridServices.GridServer
42{
43 class GridManager
44 {
45 Dictionary<string, IGridData> _plugins = new Dictionary<string, IGridData>();
46 Dictionary<string, ILogData> _logplugins = new Dictionary<string, ILogData>();
47
48 public OpenSim.Framework.Interfaces.GridConfig config;
49
50 /// <summary>
51 /// Adds a new grid server plugin - grid servers will be requested in the order they were loaded.
52 /// </summary>
53 /// <param name="FileName">The filename to the grid server plugin DLL</param>
54 public void AddPlugin(string FileName)
55 {
56 OpenSim.Framework.Console.MainConsole.Instance.Verbose("Storage: Attempting to load " + FileName);
57 Assembly pluginAssembly = Assembly.LoadFrom(FileName);
58
59 OpenSim.Framework.Console.MainConsole.Instance.Verbose("Storage: Found " + pluginAssembly.GetTypes().Length + " interfaces.");
60 foreach (Type pluginType in pluginAssembly.GetTypes())
61 {
62 if (!pluginType.IsAbstract)
63 {
64 // Regions go here
65 Type typeInterface = pluginType.GetInterface("IGridData", true);
66
67 if (typeInterface != null)
68 {
69 IGridData plug = (IGridData)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
70 plug.Initialise();
71 this._plugins.Add(plug.getName(), plug);
72 OpenSim.Framework.Console.MainConsole.Instance.Verbose("Storage: Added IGridData Interface");
73 }
74
75 typeInterface = null;
76
77 // Logs go here
78 typeInterface = pluginType.GetInterface("ILogData", true);
79
80 if (typeInterface != null)
81 {
82 ILogData plug = (ILogData)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
83 plug.Initialise();
84 this._logplugins.Add(plug.getName(), plug);
85 OpenSim.Framework.Console.MainConsole.Instance.Verbose( "Storage: Added ILogData Interface");
86 }
87
88 typeInterface = null;
89 }
90 }
91
92 pluginAssembly = null;
93 }
94
95 /// <summary>
96 /// Logs a piece of information to the database
97 /// </summary>
98 /// <param name="target">What you were operating on (in grid server, this will likely be the region UUIDs)</param>
99 /// <param name="method">Which method is being called?</param>
100 /// <param name="args">What arguments are being passed?</param>
101 /// <param name="priority">How high priority is this? 1 = Max, 6 = Verbose</param>
102 /// <param name="message">The message to log</param>
103 private void logToDB(string target, string method, string args, int priority, string message)
104 {
105 foreach (KeyValuePair<string, ILogData> kvp in _logplugins)
106 {
107 try
108 {
109 kvp.Value.saveLog("Gridserver", target, method, args, priority, message);
110 }
111 catch (Exception e)
112 {
113 OpenSim.Framework.Console.MainConsole.Instance.Warn("Storage: unable to write log via " + kvp.Key);
114 }
115 }
116 }
117
118 /// <summary>
119 /// Returns a region by argument
120 /// </summary>
121 /// <param name="uuid">A UUID key of the region to return</param>
122 /// <returns>A SimProfileData for the region</returns>
123 public SimProfileData getRegion(libsecondlife.LLUUID uuid)
124 {
125 foreach(KeyValuePair<string,IGridData> kvp in _plugins) {
126 try
127 {
128 return kvp.Value.GetProfileByLLUUID(uuid);
129 }
130 catch (Exception e)
131 {
132 OpenSim.Framework.Console.MainConsole.Instance.Warn("Storage: Unable to find region " + uuid.ToStringHyphenated() + " via " + kvp.Key);
133 }
134 }
135 return null;
136 }
137
138 /// <summary>
139 /// Returns a region by argument
140 /// </summary>
141 /// <param name="uuid">A regionHandle of the region to return</param>
142 /// <returns>A SimProfileData for the region</returns>
143 public SimProfileData getRegion(ulong handle)
144 {
145 foreach (KeyValuePair<string, IGridData> kvp in _plugins)
146 {
147 try
148 {
149 return kvp.Value.GetProfileByHandle(handle);
150 }
151 catch (Exception e)
152 {
153 OpenSim.Framework.Console.MainConsole.Instance.Warn("Storage: Unable to find region " + handle.ToString() + " via " + kvp.Key);
154 }
155 }
156 return null;
157 }
158
159 public Dictionary<ulong, SimProfileData> getRegions(uint xmin, uint ymin, uint xmax, uint ymax)
160 {
161 Dictionary<ulong, SimProfileData> regions = new Dictionary<ulong, SimProfileData>();
162
163 SimProfileData[] neighbours;
164
165 foreach (KeyValuePair<string, IGridData> kvp in _plugins)
166 {
167 try
168 {
169 neighbours = kvp.Value.GetProfilesInRange(xmin, ymin, xmax, ymax);
170 foreach (SimProfileData neighbour in neighbours)
171 {
172 regions[neighbour.regionHandle] = neighbour;
173 }
174 }
175 catch (Exception e)
176 {
177 OpenSim.Framework.Console.MainConsole.Instance.Warn("Storage: Unable to query regionblock via " + kvp.Key);
178 }
179 }
180
181 return regions;
182 }
183
184 /// <summary>
185 /// Returns a XML String containing a list of the neighbouring regions
186 /// </summary>
187 /// <param name="reqhandle">The regionhandle for the center sim</param>
188 /// <returns>An XML string containing neighbour entities</returns>
189 public string GetXMLNeighbours(ulong reqhandle)
190 {
191 string response = "";
192 SimProfileData central_region = getRegion(reqhandle);
193 SimProfileData neighbour;
194 for (int x = -1; x < 2; x++) for (int y = -1; y < 2; y++)
195 {
196 if (getRegion(Util.UIntsToLong((uint)((central_region.regionLocX + x) * 256), (uint)(central_region.regionLocY + y) * 256)) != null)
197 {
198 neighbour = getRegion(Util.UIntsToLong((uint)((central_region.regionLocX + x) * 256), (uint)(central_region.regionLocY + y) * 256));
199 response += "<neighbour>";
200 response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>";
201 response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>";
202 response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>";
203 response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>";
204 response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>";
205 response += "</neighbour>";
206
207 }
208 }
209 return response;
210 }
211
212 /// <summary>
213 /// Performed when a region connects to the grid server initially.
214 /// </summary>
215 /// <param name="request">The XMLRPC Request</param>
216 /// <returns>Startup parameters</returns>
217 public XmlRpcResponse XmlRpcLoginToSimulatorMethod(XmlRpcRequest request)
218 {
219 XmlRpcResponse response = new XmlRpcResponse();
220 Hashtable responseData = new Hashtable();
221 response.Value = responseData;
222
223 SimProfileData TheSim = null;
224 Hashtable requestData = (Hashtable)request.Params[0];
225
226 if (requestData.ContainsKey("UUID"))
227 {
228 TheSim = getRegion(new LLUUID((string)requestData["UUID"]));
229 logToDB((new LLUUID((string)requestData["UUID"])).ToStringHyphenated(),"XmlRpcLoginToSimulatorMethod","", 5,"Region attempting login with UUID.");
230 }
231 else if (requestData.ContainsKey("region_handle"))
232 {
233 TheSim = getRegion((ulong)Convert.ToUInt64(requestData["region_handle"]));
234 logToDB((string)requestData["region_handle"], "XmlRpcLoginToSimulatorMethod", "", 5, "Region attempting login with regionHandle.");
235 }
236 else
237 {
238 responseData["error"] = "No UUID or region_handle passed to grid server - unable to connect you";
239 return response;
240 }
241
242 if (TheSim == null)
243 {
244 responseData["error"] = "sim not found";
245 return response;
246 }
247 else
248 {
249
250 ArrayList SimNeighboursData = new ArrayList();
251
252 SimProfileData neighbour;
253 Hashtable NeighbourBlock;
254
255 bool fastMode = false; // Only compatible with MySQL right now
256
257 if (fastMode)
258 {
259 Dictionary<ulong, SimProfileData> neighbours = getRegions(TheSim.regionLocX - 1, TheSim.regionLocY - 1, TheSim.regionLocX + 1, TheSim.regionLocY + 1);
260
261 foreach (KeyValuePair<ulong, SimProfileData> aSim in neighbours)
262 {
263 NeighbourBlock = new Hashtable();
264 NeighbourBlock["sim_ip"] = aSim.Value.serverIP.ToString();
265 NeighbourBlock["sim_port"] = aSim.Value.serverPort.ToString();
266 NeighbourBlock["region_locx"] = aSim.Value.regionLocX.ToString();
267 NeighbourBlock["region_locy"] = aSim.Value.regionLocY.ToString();
268 NeighbourBlock["UUID"] = aSim.Value.UUID.ToString();
269
270 if (aSim.Value.UUID != TheSim.UUID)
271 SimNeighboursData.Add(NeighbourBlock);
272 }
273 }
274 else
275 {
276 for (int x = -1; x < 2; x++) for (int y = -1; y < 2; y++)
277 {
278 if (getRegion(Helpers.UIntsToLong((uint)((TheSim.regionLocX + x) * 256), (uint)(TheSim.regionLocY + y) * 256)) != null)
279 {
280 neighbour = getRegion(Helpers.UIntsToLong((uint)((TheSim.regionLocX + x) * 256), (uint)(TheSim.regionLocY + y) * 256));
281
282 NeighbourBlock = new Hashtable();
283 NeighbourBlock["sim_ip"] = neighbour.serverIP;
284 NeighbourBlock["sim_port"] = neighbour.serverPort.ToString();
285 NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString();
286 NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString();
287 NeighbourBlock["UUID"] = neighbour.UUID.ToString();
288
289 if (neighbour.UUID != TheSim.UUID) SimNeighboursData.Add(NeighbourBlock);
290 }
291 }
292 }
293
294 responseData["UUID"] = TheSim.UUID.ToString();
295 responseData["region_locx"] = TheSim.regionLocX.ToString();
296 responseData["region_locy"] = TheSim.regionLocY.ToString();
297 responseData["regionname"] = TheSim.regionName;
298 responseData["estate_id"] = "1";
299 responseData["neighbours"] = SimNeighboursData;
300
301 responseData["sim_ip"] = TheSim.serverIP;
302 responseData["sim_port"] = TheSim.serverPort.ToString();
303 responseData["asset_url"] = TheSim.regionAssetURI;
304 responseData["asset_sendkey"] = TheSim.regionAssetSendKey;
305 responseData["asset_recvkey"] = TheSim.regionAssetRecvKey;
306 responseData["user_url"] = TheSim.regionUserURI;
307 responseData["user_sendkey"] = TheSim.regionUserSendKey;
308 responseData["user_recvkey"] = TheSim.regionUserRecvKey;
309 responseData["authkey"] = TheSim.regionSecret;
310
311 // New! If set, use as URL to local sim storage (ie http://remotehost/region.yap)
312 responseData["data_uri"] = TheSim.regionDataURI;
313 }
314
315 return response;
316 }
317
318 public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request)
319 {
320 int xmin=980, ymin=980, xmax=1020, ymax=1020;
321
322 Hashtable requestData = (Hashtable)request.Params[0];
323 if (requestData.ContainsKey("xmin"))
324 {
325 xmin = (Int32)requestData["xmin"];
326 }
327 if (requestData.ContainsKey("ymin"))
328 {
329 ymin = (Int32)requestData["ymin"];
330 }
331 if (requestData.ContainsKey("xmax"))
332 {
333 xmax = (Int32)requestData["xmax"];
334 }
335 if (requestData.ContainsKey("ymax"))
336 {
337 ymax = (Int32)requestData["ymax"];
338 }
339
340 XmlRpcResponse response = new XmlRpcResponse();
341 Hashtable responseData = new Hashtable();
342 response.Value = responseData;
343 IList simProfileList = new ArrayList();
344
345 bool fastMode = true; // MySQL Only
346
347 if (fastMode)
348 {
349 Dictionary<ulong, SimProfileData> neighbours = getRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax);
350
351 foreach (KeyValuePair<ulong, SimProfileData> aSim in neighbours)
352 {
353 Hashtable simProfileBlock = new Hashtable();
354 simProfileBlock["x"] = aSim.Value.regionLocX.ToString();
355 simProfileBlock["y"] = aSim.Value.regionLocY.ToString();
356 simProfileBlock["name"] = aSim.Value.regionName;
357 simProfileBlock["access"] = 21;
358 simProfileBlock["region-flags"] = 512;
359 simProfileBlock["water-height"] = 0;
360 simProfileBlock["agents"] = 1;
361 simProfileBlock["map-image-id"] = aSim.Value.regionMapTextureID.ToString();
362
363 simProfileList.Add(simProfileBlock);
364 }
365 OpenSim.Framework.Console.MainConsole.Instance.Verbose("World map request processed, returned " + simProfileList.Count.ToString() + " region(s) in range via FastMode");
366 }
367 else
368 {
369 SimProfileData simProfile;
370 for (int x = xmin; x < xmax; x++)
371 {
372 for (int y = ymin; y < ymax; y++)
373 {
374 simProfile = getRegion(Helpers.UIntsToLong((uint)(x * 256), (uint)(y * 256)));
375 if (simProfile != null)
376 {
377 Hashtable simProfileBlock = new Hashtable();
378 simProfileBlock["x"] = x;
379 simProfileBlock["y"] = y;
380 simProfileBlock["name"] = simProfile.regionName;
381 simProfileBlock["access"] = 0;
382 simProfileBlock["region-flags"] = 0;
383 simProfileBlock["water-height"] = 20;
384 simProfileBlock["agents"] = 1;
385 simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString();
386
387 simProfileList.Add(simProfileBlock);
388 }
389 }
390 }
391 OpenSim.Framework.Console.MainConsole.Instance.Verbose("World map request processed, returned " + simProfileList.Count.ToString() + " region(s) in range via Standard Mode");
392 }
393
394 responseData["sim-profiles"] = simProfileList;
395
396 return response;
397 }
398
399
400
401 /// <summary>
402 /// Performs a REST Get Operation
403 /// </summary>
404 /// <param name="request"></param>
405 /// <param name="path"></param>
406 /// <param name="param"></param>
407 /// <returns></returns>
408 public string RestGetRegionMethod(string request, string path, string param)
409 {
410 return RestGetSimMethod("", "/sims/", param);
411 }
412
413 /// <summary>
414 /// Performs a REST Set Operation
415 /// </summary>
416 /// <param name="request"></param>
417 /// <param name="path"></param>
418 /// <param name="param"></param>
419 /// <returns></returns>
420 public string RestSetRegionMethod(string request, string path, string param)
421 {
422 return RestSetSimMethod("", "/sims/", param);
423 }
424
425 /// <summary>
426 /// Returns information about a sim via a REST Request
427 /// </summary>
428 /// <param name="request"></param>
429 /// <param name="path"></param>
430 /// <param name="param"></param>
431 /// <returns>Information about the sim in XML</returns>
432 public string RestGetSimMethod(string request, string path, string param)
433 {
434 string respstring = String.Empty;
435
436 SimProfileData TheSim;
437 LLUUID UUID = new LLUUID(param);
438 TheSim = getRegion(UUID);
439
440 if (!(TheSim == null))
441 {
442 respstring = "<Root>";
443 respstring += "<authkey>" + TheSim.regionSendKey + "</authkey>";
444 respstring += "<sim>";
445 respstring += "<uuid>" + TheSim.UUID.ToString() + "</uuid>";
446 respstring += "<regionname>" + TheSim.regionName + "</regionname>";
447 respstring += "<sim_ip>" + TheSim.serverIP + "</sim_ip>";
448 respstring += "<sim_port>" + TheSim.serverPort.ToString() + "</sim_port>";
449 respstring += "<region_locx>" + TheSim.regionLocX.ToString() + "</region_locx>";
450 respstring += "<region_locy>" + TheSim.regionLocY.ToString() + "</region_locy>";
451 respstring += "<estate_id>1</estate_id>";
452 respstring += "</sim>";
453 respstring += "</Root>";
454 }
455
456 return respstring;
457 }
458
459 /// <summary>
460 /// Creates or updates a sim via a REST Method Request
461 /// BROKEN with SQL Update
462 /// </summary>
463 /// <param name="request"></param>
464 /// <param name="path"></param>
465 /// <param name="param"></param>
466 /// <returns>"OK" or an error</returns>
467 public string RestSetSimMethod(string request, string path, string param)
468 {
469 Console.WriteLine("Processing region update");
470 SimProfileData TheSim;
471 TheSim = getRegion(new LLUUID(param));
472 if ((TheSim) == null)
473 {
474 TheSim = new SimProfileData();
475 LLUUID UUID = new LLUUID(param);
476 TheSim.UUID = UUID;
477 TheSim.regionRecvKey = config.SimRecvKey;
478 }
479
480 XmlDocument doc = new XmlDocument();
481 doc.LoadXml(request);
482 XmlNode rootnode = doc.FirstChild;
483 XmlNode authkeynode = rootnode.ChildNodes[0];
484 if (authkeynode.Name != "authkey")
485 {
486 return "ERROR! bad XML - expected authkey tag";
487 }
488
489 XmlNode simnode = rootnode.ChildNodes[1];
490 if (simnode.Name != "sim")
491 {
492 return "ERROR! bad XML - expected sim tag";
493 }
494
495 if (authkeynode.InnerText != TheSim.regionRecvKey)
496 {
497 return "ERROR! invalid key";
498 }
499
500 //TheSim.regionSendKey = Cfg;
501 TheSim.regionRecvKey = config.SimRecvKey;
502 TheSim.regionSendKey = config.SimSendKey;
503 TheSim.regionSecret = config.SimRecvKey;
504 TheSim.regionDataURI = "";
505 TheSim.regionAssetURI = config.DefaultAssetServer;
506 TheSim.regionAssetRecvKey = config.AssetRecvKey;
507 TheSim.regionAssetSendKey = config.AssetSendKey;
508 TheSim.regionUserURI = config.DefaultUserServer;
509 TheSim.regionUserSendKey = config.UserSendKey;
510 TheSim.regionUserRecvKey = config.UserRecvKey;
511
512
513 for (int i = 0; i < simnode.ChildNodes.Count; i++)
514 {
515 switch (simnode.ChildNodes[i].Name)
516 {
517 case "regionname":
518 TheSim.regionName = simnode.ChildNodes[i].InnerText;
519 break;
520
521 case "sim_ip":
522 TheSim.serverIP = simnode.ChildNodes[i].InnerText;
523 break;
524
525 case "sim_port":
526 TheSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText);
527 break;
528
529 case "region_locx":
530 TheSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText);
531 TheSim.regionHandle = Helpers.UIntsToLong((TheSim.regionLocX * 256), (TheSim.regionLocY * 256));
532 break;
533
534 case "region_locy":
535 TheSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText);
536 TheSim.regionHandle = Helpers.UIntsToLong((TheSim.regionLocX * 256), (TheSim.regionLocY * 256));
537 break;
538 }
539 }
540
541 TheSim.serverURI = "http://" + TheSim.serverIP + ":" + TheSim.serverPort + "/";
542
543 bool requirePublic = false;
544
545 if (requirePublic && (TheSim.serverIP.StartsWith("172.16") || TheSim.serverIP.StartsWith("192.168") || TheSim.serverIP.StartsWith("10.") || TheSim.serverIP.StartsWith("0.") || TheSim.serverIP.StartsWith("255.")))
546 {
547 return "ERROR! Servers must register with public addresses.";
548 }
549
550 try
551 {
552 OpenSim.Framework.Console.MainConsole.Instance.Verbose("Updating / adding via " + _plugins.Count + " storage provider(s) registered.");
553 foreach (KeyValuePair<string, IGridData> kvp in _plugins)
554 {
555 try
556 {
557 kvp.Value.AddProfile(TheSim);
558 OpenSim.Framework.Console.MainConsole.Instance.Verbose("New sim added to grid (" + TheSim.regionName + ")");
559 logToDB(TheSim.UUID.ToStringHyphenated(), "RestSetSimMethod", "", 5, "Region successfully updated and connected to grid.");
560 }
561 catch (Exception e)
562 {
563 OpenSim.Framework.Console.MainConsole.Instance.Verbose("getRegionPlugin Handle " + kvp.Key + " unable to add new sim: " + e.ToString());
564 }
565 }
566 return "OK";
567 }
568 catch (Exception e)
569 {
570 return "ERROR! Could not save to database! (" + e.ToString() + ")";
571 }
572 }
573
574 }
575}