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