aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/GridService/HypergridLinker.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/GridService/HypergridLinker.cs')
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs641
1 files changed, 641 insertions, 0 deletions
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
new file mode 100644
index 0000000..af603b2
--- /dev/null
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -0,0 +1,641 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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 OpenSimulator 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.Generic;
30using System.Net;
31using System.Reflection;
32using System.Xml;
33
34using Nini.Config;
35using log4net;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
38using OpenSim.Data;
39using OpenSim.Server.Base;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Hypergrid;
42using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43using OpenMetaverse;
44
45namespace OpenSim.Services.GridService
46{
47 public class HypergridLinker
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private static UUID m_HGMapImage = new UUID("00000000-0000-1111-9999-000000000013");
54
55 private static uint m_autoMappingX = 0;
56 private static uint m_autoMappingY = 0;
57 private static bool m_enableAutoMapping = false;
58
59 protected IRegionData m_Database;
60 protected GridService m_GridService;
61 protected IAssetService m_AssetService;
62 protected GatekeeperServiceConnector m_GatekeeperConnector;
63
64 protected UUID m_ScopeID = UUID.Zero;
65
66 // Hyperlink regions are hyperlinks on the map
67 public readonly Dictionary<UUID, GridRegion> m_HyperlinkRegions = new Dictionary<UUID, GridRegion>();
68 protected Dictionary<UUID, ulong> m_HyperlinkHandles = new Dictionary<UUID, ulong>();
69
70 protected GridRegion m_DefaultRegion;
71 protected GridRegion DefaultRegion
72 {
73 get
74 {
75 if (m_DefaultRegion == null)
76 {
77 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID);
78 if (defs != null && defs.Count > 0)
79 m_DefaultRegion = defs[0];
80 else
81 {
82 // Get any region
83 defs = m_GridService.GetRegionsByName(m_ScopeID, "", 1);
84 if (defs != null && defs.Count > 0)
85 m_DefaultRegion = defs[0];
86 else
87 {
88 // This shouldn't happen
89 m_DefaultRegion = new GridRegion(1000, 1000);
90 m_log.Error("[HYPERGRID LINKER]: Something is wrong with this grid. It has no regions?");
91 }
92 }
93 }
94 return m_DefaultRegion;
95 }
96 }
97
98 public HypergridLinker(IConfigSource config, GridService gridService, IRegionData db)
99 {
100 m_log.DebugFormat("[HYPERGRID LINKER]: Starting with db {0}", db.GetType());
101
102 m_Database = db;
103 m_GridService = gridService;
104
105 IConfig gridConfig = config.Configs["GridService"];
106 if (gridConfig != null)
107 {
108 string assetService = gridConfig.GetString("AssetService", string.Empty);
109
110 Object[] args = new Object[] { config };
111
112 if (assetService != string.Empty)
113 m_AssetService = ServerUtils.LoadPlugin<IAssetService>(assetService, args);
114
115 string scope = gridConfig.GetString("ScopeID", string.Empty);
116 if (scope != string.Empty)
117 UUID.TryParse(scope, out m_ScopeID);
118
119 m_GatekeeperConnector = new GatekeeperServiceConnector(m_AssetService);
120
121 m_log.DebugFormat("[HYPERGRID LINKER]: Loaded all services...");
122 }
123
124 if (MainConsole.Instance != null)
125 {
126 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region",
127 "link-region <Xloc> <Yloc> <HostName>:<HttpPort>[:<RemoteRegionName>] <cr>",
128 "Link a hypergrid region", RunCommand);
129 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region",
130 "unlink-region <local name> or <HostName>:<HttpPort> <cr>",
131 "Unlink a hypergrid region", RunCommand);
132 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-mapping", "link-mapping [<x> <y>] <cr>",
133 "Set local coordinate to map HG regions to", RunCommand);
134 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "show hyperlinks", "show hyperlinks <cr>",
135 "List the HG regions", HandleShow);
136 }
137 }
138
139
140 #region Link Region
141
142 public GridRegion LinkRegion(UUID scopeID, string regionDescriptor)
143 {
144 string reason = string.Empty;
145 int xloc = random.Next(0, Int16.MaxValue) * (int)Constants.RegionSize;
146 return TryLinkRegionToCoords(scopeID, regionDescriptor, xloc, 0, out reason);
147 }
148
149 private static Random random = new Random();
150
151 // From the command line link-region
152 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, out string reason)
153 {
154 reason = string.Empty;
155 string host = "127.0.0.1";
156 string portstr;
157 string regionName = "";
158 uint port = 9000;
159 string[] parts = mapName.Split(new char[] { ':' });
160 if (parts.Length >= 1)
161 {
162 host = parts[0];
163 }
164 if (parts.Length >= 2)
165 {
166 portstr = parts[1];
167 //m_log.Debug("-- port = " + portstr);
168 if (!UInt32.TryParse(portstr, out port))
169 regionName = parts[1];
170 }
171 // always take the last one
172 if (parts.Length >= 3)
173 {
174 regionName = parts[2];
175 }
176
177 // Sanity check.
178 //IPAddress ipaddr = null;
179 try
180 {
181 //ipaddr = Util.GetHostFromDNS(host);
182 Util.GetHostFromDNS(host);
183 }
184 catch
185 {
186 reason = "Malformed hostname";
187 return null;
188 }
189
190 GridRegion regInfo;
191 bool success = TryCreateLink(scopeID, xloc, yloc, regionName, port, host, out regInfo, out reason);
192 if (success)
193 {
194 regInfo.RegionName = mapName;
195 return regInfo;
196 }
197
198 return null;
199 }
200
201
202 // From the command line and the 2 above
203 public bool TryCreateLink(UUID scopeID, int xloc, int yloc,
204 string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo, out string reason)
205 {
206 m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}:{2}, in {3}-{4}", externalHostName, externalPort, externalRegionName, xloc, yloc);
207
208 reason = string.Empty;
209 regInfo = new GridRegion();
210 regInfo.RegionName = externalRegionName;
211 regInfo.HttpPort = externalPort;
212 regInfo.ExternalHostName = externalHostName;
213 regInfo.RegionLocX = xloc;
214 regInfo.RegionLocY = yloc;
215 regInfo.ScopeID = scopeID;
216
217 try
218 {
219 regInfo.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)0);
220 }
221 catch (Exception e)
222 {
223 m_log.Warn("[HYPERGRID LINKER]: Wrong format for link-region: " + e.Message);
224 reason = "Internal error";
225 return false;
226 }
227
228 // Finally, link it
229 ulong handle = 0;
230 UUID regionID = UUID.Zero;
231 string externalName = string.Empty;
232 string imageURL = string.Empty;
233 if (!m_GatekeeperConnector.LinkRegion(regInfo, out regionID, out handle, out externalName, out imageURL, out reason))
234 return false;
235
236 if (regionID != UUID.Zero)
237 {
238 GridRegion r = m_GridService.GetRegionByUUID(scopeID, regionID);
239 if (r != null)
240 {
241 m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates {0} {1}", r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
242 regInfo = r;
243 return true;
244 }
245
246 regInfo.RegionID = regionID;
247 Uri uri = null;
248 try
249 {
250 uri = new Uri(externalName);
251 regInfo.ExternalHostName = uri.Host;
252 regInfo.HttpPort = (uint)uri.Port;
253 }
254 catch
255 {
256 m_log.WarnFormat("[HYPERGRID LINKER]: Remote Gatekeeper at {0} provided malformed ExternalName {1}", regInfo.ExternalHostName, externalName);
257 }
258 regInfo.RegionName = regInfo.ExternalHostName + ":" + regInfo.HttpPort + ":" + regInfo.RegionName;
259 // Try get the map image
260 //regInfo.TerrainImage = m_GatekeeperConnector.GetMapImage(regionID, imageURL);
261 // I need a texture that works for this... the one I tried doesn't seem to be working
262 regInfo.TerrainImage = m_HGMapImage;
263
264 AddHyperlinkRegion(regInfo, handle);
265 m_log.Info("[HYPERGRID LINKER]: Successfully linked to region_uuid " + regInfo.RegionID);
266
267 }
268 else
269 {
270 m_log.Warn("[HYPERGRID LINKER]: Unable to link region");
271 reason = "Remote region could not be found";
272 return false;
273 }
274
275 uint x, y;
276 if (!Check4096(handle, out x, out y))
277 {
278 RemoveHyperlinkRegion(regInfo.RegionID);
279 reason = "Region is too far (" + x + ", " + y + ")";
280 m_log.Info("[HYPERGRID LINKER]: Unable to link, region is too far (" + x + ", " + y + ")");
281 return false;
282 }
283
284 m_log.Debug("[HYPERGRID LINKER]: link region succeeded");
285 return true;
286 }
287
288 public bool TryUnlinkRegion(string mapName)
289 {
290 m_log.DebugFormat("[HYPERGRID LINKER]: Request to unlink {0}", mapName);
291 GridRegion regInfo = null;
292
293 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID);
294 if (regions != null && regions.Count > 0)
295 {
296 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
297 if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0)
298 {
299 regInfo = new GridRegion();
300 regInfo.RegionID = regions[0].RegionID;
301 regInfo.ScopeID = m_ScopeID;
302 }
303 }
304
305 //foreach (GridRegion r in m_HyperlinkRegions.Values)
306 //{
307 // m_log.DebugFormat("XXX Comparing {0}:{1} with {2}:{3}", host, port, r.ExternalHostName, r.HttpPort);
308 // if (host.Equals(r.ExternalHostName) && (port == r.HttpPort))
309 // regInfo = r;
310 //}
311
312 if (regInfo != null)
313 {
314 RemoveHyperlinkRegion(regInfo.RegionID);
315 return true;
316 }
317 else
318 {
319 m_log.InfoFormat("[HYPERGRID LINKER]: Region {0} not found", mapName);
320 return false;
321 }
322 }
323
324 /// <summary>
325 /// Cope with this viewer limitation.
326 /// </summary>
327 /// <param name="regInfo"></param>
328 /// <returns></returns>
329 public bool Check4096(ulong realHandle, out uint x, out uint y)
330 {
331 GridRegion defRegion = DefaultRegion;
332
333 uint ux = 0, uy = 0;
334 Utils.LongToUInts(realHandle, out ux, out uy);
335 x = ux / Constants.RegionSize;
336 y = uy / Constants.RegionSize;
337
338 if ((Math.Abs((int)defRegion.RegionLocX - ux) >= 4096 * Constants.RegionSize) ||
339 (Math.Abs((int)defRegion.RegionLocY - uy) >= 4096 * Constants.RegionSize))
340 {
341 return false;
342 }
343 return true;
344 }
345
346 private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
347 {
348 //m_HyperlinkRegions[regionInfo.RegionID] = regionInfo;
349 //m_HyperlinkHandles[regionInfo.RegionID] = regionHandle;
350
351 RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo);
352 int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline;
353 rdata.Data["flags"] = flags.ToString();
354
355 m_Database.Store(rdata);
356
357 }
358
359 private void RemoveHyperlinkRegion(UUID regionID)
360 {
361 //// Try the hyperlink collection
362 //if (m_HyperlinkRegions.ContainsKey(regionID))
363 //{
364 // m_HyperlinkRegions.Remove(regionID);
365 // m_HyperlinkHandles.Remove(regionID);
366 //}
367 m_Database.Delete(regionID);
368 }
369
370 #endregion
371
372
373 #region Console Commands
374
375 public void HandleShow(string module, string[] cmd)
376 {
377 MainConsole.Instance.Output("Not Implemented Yet");
378 //if (cmd.Length != 2)
379 //{
380 // MainConsole.Instance.Output("Syntax: show hyperlinks");
381 // return;
382 //}
383 //List<GridRegion> regions = new List<GridRegion>(m_HypergridService.m_HyperlinkRegions.Values);
384 //if (regions == null || regions.Count < 1)
385 //{
386 // MainConsole.Instance.Output("No hyperlinks");
387 // return;
388 //}
389
390 //MainConsole.Instance.Output("Region Name Region UUID");
391 //MainConsole.Instance.Output("Location URI");
392 //MainConsole.Instance.Output("Owner ID ");
393 //MainConsole.Instance.Output("-------------------------------------------------------------------------------");
394 //foreach (GridRegion r in regions)
395 //{
396 // MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} \n\n",
397 // r.RegionName, r.RegionID,
398 // String.Format("{0},{1}", r.RegionLocX, r.RegionLocY), "http://" + r.ExternalHostName + ":" + r.HttpPort.ToString(),
399 // r.EstateOwner.ToString()));
400 //}
401 //return;
402 }
403 public void RunCommand(string module, string[] cmdparams)
404 {
405 List<string> args = new List<string>(cmdparams);
406 if (args.Count < 1)
407 return;
408
409 string command = args[0];
410 args.RemoveAt(0);
411
412 cmdparams = args.ToArray();
413
414 RunHGCommand(command, cmdparams);
415
416 }
417
418 private void RunHGCommand(string command, string[] cmdparams)
419 {
420 if (command.Equals("link-mapping"))
421 {
422 if (cmdparams.Length == 2)
423 {
424 try
425 {
426 m_autoMappingX = Convert.ToUInt32(cmdparams[0]);
427 m_autoMappingY = Convert.ToUInt32(cmdparams[1]);
428 m_enableAutoMapping = true;
429 }
430 catch (Exception)
431 {
432 m_autoMappingX = 0;
433 m_autoMappingY = 0;
434 m_enableAutoMapping = false;
435 }
436 }
437 }
438 else if (command.Equals("link-region"))
439 {
440 if (cmdparams.Length < 3)
441 {
442 if ((cmdparams.Length == 1) || (cmdparams.Length == 2))
443 {
444 LoadXmlLinkFile(cmdparams);
445 }
446 else
447 {
448 LinkRegionCmdUsage();
449 }
450 return;
451 }
452
453 if (cmdparams[2].Contains(":"))
454 {
455 // New format
456 int xloc, yloc;
457 string mapName;
458 try
459 {
460 xloc = Convert.ToInt32(cmdparams[0]);
461 yloc = Convert.ToInt32(cmdparams[1]);
462 mapName = cmdparams[2];
463 if (cmdparams.Length > 3)
464 for (int i = 3; i < cmdparams.Length; i++)
465 mapName += " " + cmdparams[i];
466
467 //m_log.Info(">> MapName: " + mapName);
468 }
469 catch (Exception e)
470 {
471 MainConsole.Instance.Output("[HGrid] Wrong format for link-region command: " + e.Message);
472 LinkRegionCmdUsage();
473 return;
474 }
475
476 // Convert cell coordinates given by the user to meters
477 xloc = xloc * (int)Constants.RegionSize;
478 yloc = yloc * (int)Constants.RegionSize;
479 string reason = string.Empty;
480 if (TryLinkRegionToCoords(UUID.Zero, mapName, xloc, yloc, out reason) == null)
481 MainConsole.Instance.Output("Failed to link region: " + reason);
482 else
483 MainConsole.Instance.Output("Hyperlink established");
484 }
485 else
486 {
487 // old format
488 GridRegion regInfo;
489 int xloc, yloc;
490 uint externalPort;
491 string externalHostName;
492 try
493 {
494 xloc = Convert.ToInt32(cmdparams[0]);
495 yloc = Convert.ToInt32(cmdparams[1]);
496 externalPort = Convert.ToUInt32(cmdparams[3]);
497 externalHostName = cmdparams[2];
498 //internalPort = Convert.ToUInt32(cmdparams[4]);
499 //remotingPort = Convert.ToUInt32(cmdparams[5]);
500 }
501 catch (Exception e)
502 {
503 MainConsole.Instance.Output("[HGrid] Wrong format for link-region command: " + e.Message);
504 LinkRegionCmdUsage();
505 return;
506 }
507
508 // Convert cell coordinates given by the user to meters
509 xloc = xloc * (int)Constants.RegionSize;
510 yloc = yloc * (int)Constants.RegionSize;
511 string reason = string.Empty;
512 if (TryCreateLink(UUID.Zero, xloc, yloc, "", externalPort, externalHostName, out regInfo, out reason))
513 {
514 if (cmdparams.Length >= 5)
515 {
516 regInfo.RegionName = "";
517 for (int i = 4; i < cmdparams.Length; i++)
518 regInfo.RegionName += cmdparams[i] + " ";
519 }
520 }
521 }
522 return;
523 }
524 else if (command.Equals("unlink-region"))
525 {
526 if (cmdparams.Length < 1)
527 {
528 UnlinkRegionCmdUsage();
529 return;
530 }
531 if (TryUnlinkRegion(cmdparams[0]))
532 MainConsole.Instance.Output("Successfully unlinked " + cmdparams[0]);
533 else
534 MainConsole.Instance.Output("Unable to unlink " + cmdparams[0] + ", region not found.");
535 }
536 }
537
538 private void LoadXmlLinkFile(string[] cmdparams)
539 {
540 //use http://www.hgurl.com/hypergrid.xml for test
541 try
542 {
543 XmlReader r = XmlReader.Create(cmdparams[0]);
544 XmlConfigSource cs = new XmlConfigSource(r);
545 string[] excludeSections = null;
546
547 if (cmdparams.Length == 2)
548 {
549 if (cmdparams[1].ToLower().StartsWith("excludelist:"))
550 {
551 string excludeString = cmdparams[1].ToLower();
552 excludeString = excludeString.Remove(0, 12);
553 char[] splitter = { ';' };
554
555 excludeSections = excludeString.Split(splitter);
556 }
557 }
558
559 for (int i = 0; i < cs.Configs.Count; i++)
560 {
561 bool skip = false;
562 if ((excludeSections != null) && (excludeSections.Length > 0))
563 {
564 for (int n = 0; n < excludeSections.Length; n++)
565 {
566 if (excludeSections[n] == cs.Configs[i].Name.ToLower())
567 {
568 skip = true;
569 break;
570 }
571 }
572 }
573 if (!skip)
574 {
575 ReadLinkFromConfig(cs.Configs[i]);
576 }
577 }
578 }
579 catch (Exception e)
580 {
581 m_log.Error(e.ToString());
582 }
583 }
584
585
586 private void ReadLinkFromConfig(IConfig config)
587 {
588 GridRegion regInfo;
589 int xloc, yloc;
590 uint externalPort;
591 string externalHostName;
592 uint realXLoc, realYLoc;
593
594 xloc = Convert.ToInt32(config.GetString("xloc", "0"));
595 yloc = Convert.ToInt32(config.GetString("yloc", "0"));
596 externalPort = Convert.ToUInt32(config.GetString("externalPort", "0"));
597 externalHostName = config.GetString("externalHostName", "");
598 realXLoc = Convert.ToUInt32(config.GetString("real-xloc", "0"));
599 realYLoc = Convert.ToUInt32(config.GetString("real-yloc", "0"));
600
601 if (m_enableAutoMapping)
602 {
603 xloc = (int)((xloc % 100) + m_autoMappingX);
604 yloc = (int)((yloc % 100) + m_autoMappingY);
605 }
606
607 if (((realXLoc == 0) && (realYLoc == 0)) ||
608 (((realXLoc - xloc < 3896) || (xloc - realXLoc < 3896)) &&
609 ((realYLoc - yloc < 3896) || (yloc - realYLoc < 3896))))
610 {
611 xloc = xloc * (int)Constants.RegionSize;
612 yloc = yloc * (int)Constants.RegionSize;
613 string reason = string.Empty;
614 if (TryCreateLink(UUID.Zero, xloc, yloc, "", externalPort,
615 externalHostName, out regInfo, out reason))
616 {
617 regInfo.RegionName = config.GetString("localName", "");
618 }
619 else
620 MainConsole.Instance.Output("Unable to link " + externalHostName + ": " + reason);
621 }
622 }
623
624
625 private void LinkRegionCmdUsage()
626 {
627 MainConsole.Instance.Output("Usage: link-region <Xloc> <Yloc> <HostName>:<HttpPort>[:<RemoteRegionName>]");
628 MainConsole.Instance.Output("Usage: link-region <Xloc> <Yloc> <HostName> <HttpPort> [<LocalName>]");
629 MainConsole.Instance.Output("Usage: link-region <URI_of_xml> [<exclude>]");
630 }
631
632 private void UnlinkRegionCmdUsage()
633 {
634 MainConsole.Instance.Output("Usage: unlink-region <HostName>:<HttpPort>");
635 MainConsole.Instance.Output("Usage: unlink-region <LocalName>");
636 }
637
638 #endregion
639
640 }
641}