OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
SimianGridServiceConnector.cs
Go to the documentation of this file.
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 
28 using System;
29 using System.Collections.Generic;
30 using System.Collections.Specialized;
31 using System.Drawing;
32 using System.Drawing.Imaging;
33 using System.IO;
34 using System.Net;
35 using System.Reflection;
36 using log4net;
37 using Mono.Addins;
38 using Nini.Config;
39 using OpenSim.Framework;
40 using OpenSim.Region.Framework.Interfaces;
41 using OpenSim.Region.Framework.Scenes;
42 using OpenSim.Services.Interfaces;
43 using OpenMetaverse;
44 using OpenMetaverse.StructuredData;
45 
47 
48 namespace OpenSim.Services.Connectors.SimianGrid
49 {
55  {
56  private static readonly ILog m_log =
57  LogManager.GetLogger(
58  MethodBase.GetCurrentMethod().DeclaringType);
59 
60  private string m_ServerURI = String.Empty;
61 // private bool m_Enabled = false;
62 
64  public SimianGridServiceConnector(string serverURI)
65  {
66  m_ServerURI = serverURI.TrimEnd('/');
67  }
68 
69  public SimianGridServiceConnector(IConfigSource source)
70  {
71  CommonInit(source);
72  }
73 
74  public void Initialise(IConfigSource source)
75  {
76  CommonInit(source);
77  }
78 
79  private void CommonInit(IConfigSource source)
80  {
81  IConfig gridConfig = source.Configs["GridService"];
82  if (gridConfig == null)
83  {
84  m_log.Error("[SIMIAN GRID CONNECTOR]: GridService missing from OpenSim.ini");
85  throw new Exception("Grid connector init error");
86  }
87 
88  string serviceUrl = gridConfig.GetString("GridServerURI");
89  if (String.IsNullOrEmpty(serviceUrl))
90  {
91  m_log.Error("[SIMIAN GRID CONNECTOR]: No Server URI named in section GridService");
92  throw new Exception("Grid connector init error");
93  }
94 
95  if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
96  serviceUrl = serviceUrl + '/';
97  m_ServerURI = serviceUrl;
98 // m_Enabled = true;
99  }
100 
101  #region IGridService
102 
103  public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
104  {
105  IPEndPoint ext = regionInfo.ExternalEndPoint;
106  if (ext == null) return "Region registration for " + regionInfo.RegionName + " failed: Could not resolve EndPoint";
107  // Generate and upload our map tile in PNG format to the SimianGrid AddMapTile service
108 // Scene scene;
109 // if (m_scenes.TryGetValue(regionInfo.RegionID, out scene))
110 // UploadMapTile(scene);
111 // else
112 // m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113 
114  Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
115  Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight);
116 
117  OSDMap extraData = new OSDMap
118  {
119  { "ServerURI", OSD.FromString(regionInfo.ServerURI) },
120  { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) },
121  { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) },
122  { "ExternalAddress", OSD.FromString(ext.Address.ToString()) },
123  { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) },
124  { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) },
125  { "Access", OSD.FromInteger(regionInfo.Access) },
126  { "RegionSecret", OSD.FromString(regionInfo.RegionSecret) },
127  { "EstateOwner", OSD.FromUUID(regionInfo.EstateOwner) },
128  { "Token", OSD.FromString(regionInfo.Token) }
129  };
130 
131  NameValueCollection requestArgs = new NameValueCollection
132  {
133  { "RequestMethod", "AddScene" },
134  { "SceneID", regionInfo.RegionID.ToString() },
135  { "Name", regionInfo.RegionName },
136  { "MinPosition", minPosition.ToString() },
137  { "MaxPosition", maxPosition.ToString() },
138  { "Address", regionInfo.ServerURI },
139  { "Enabled", "1" },
140  { "ExtraData", OSDParser.SerializeJsonString(extraData) }
141  };
142 
143  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
144  if (response["Success"].AsBoolean())
145  return String.Empty;
146  else
147  return "Region registration for " + regionInfo.RegionName + " failed: " + response["Message"].AsString();
148  }
149 
150  public bool DeregisterRegion(UUID regionID)
151  {
152  NameValueCollection requestArgs = new NameValueCollection
153  {
154  { "RequestMethod", "AddScene" },
155  { "SceneID", regionID.ToString() },
156  { "Enabled", "0" }
157  };
158 
159  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
160  bool success = response["Success"].AsBoolean();
161 
162  if (!success)
163  m_log.Warn("[SIMIAN GRID CONNECTOR]: Region deregistration for " + regionID + " failed: " + response["Message"].AsString());
164 
165  return success;
166  }
167 
168  public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
169  {
170  GridRegion region = GetRegionByUUID(scopeID, regionID);
171 
172  int NEIGHBOR_RADIUS = Math.Max(region.RegionSizeX, region.RegionSizeY) / 2;
173 
174  if (region != null)
175  {
176  List<GridRegion> regions = GetRegionRange(scopeID,
177  region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + region.RegionSizeX + NEIGHBOR_RADIUS,
178  region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + region.RegionSizeY + NEIGHBOR_RADIUS);
179 
180  for (int i = 0; i < regions.Count; i++)
181  {
182  if (regions[i].RegionID == regionID)
183  {
184  regions.RemoveAt(i);
185  break;
186  }
187  }
188 
189 // m_log.Debug("[SIMIAN GRID CONNECTOR]: Found " + regions.Count + " neighbors for region " + regionID);
190  return regions;
191  }
192 
193  return new List<GridRegion>(0);
194  }
195 
196  public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
197  {
198  NameValueCollection requestArgs = new NameValueCollection
199  {
200  { "RequestMethod", "GetScene" },
201  { "SceneID", regionID.ToString() }
202  };
203 
204  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region with uuid {0}",regionID.ToString());
205 
206  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
207  if (response["Success"].AsBoolean())
208  {
209  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] uuid request successful {0}",response["Name"].AsString());
210  return ResponseToGridRegion(response);
211  }
212  else
213  {
214  m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region " + regionID);
215  return null;
216  }
217  }
218 
219  public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
220  {
221  // Go one meter in from the requested x/y coords to avoid requesting a position
222  // that falls on the border of two sims
223  Vector3d position = new Vector3d(x + 1, y + 1, 0.0);
224 
225  NameValueCollection requestArgs = new NameValueCollection
226  {
227  { "RequestMethod", "GetScene" },
228  { "Position", position.ToString() },
229  { "Enabled", "1" }
230  };
231 
232  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request grid at {0}",position.ToString());
233 
234  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
235  if (response["Success"].AsBoolean())
236  {
237  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] position request successful {0}",response["Name"].AsString());
238  return ResponseToGridRegion(response);
239  }
240  else
241  {
242  // m_log.InfoFormat("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}",
243  // Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
244  return null;
245  }
246  }
247 
248  public GridRegion GetRegionByName(UUID scopeID, string regionName)
249  {
250  List<GridRegion> regions = GetRegionsByName(scopeID, regionName, 1);
251 
252  m_log.Debug("[SIMIAN GRID CONNECTOR]: Got " + regions.Count + " matches for region name " + regionName);
253 
254  if (regions.Count > 0)
255  return regions[0];
256 
257  return null;
258  }
259 
260  public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
261  {
262  List<GridRegion> foundRegions = new List<GridRegion>();
263 
264  NameValueCollection requestArgs = new NameValueCollection
265  {
266  { "RequestMethod", "GetScenes" },
267  { "NameQuery", name },
268  { "Enabled", "1" }
269  };
270  if (maxNumber > 0)
271  requestArgs["MaxNumber"] = maxNumber.ToString();
272 
273  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions with name {0}",name);
274 
275  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
276  if (response["Success"].AsBoolean())
277  {
278  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
279 
280  OSDArray array = response["Scenes"] as OSDArray;
281  if (array != null)
282  {
283  for (int i = 0; i < array.Count; i++)
284  {
285  GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
286  if (region != null)
287  foundRegions.Add(region);
288  }
289  }
290  }
291 
292  return foundRegions;
293  }
294 
295  public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
296  {
297  List<GridRegion> foundRegions = new List<GridRegion>();
298 
299  Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
300  Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
301 
302  NameValueCollection requestArgs = new NameValueCollection
303  {
304  { "RequestMethod", "GetScenes" },
305  { "MinPosition", minPosition.ToString() },
306  { "MaxPosition", maxPosition.ToString() },
307  { "Enabled", "1" }
308  };
309 
310  //m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions by range {0} to {1}",minPosition.ToString(),maxPosition.ToString());
311 
312 
313  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
314  if (response["Success"].AsBoolean())
315  {
316  OSDArray array = response["Scenes"] as OSDArray;
317  if (array != null)
318  {
319  for (int i = 0; i < array.Count; i++)
320  {
321  GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
322  if (region != null)
323  foundRegions.Add(region);
324  }
325  }
326  }
327 
328  return foundRegions;
329  }
330 
331  public List<GridRegion> GetDefaultRegions(UUID scopeID)
332  {
333  // TODO: Allow specifying the default grid location
334  const int DEFAULT_X = 1000 * 256;
335  const int DEFAULT_Y = 1000 * 256;
336 
337  GridRegion defRegion = GetNearestRegion(new Vector3d(DEFAULT_X, DEFAULT_Y, 0.0), true);
338  if (defRegion != null)
339  return new List<GridRegion>(1) { defRegion };
340  else
341  return new List<GridRegion>(0);
342  }
343 
344  public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
345  {
346  // TODO: Allow specifying the default grid location
347  return GetDefaultRegions(scopeID);
348  }
349 
350  public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
351  {
352  GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true);
353  if (defRegion != null)
354  return new List<GridRegion>(1) { defRegion };
355  else
356  return new List<GridRegion>(0);
357  }
358 
359  public List<GridRegion> GetHyperlinks(UUID scopeID)
360  {
361  List<GridRegion> foundRegions = new List<GridRegion>();
362 
363  NameValueCollection requestArgs = new NameValueCollection
364  {
365  { "RequestMethod", "GetScenes" },
366  { "HyperGrid", "true" },
367  { "Enabled", "1" }
368  };
369 
370  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
371  if (response["Success"].AsBoolean())
372  {
373  // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
374 
375  OSDArray array = response["Scenes"] as OSDArray;
376  if (array != null)
377  {
378  for (int i = 0; i < array.Count; i++)
379  {
380  GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
381  if (region != null)
382  foundRegions.Add(region);
383  }
384  }
385  }
386 
387  return foundRegions;
388  }
389 
390  public int GetRegionFlags(UUID scopeID, UUID regionID)
391  {
392  NameValueCollection requestArgs = new NameValueCollection
393  {
394  { "RequestMethod", "GetScene" },
395  { "SceneID", regionID.ToString() }
396  };
397 
398  m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region flags for {0}",regionID.ToString());
399 
400  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
401  if (response["Success"].AsBoolean())
402  {
403  OSDMap extraData = response["ExtraData"] as OSDMap;
404  int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0;
405  int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.Hyperlink : 0;
406  int flags = enabled | hypergrid;
407  m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags);
408  return flags;
409  }
410  else
411  {
412  m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region " + regionID + " during region flags check");
413  return -1;
414  }
415  }
416 
417  public Dictionary<string, object> GetExtraFeatures()
418  {
420  Dictionary<string, object> extraFeatures = new Dictionary<string, object>();
421  return extraFeatures;
422  }
423 
424  #endregion IGridService
425 
426  private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled)
427  {
428  NameValueCollection requestArgs = new NameValueCollection
429  {
430  { "RequestMethod", "GetScene" },
431  { "Position", position.ToString() },
432  { "FindClosest", "1" }
433  };
434  if (onlyEnabled)
435  requestArgs["Enabled"] = "1";
436 
437  OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
438  if (response["Success"].AsBoolean())
439  {
440  return ResponseToGridRegion(response);
441  }
442  else
443  {
444  m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at " + position);
445  return null;
446  }
447  }
448 
449  private GridRegion ResponseToGridRegion(OSDMap response)
450  {
451  if (response == null)
452  return null;
453 
454  OSDMap extraData = response["ExtraData"] as OSDMap;
455  if (extraData == null)
456  return null;
457 
458  GridRegion region = new GridRegion();
459 
460  region.RegionID = response["SceneID"].AsUUID();
461  region.RegionName = response["Name"].AsString();
462 
463  Vector3d minPosition = response["MinPosition"].AsVector3d();
464  Vector3d maxPosition = response["MaxPosition"].AsVector3d();
465  region.RegionLocX = (int)minPosition.X;
466  region.RegionLocY = (int)minPosition.Y;
467 
468  region.RegionSizeX = (int)maxPosition.X - (int)minPosition.X;
469  region.RegionSizeY = (int)maxPosition.Y - (int)minPosition.Y;
470 
471  if ( ! extraData["HyperGrid"] ) {
472  Uri httpAddress = response["Address"].AsUri();
473  region.ExternalHostName = httpAddress.Host;
474  region.HttpPort = (uint)httpAddress.Port;
475 
476  IPAddress internalAddress;
477  IPAddress.TryParse(extraData["InternalAddress"].AsString(), out internalAddress);
478  if (internalAddress == null)
479  internalAddress = IPAddress.Any;
480 
481  region.InternalEndPoint = new IPEndPoint(internalAddress, extraData["InternalPort"].AsInteger());
482  region.TerrainImage = extraData["MapTexture"].AsUUID();
483  region.Access = (byte)extraData["Access"].AsInteger();
484  region.RegionSecret = extraData["RegionSecret"].AsString();
485  region.EstateOwner = extraData["EstateOwner"].AsUUID();
486  region.Token = extraData["Token"].AsString();
487  region.ServerURI = extraData["ServerURI"].AsString();
488  } else {
489  region.ServerURI = response["Address"];
490  }
491 
492  return region;
493  }
494  }
495 }
OpenMetaverse.StructuredData.OSDArray OSDArray
Connects region registration and neighbor lookups to the SimianGrid backend
bool DeregisterRegion(UUID regionID)
Deregister a region with the grid service.
OpenMetaverse.StructuredData.OSDMap OSDMap
string RegisterRegion(UUID scopeID, GridRegion regionInfo)
Register a region with the grid service.
int RegionLocX
The location of this region in meters. DANGER DANGER! Note that this name means something different i...
int RegionLocY
The location of this region in meters. DANGER DANGER! Note that this name means something different i...
OpenSim.Services.Interfaces.GridRegion GridRegion
List< GridRegion > GetNeighbours(UUID scopeID, UUID regionID)
Get information about the regions neighbouring the given co-ordinates (in meters).
List< GridRegion > GetRegionsByName(UUID scopeID, string name, int maxNumber)
Get information about regions starting with the provided name.
List< GridRegion > GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
int GetRegionFlags(UUID scopeID, UUID regionID)
Get internal OpenSimulator region flags.
GridRegion GetRegionByName(UUID scopeID, string regionName)
Get information about a region which exactly matches the name given.
GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
Get the region at the given position (in meters)