diff --git a/Programs/Simian/Extensions/GridLocal.cs b/Programs/Simian/Extensions/GridLocal.cs index 097eeee1..746be501 100644 --- a/Programs/Simian/Extensions/GridLocal.cs +++ b/Programs/Simian/Extensions/GridLocal.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Security.Cryptography.X509Certificates; using ExtensionLoader; using OpenMetaverse; @@ -7,6 +9,7 @@ namespace Simian public class GridLocal : IExtension, IGridProvider { Simian server; + DoubleDictionary grid = new DoubleDictionary(); public GridLocal() { @@ -22,41 +25,52 @@ namespace Simian { } - public bool TryRegisterGridSpace(RegionInfo region, out UUID regionID) + public bool TryRegisterGridSpace(RegionInfo regionInfo, X509Certificate2 regionCert, out UUID regionID) + { + // No need to check the certificate since the requests are all local + + // Check the coordinates + if (!grid.ContainsKey(regionInfo.Handle)) + { + regionID = UUID.Random(); + grid.Add(regionInfo.Handle, regionID, regionInfo); + return true; + } + else + { + regionID = UUID.Zero; + return false; + } + } + + public bool TryRegisterAnyGridSpace(RegionInfo region, X509Certificate2 regionCert, bool isolated, out UUID regionID) { regionID = UUID.Zero; return false; } - public bool TryRegisterAnyGridSpace(RegionInfo region, bool isolated, out UUID regionID) + public bool UnregisterGridSpace(UUID regionID, X509Certificate2 regionCert) { - regionID = UUID.Zero; - return false; + return grid.Remove(regionID); } - public bool UnregisterGridSpace(RegionInfo region) - { - return false; - } - - public void RegionUpdate(RegionInfo region) + public void RegionUpdate(UUID regionID, X509Certificate2 regionCert) { } - public void RegionHeartbeat(RegionInfo region) + public void RegionHeartbeat(UUID regionID, X509Certificate2 regionCert) { } - public bool TryGetRegion(UUID regionID, out RegionInfo region) + public bool TryGetRegion(UUID regionID, X509Certificate2 regionCert, out RegionInfo region) { - region = null; - return false; + return grid.TryGetValue(regionID, out region); } - public bool TryGetRegion(uint x, uint y, out RegionInfo region) + public bool TryGetRegion(uint regionX, uint regionY, X509Certificate2 regionCert, out RegionInfo region) { - region = null; - return false; + ulong handle = Utils.UIntsToLong(256 * regionX, 256 * regionY); + return grid.TryGetValue(handle, out region); } public ISceneProvider GetDefaultLocalScene() diff --git a/Programs/Simian/Extensions/SceneManager.cs b/Programs/Simian/Extensions/SceneManager.cs index 0f85ea1a..403c6de9 100644 --- a/Programs/Simian/Extensions/SceneManager.cs +++ b/Programs/Simian/Extensions/SceneManager.cs @@ -124,12 +124,13 @@ namespace Simian { } - public bool Start(Simian server, string name, IPEndPoint endpoint, uint regionX, uint regionY, + public bool Start(Simian server, string name, IPEndPoint endpoint, UUID regionID, uint regionX, uint regionY, string defaultTerrainFile, int staticObjects, int physicalObjects) { this.server = server; this.regionName = name; this.endpoint = endpoint; + this.regionID = regionID; // Set the properties because this will automatically update the regionHandle RegionX = regionX; @@ -176,6 +177,8 @@ namespace Simian if (!String.IsNullOrEmpty(defaultTerrainFile)) LoadTerrain(Simian.DATA_DIR + defaultTerrainFile); + Logger.Log(String.Format("Region {0} online at ({1},{2}) listening on {3}", name, regionX, regionY, endpoint), + Helpers.LogLevel.Info); return true; } diff --git a/Programs/Simian/Interfaces/IGridProvider.cs b/Programs/Simian/Interfaces/IGridProvider.cs index 6d5610f2..a5da1ff0 100644 --- a/Programs/Simian/Interfaces/IGridProvider.cs +++ b/Programs/Simian/Interfaces/IGridProvider.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Security.Cryptography.X509Certificates; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -88,7 +89,7 @@ namespace Simian public interface IGridProvider { - bool TryRegisterGridSpace(RegionInfo region, out UUID regionID); + bool TryRegisterGridSpace(RegionInfo regionInfo, X509Certificate2 regionCert, out UUID regionID); /// /// Attempts to register any available space closest to the given grid /// coordinates @@ -96,19 +97,21 @@ namespace Simian /// Information about the region to be registered. /// The X, Y, and Handle values may be modified if the exact grid /// coordinate requested is not available + /// SSL client certificate file for the region. + /// Must be signed by the grid server /// If true, the registered grid space must not /// be adjacent to any other regions /// The unique identifier of the registered /// region upon success. This will also be assigned to region.ID /// True if the registration was successful, otherwise false - bool TryRegisterAnyGridSpace(RegionInfo region, bool isolated, out UUID regionID); - bool UnregisterGridSpace(RegionInfo region); + bool TryRegisterAnyGridSpace(RegionInfo region, X509Certificate2 regionCert, bool isolated, out UUID regionID); + bool UnregisterGridSpace(UUID regionID, X509Certificate2 regionCert); - void RegionUpdate(RegionInfo region); - void RegionHeartbeat(RegionInfo region); + void RegionUpdate(UUID regionID, X509Certificate2 regionCert); + void RegionHeartbeat(UUID regionID, X509Certificate2 regionCert); - bool TryGetRegion(UUID regionID, out RegionInfo region); - bool TryGetRegion(uint x, uint y, out RegionInfo region); + bool TryGetRegion(UUID regionID, X509Certificate2 regionCert, out RegionInfo region); + bool TryGetRegion(uint regionX, uint regionY, X509Certificate2 regionCert, out RegionInfo region); /// /// Gets the default scene running on this server diff --git a/Programs/Simian/Interfaces/ISceneProvider.cs b/Programs/Simian/Interfaces/ISceneProvider.cs index 533855bc..205afe91 100644 --- a/Programs/Simian/Interfaces/ISceneProvider.cs +++ b/Programs/Simian/Interfaces/ISceneProvider.cs @@ -149,7 +149,7 @@ namespace Simian uint TerrainPatchCountWidth { get; } uint TerrainPatchCountHeight { get; } - bool Start(Simian server, string name, IPEndPoint endpoint, uint regionX, uint regionY, string defaultTerrainFile, int staticObjects, int physicalObjects); + bool Start(Simian server, string name, IPEndPoint endpoint, UUID regionID, uint regionX, uint regionY, string defaultTerrainFile, int staticObjects, int physicalObjects); void Stop(); void ObjectAddOrUpdate(object sender, SimulationObject obj, UUID ownerID, int scriptStartParam, PrimFlags creatorFlags, UpdateFlags updateFlags); diff --git a/Programs/Simian/Simian.cs b/Programs/Simian/Simian.cs index b666f38b..3cb2e2fd 100644 --- a/Programs/Simian/Simian.cs +++ b/Programs/Simian/Simian.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Net; +using System.Net.Sockets; using System.IO; using System.Text; using System.Xml; @@ -23,6 +24,7 @@ namespace Simian public const string REGION_CONFIG_DIR = DATA_DIR + "RegionConfig/"; public const string ASSET_CACHE_DIR = DATA_DIR + "AssetCache/"; public const string DEFAULT_ASSET_DIR = DATA_DIR + "DefaultAssets/"; + public const int DEFAULT_UDP_PORT = 9000; public Uri HttpUri; public HttpListener HttpServer; @@ -53,6 +55,8 @@ namespace Simian public bool Start() { + IPHostEntry entry; + IPAddress address; IConfig httpConfig; try @@ -74,17 +78,26 @@ namespace Simian int port = httpConfig.GetInt("ListenPort"); string hostname = httpConfig.GetString("Hostname", null); string sslCertFile = httpConfig.GetString("SSLCertFile", null); - IPAddress address = IPAddress.Any; if (String.IsNullOrEmpty(hostname)) { hostname = Dns.GetHostName(); + entry = Dns.GetHostEntry(hostname); + address = IPAddress.Any; } else { - IPHostEntry entry = Dns.GetHostEntry(hostname); + entry = Dns.GetHostEntry(hostname); if (entry != null && entry.AddressList.Length > 0) + { address = entry.AddressList[0]; + } + else + { + Logger.Log("Could not resolve an IP address from hostname " + hostname + ", binding to all interfaces", + Helpers.LogLevel.Warning); + address = IPAddress.Any; + } } if (!String.IsNullOrEmpty(sslCertFile)) @@ -173,25 +186,80 @@ namespace Simian uint regionX, regionY; UInt32.TryParse(regionConfig.GetString("RegionX", "0"), out regionX); UInt32.TryParse(regionConfig.GetString("RegionY", "0"), out regionY); + string certFile = regionConfig.GetString("RegionCertificate", null); int staticObjectLimit = regionConfig.GetInt("StaticObjectLimit", 0); int physicalObjectLimit = regionConfig.GetInt("PhysicalObjectLimit", 0); - if (String.IsNullOrEmpty(name) || regionX == 0 || regionY == 0) + if (String.IsNullOrEmpty(name) || regionX == 0 || regionY == 0 || String.IsNullOrEmpty(certFile)) { Logger.Log("Incomplete information in " + configFiles[i] + ", skipping", Helpers.LogLevel.Warning); continue; } - // Get the IPEndPoint for this region - IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 9000); + #region IPEndPoint Assignment + + IPEndPoint endpoint; + + if (udpPort != 0) + { + endpoint = new IPEndPoint(address, udpPort); + } + else + { + udpPort = DEFAULT_UDP_PORT; + + while (true) + { + endpoint = new IPEndPoint(address, udpPort); + Socket udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + try + { + udpSocket.Bind(endpoint); + udpSocket.Close(); + break; + } + catch (SocketException) + { + ++udpPort; + } + } + } + + #endregion IPEndPoint Assignment + + #region Grid Registration + + X509Certificate2 regionCert; + + try + { + regionCert = new X509Certificate2(DATA_DIR + certFile); + } + catch (Exception) + { + Logger.Log("Failed to load region certificate file from " + certFile, Helpers.LogLevel.Error); + continue; + } + + RegionInfo info = new RegionInfo(); + info.Handle = Utils.UIntsToLong(256 * regionX, 256 * regionY); + info.HttpServer = HttpUri; + info.IPAndPort = endpoint; + info.Name = name; + info.Online = true; + + if (!Grid.TryRegisterGridSpace(info, regionCert, out info.ID)) + { + Logger.Log("Failed to register grid space for region " + name, Helpers.LogLevel.Error); + continue; + } + + #endregion Grid Registration // TODO: Support non-SceneManager scenes? ISceneProvider scene = new SceneManager(); - scene.Start(this, name, endpoint, regionX, regionY, defaultTerrain, staticObjectLimit, physicalObjectLimit); + scene.Start(this, name, endpoint, info.ID, regionX, regionY, defaultTerrain, staticObjectLimit, physicalObjectLimit); Scenes.Add(scene); - - // FIXME: Use IGridProvider to actually register the scenes into spaces - break; } } catch (Exception ex) diff --git a/bin/SimianData/JunkRegionCertificate.p12 b/bin/SimianData/JunkRegionCertificate.p12 new file mode 100644 index 00000000..808a2ad9 Binary files /dev/null and b/bin/SimianData/JunkRegionCertificate.p12 differ diff --git a/bin/SimianData/RegionConfig/Baboon.ini b/bin/SimianData/RegionConfig/Baboon.ini index 05b6b973..068b586c 100644 --- a/bin/SimianData/RegionConfig/Baboon.ini +++ b/bin/SimianData/RegionConfig/Baboon.ini @@ -9,8 +9,13 @@ Name = Baboon ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 6999 +RegionY = 7001 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Capuchin.ini b/bin/SimianData/RegionConfig/Capuchin.ini index ce5dd03f..2eb30115 100644 --- a/bin/SimianData/RegionConfig/Capuchin.ini +++ b/bin/SimianData/RegionConfig/Capuchin.ini @@ -9,8 +9,13 @@ Name = Capuchin ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 7000 +RegionY = 7001 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Chimpanzee.ini b/bin/SimianData/RegionConfig/Chimpanzee.ini index 31c83c40..a20d29d2 100644 --- a/bin/SimianData/RegionConfig/Chimpanzee.ini +++ b/bin/SimianData/RegionConfig/Chimpanzee.ini @@ -9,8 +9,13 @@ Name = Chimpanzee ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 7001 +RegionY = 7001 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Macaque.ini b/bin/SimianData/RegionConfig/Macaque.ini index f51ea252..c221348d 100644 --- a/bin/SimianData/RegionConfig/Macaque.ini +++ b/bin/SimianData/RegionConfig/Macaque.ini @@ -9,8 +9,13 @@ Name = Macaque ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 6999 +RegionY = 7000 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Mandrill.ini b/bin/SimianData/RegionConfig/Mandrill.ini index e7fa09bd..7e596be8 100644 --- a/bin/SimianData/RegionConfig/Mandrill.ini +++ b/bin/SimianData/RegionConfig/Mandrill.ini @@ -9,8 +9,13 @@ Name = Mandrill ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 7000 +RegionY = 7000 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Marmoset.ini b/bin/SimianData/RegionConfig/Marmoset.ini index 20bc92b2..efb9b017 100644 --- a/bin/SimianData/RegionConfig/Marmoset.ini +++ b/bin/SimianData/RegionConfig/Marmoset.ini @@ -9,8 +9,13 @@ Name = Marmoset ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 7001 +RegionY = 7000 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Orangutan.ini b/bin/SimianData/RegionConfig/Orangutan.ini index 80885957..8e5208e1 100644 --- a/bin/SimianData/RegionConfig/Orangutan.ini +++ b/bin/SimianData/RegionConfig/Orangutan.ini @@ -9,8 +9,13 @@ Name = Orangutan ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 6999 +RegionY = 6999 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Spider Monkey.ini b/bin/SimianData/RegionConfig/Spider Monkey.ini index 814211fa..4acb46ba 100644 --- a/bin/SimianData/RegionConfig/Spider Monkey.ini +++ b/bin/SimianData/RegionConfig/Spider Monkey.ini @@ -9,8 +9,13 @@ Name = Spider Monkey ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 7000 +RegionY = 6999 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/RegionConfig/Tamarin.ini b/bin/SimianData/RegionConfig/Tamarin.ini index d48da687..b30e4e02 100644 --- a/bin/SimianData/RegionConfig/Tamarin.ini +++ b/bin/SimianData/RegionConfig/Tamarin.ini @@ -9,8 +9,13 @@ Name = Tamarin ; Coordinates of this simulator on the grid. If these values are not present, ; the server will automatically assign grid coordinates -RegionX = 1000 -RegionY = 1000 +RegionX = 7001 +RegionY = 6999 + +; The region certificate used to identify this region. This is a PKCS#12 file +; that must be signed (usually generated) by the grid server that this region +; belongs to. This path is relative to the SimianData directory +RegionCertificate = JunkRegionCertificate.p12 ; The default terrain file to use if no terrain data has been stored for this ; region yet. This path is relative to the SimianData directory diff --git a/bin/SimianData/Simian.ini b/bin/SimianData/Simian.ini index bb618082..925525e1 100644 --- a/bin/SimianData/Simian.ini +++ b/bin/SimianData/Simian.ini @@ -74,9 +74,6 @@ CapsManager ; Various avatar-related functions including appearance, animations and sounds AvatarManager -; Texture downloads -ImageDelivery - ; Other asset downloads TransferManager @@ -84,11 +81,6 @@ TransferManager ; is present that makes use of prim mesh data. RenderingPluginMesher -; A simple physics engine for avatar movement. Supports walking, flying, and -; swimming as well as avatar-avatar collisions. Does not support avatar-prim -; or prim-prim collisions. -Movement - ; A simple physics engine with good (but slow) implementations of the ; interfaces. PhysicsSimple @@ -110,6 +102,14 @@ XScriptEngine ; Allows LSL functions to be called through chat ScriptConsole +; Texture downloads +;ImageDelivery + +; A simple physics engine for avatar movement. Supports walking, flying, and +; swimming as well as avatar-avatar collisions. Does not support avatar-prim +; or prim-prim collisions. +;Movement + ; Periscope allows you to proxy a foreign grid simulator into the local Simian ; using a libOpenMetaverse bot. The first person to login to Simian will become ; the master agent, who's movement is tethered to the bot's movement. Any other @@ -117,7 +117,7 @@ ScriptConsole ; agent is seeing through the periscope. If you enable this extension, disable ; ImageDelivery and Movement as Periscope has its own implementations of those ; extensions -;Periscope +Periscope ; ; ---Linden Client Extensions---