diff options
-rw-r--r-- | OpenSim/Grid/GridServer/GridDBService.cs | 303 | ||||
-rw-r--r-- | OpenSim/Grid/GridServer/GridMessagingModule.cs | 101 | ||||
-rw-r--r-- | OpenSim/Grid/GridServer/GridRestModule.cs | 269 | ||||
-rw-r--r-- | OpenSim/Grid/GridServer/GridServerBase.cs | 121 | ||||
-rw-r--r-- | OpenSim/Grid/GridServer/GridXmlRpcModule.cs (renamed from OpenSim/Grid/GridServer/GridManager.cs) | 2126 | ||||
-rw-r--r-- | OpenSim/Grid/GridServer/IGridCore.cs | 13 | ||||
-rw-r--r-- | OpenSim/Grid/GridServer/IGridMessagingModule.cs | 11 |
7 files changed, 1621 insertions, 1323 deletions
diff --git a/OpenSim/Grid/GridServer/GridDBService.cs b/OpenSim/Grid/GridServer/GridDBService.cs new file mode 100644 index 0000000..389cf69 --- /dev/null +++ b/OpenSim/Grid/GridServer/GridDBService.cs | |||
@@ -0,0 +1,303 @@ | |||
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 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 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using System.Xml; | ||
34 | using log4net; | ||
35 | using Nwc.XmlRpc; | ||
36 | using OpenMetaverse; | ||
37 | using OpenSim.Data; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Communications; | ||
40 | using OpenSim.Framework.Servers; | ||
41 | |||
42 | |||
43 | namespace OpenSim.Grid.GridServer | ||
44 | { | ||
45 | public class GridDBService | ||
46 | { | ||
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
48 | |||
49 | private List<IGridDataPlugin> _plugins = new List<IGridDataPlugin>(); | ||
50 | private List<ILogDataPlugin> _logplugins = new List<ILogDataPlugin>(); | ||
51 | |||
52 | /// <summary> | ||
53 | /// Adds a list of grid and log data plugins, as described by | ||
54 | /// `provider' and `connect', to `_plugins' and `_logplugins', | ||
55 | /// respectively. | ||
56 | /// </summary> | ||
57 | /// <param name="provider"> | ||
58 | /// The filename of the inventory server plugin DLL. | ||
59 | /// </param> | ||
60 | /// <param name="connect"> | ||
61 | /// The connection string for the storage backend. | ||
62 | /// </param> | ||
63 | public void AddPlugin(string provider, string connect) | ||
64 | { | ||
65 | _plugins = DataPluginFactory.LoadDataPlugins<IGridDataPlugin>(provider, connect); | ||
66 | _logplugins = DataPluginFactory.LoadDataPlugins<ILogDataPlugin>(provider, connect); | ||
67 | } | ||
68 | |||
69 | public int GetNumberOfPlugins() | ||
70 | { | ||
71 | return _plugins.Count; | ||
72 | } | ||
73 | |||
74 | /// <summary> | ||
75 | /// Logs a piece of information to the database | ||
76 | /// </summary> | ||
77 | /// <param name="target">What you were operating on (in grid server, this will likely be the region UUIDs)</param> | ||
78 | /// <param name="method">Which method is being called?</param> | ||
79 | /// <param name="args">What arguments are being passed?</param> | ||
80 | /// <param name="priority">How high priority is this? 1 = Max, 6 = Verbose</param> | ||
81 | /// <param name="message">The message to log</param> | ||
82 | private void logToDB(string target, string method, string args, int priority, string message) | ||
83 | { | ||
84 | foreach (ILogDataPlugin plugin in _logplugins) | ||
85 | { | ||
86 | try | ||
87 | { | ||
88 | plugin.saveLog("Gridserver", target, method, args, priority, message); | ||
89 | } | ||
90 | catch (Exception) | ||
91 | { | ||
92 | m_log.Warn("[storage]: Unable to write log via " + plugin.Name); | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | /// <summary> | ||
98 | /// Returns a region by argument | ||
99 | /// </summary> | ||
100 | /// <param name="uuid">A UUID key of the region to return</param> | ||
101 | /// <returns>A SimProfileData for the region</returns> | ||
102 | public RegionProfileData GetRegion(UUID uuid) | ||
103 | { | ||
104 | foreach (IGridDataPlugin plugin in _plugins) | ||
105 | { | ||
106 | try | ||
107 | { | ||
108 | return plugin.GetProfileByUUID(uuid); | ||
109 | } | ||
110 | catch (Exception e) | ||
111 | { | ||
112 | m_log.Warn("[storage]: GetRegion - " + e.Message); | ||
113 | } | ||
114 | } | ||
115 | return null; | ||
116 | } | ||
117 | |||
118 | /// <summary> | ||
119 | /// Returns a region by argument | ||
120 | /// </summary> | ||
121 | /// <param name="uuid">A regionHandle of the region to return</param> | ||
122 | /// <returns>A SimProfileData for the region</returns> | ||
123 | public RegionProfileData GetRegion(ulong handle) | ||
124 | { | ||
125 | foreach (IGridDataPlugin plugin in _plugins) | ||
126 | { | ||
127 | try | ||
128 | { | ||
129 | return plugin.GetProfileByHandle(handle); | ||
130 | } | ||
131 | catch (Exception ex) | ||
132 | { | ||
133 | m_log.Debug("[storage]: " + ex.Message); | ||
134 | m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + plugin.Name); | ||
135 | } | ||
136 | } | ||
137 | return null; | ||
138 | } | ||
139 | |||
140 | /// <summary> | ||
141 | /// Returns a region by argument | ||
142 | /// </summary> | ||
143 | /// <param name="regionName">A partial regionName of the region to return</param> | ||
144 | /// <returns>A SimProfileData for the region</returns> | ||
145 | public RegionProfileData GetRegion(string regionName) | ||
146 | { | ||
147 | foreach (IGridDataPlugin plugin in _plugins) | ||
148 | { | ||
149 | try | ||
150 | { | ||
151 | return plugin.GetProfileByString(regionName); | ||
152 | } | ||
153 | catch | ||
154 | { | ||
155 | m_log.Warn("[storage]: Unable to find region " + regionName + " via " + plugin.Name); | ||
156 | } | ||
157 | } | ||
158 | return null; | ||
159 | } | ||
160 | |||
161 | public List<RegionProfileData> GetRegions(uint xmin, uint ymin, uint xmax, uint ymax) | ||
162 | { | ||
163 | List<RegionProfileData> regions = new List<RegionProfileData>(); | ||
164 | |||
165 | foreach (IGridDataPlugin plugin in _plugins) | ||
166 | { | ||
167 | try | ||
168 | { | ||
169 | regions.AddRange(plugin.GetProfilesInRange(xmin, ymin, xmax, ymax)); | ||
170 | } | ||
171 | catch | ||
172 | { | ||
173 | m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | return regions; | ||
178 | } | ||
179 | |||
180 | public List<RegionProfileData> GetRegions(string name, int maxNum) | ||
181 | { | ||
182 | List<RegionProfileData> regions = new List<RegionProfileData>(); | ||
183 | foreach (IGridDataPlugin plugin in _plugins) | ||
184 | { | ||
185 | try | ||
186 | { | ||
187 | int num = maxNum - regions.Count; | ||
188 | List<RegionProfileData> profiles = plugin.GetRegionsByName(name, (uint)num); | ||
189 | if (profiles != null) regions.AddRange(profiles); | ||
190 | } | ||
191 | catch | ||
192 | { | ||
193 | m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | return regions; | ||
198 | } | ||
199 | |||
200 | public void LoginRegion(RegionProfileData sim, RegionProfileData existingSim) | ||
201 | { | ||
202 | foreach (IGridDataPlugin plugin in _plugins) | ||
203 | { | ||
204 | try | ||
205 | { | ||
206 | DataResponse insertResponse; | ||
207 | |||
208 | if (existingSim == null) | ||
209 | { | ||
210 | insertResponse = plugin.AddProfile(sim); | ||
211 | } | ||
212 | else | ||
213 | { | ||
214 | insertResponse = plugin.UpdateProfile(sim); | ||
215 | } | ||
216 | |||
217 | switch (insertResponse) | ||
218 | { | ||
219 | case DataResponse.RESPONSE_OK: | ||
220 | m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); | ||
221 | break; | ||
222 | case DataResponse.RESPONSE_ERROR: | ||
223 | m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); | ||
224 | break; | ||
225 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | ||
226 | m_log.Warn("[LOGIN END]: " + | ||
227 | "Sim login failed (Invalid Credentials): " + sim.regionName); | ||
228 | break; | ||
229 | case DataResponse.RESPONSE_AUTHREQUIRED: | ||
230 | m_log.Warn("[LOGIN END]: " + | ||
231 | "Sim login failed (Authentication Required): " + | ||
232 | sim.regionName); | ||
233 | break; | ||
234 | } | ||
235 | } | ||
236 | catch (Exception e) | ||
237 | { | ||
238 | m_log.Warn("[LOGIN END]: " + | ||
239 | "Unable to login region " + sim.ToString() + " via " + plugin.Name); | ||
240 | m_log.Warn("[LOGIN END]: " + e.ToString()); | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | public DataResponse DeleteRegion(string uuid) | ||
246 | { | ||
247 | DataResponse insertResponse = DataResponse.RESPONSE_ERROR; | ||
248 | foreach (IGridDataPlugin plugin in _plugins) | ||
249 | { | ||
250 | //OpenSim.Data.MySQL.MySQLGridData dbengine = new OpenSim.Data.MySQL.MySQLGridData(); | ||
251 | try | ||
252 | { | ||
253 | //Nice are we not using multiple databases? | ||
254 | //MySQLGridData mysqldata = (MySQLGridData)(plugin); | ||
255 | |||
256 | //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim); | ||
257 | insertResponse = plugin.DeleteProfile(uuid); | ||
258 | } | ||
259 | catch (Exception) | ||
260 | { | ||
261 | m_log.Error("storage Unable to delete region " + uuid + " via " + plugin.Name); | ||
262 | //MainLog.Instance.Warn("storage", e.ToString()); | ||
263 | insertResponse = DataResponse.RESPONSE_ERROR; | ||
264 | } | ||
265 | } | ||
266 | return insertResponse; | ||
267 | } | ||
268 | |||
269 | public string CheckReservations(RegionProfileData theSim, XmlNode authkeynode) | ||
270 | { | ||
271 | foreach (IGridDataPlugin plugin in _plugins) | ||
272 | { | ||
273 | try | ||
274 | { | ||
275 | //Check reservations | ||
276 | ReservationData reserveData = | ||
277 | plugin.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY); | ||
278 | if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) || | ||
279 | (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey)) | ||
280 | { | ||
281 | plugin.AddProfile(theSim); | ||
282 | m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")"); | ||
283 | logToDB(theSim.ToString(), "RestSetSimMethod", String.Empty, 5, | ||
284 | "Region successfully updated and connected to grid."); | ||
285 | } | ||
286 | else | ||
287 | { | ||
288 | m_log.Warn("[grid]: " + | ||
289 | "Unable to update region (RestSetSimMethod): Incorrect reservation auth key."); | ||
290 | // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + "."); | ||
291 | return "Unable to update region (RestSetSimMethod): Incorrect auth key."; | ||
292 | } | ||
293 | } | ||
294 | catch (Exception e) | ||
295 | { | ||
296 | m_log.Warn("[GRID]: GetRegionPlugin Handle " + plugin.Name + " unable to add new sim: " + | ||
297 | e.ToString()); | ||
298 | } | ||
299 | } | ||
300 | return "OK"; | ||
301 | } | ||
302 | } | ||
303 | } | ||
diff --git a/OpenSim/Grid/GridServer/GridMessagingModule.cs b/OpenSim/Grid/GridServer/GridMessagingModule.cs new file mode 100644 index 0000000..348e56c --- /dev/null +++ b/OpenSim/Grid/GridServer/GridMessagingModule.cs | |||
@@ -0,0 +1,101 @@ | |||
1 | using System; | ||
2 | using System.Collections; | ||
3 | using System.Collections.Generic; | ||
4 | using System.Reflection; | ||
5 | using System.Text; | ||
6 | using Nwc.XmlRpc; | ||
7 | using log4net; | ||
8 | using OpenSim.Framework.Servers; | ||
9 | using OpenSim.Framework; | ||
10 | |||
11 | namespace OpenSim.Grid.GridServer | ||
12 | { | ||
13 | public class GridMessagingModule : IGridMessagingModule | ||
14 | { | ||
15 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
16 | |||
17 | protected GridDBService m_gridDBService; | ||
18 | protected IGridCore m_gridCore; | ||
19 | |||
20 | protected GridConfig m_config; | ||
21 | |||
22 | /// <value> | ||
23 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
24 | /// </value> | ||
25 | private string m_opensimVersion; | ||
26 | |||
27 | protected BaseHttpServer m_httpServer; | ||
28 | |||
29 | // This is here so that the grid server can hand out MessageServer settings to regions on registration | ||
30 | private List<MessageServerInfo> _MessageServers = new List<MessageServerInfo>(); | ||
31 | |||
32 | public List<MessageServerInfo> MessageServers | ||
33 | { | ||
34 | get { return _MessageServers; } | ||
35 | } | ||
36 | |||
37 | public GridMessagingModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config) | ||
38 | { | ||
39 | m_opensimVersion = opensimVersion; | ||
40 | m_gridDBService = gridDBService; | ||
41 | m_gridCore = gridCore; | ||
42 | m_config = config; | ||
43 | m_httpServer = m_gridCore.GetHttpServer(); | ||
44 | } | ||
45 | |||
46 | public void Initialise() | ||
47 | { | ||
48 | m_gridCore.RegisterInterface<IGridMessagingModule>(this); | ||
49 | // Message Server ---> Grid Server | ||
50 | m_httpServer.AddXmlRPCHandler("register_messageserver", XmlRPCRegisterMessageServer); | ||
51 | m_httpServer.AddXmlRPCHandler("deregister_messageserver", XmlRPCDeRegisterMessageServer); | ||
52 | |||
53 | } | ||
54 | |||
55 | public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) | ||
56 | { | ||
57 | XmlRpcResponse response = new XmlRpcResponse(); | ||
58 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
59 | Hashtable responseData = new Hashtable(); | ||
60 | |||
61 | if (requestData.Contains("uri")) | ||
62 | { | ||
63 | string URI = (string)requestData["URI"]; | ||
64 | string sendkey = (string)requestData["sendkey"]; | ||
65 | string recvkey = (string)requestData["recvkey"]; | ||
66 | MessageServerInfo m = new MessageServerInfo(); | ||
67 | m.URI = URI; | ||
68 | m.sendkey = sendkey; | ||
69 | m.recvkey = recvkey; | ||
70 | if (!_MessageServers.Contains(m)) | ||
71 | _MessageServers.Add(m); | ||
72 | responseData["responsestring"] = "TRUE"; | ||
73 | response.Value = responseData; | ||
74 | } | ||
75 | return response; | ||
76 | } | ||
77 | |||
78 | public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) | ||
79 | { | ||
80 | XmlRpcResponse response = new XmlRpcResponse(); | ||
81 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
82 | Hashtable responseData = new Hashtable(); | ||
83 | |||
84 | if (requestData.Contains("uri")) | ||
85 | { | ||
86 | string URI = (string)requestData["uri"]; | ||
87 | string sendkey = (string)requestData["sendkey"]; | ||
88 | string recvkey = (string)requestData["recvkey"]; | ||
89 | MessageServerInfo m = new MessageServerInfo(); | ||
90 | m.URI = URI; | ||
91 | m.sendkey = sendkey; | ||
92 | m.recvkey = recvkey; | ||
93 | if (_MessageServers.Contains(m)) | ||
94 | _MessageServers.Remove(m); | ||
95 | responseData["responsestring"] = "TRUE"; | ||
96 | response.Value = responseData; | ||
97 | } | ||
98 | return response; | ||
99 | } | ||
100 | } | ||
101 | } | ||
diff --git a/OpenSim/Grid/GridServer/GridRestModule.cs b/OpenSim/Grid/GridServer/GridRestModule.cs new file mode 100644 index 0000000..1ed0ac1 --- /dev/null +++ b/OpenSim/Grid/GridServer/GridRestModule.cs | |||
@@ -0,0 +1,269 @@ | |||
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 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 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using System.Xml; | ||
34 | using log4net; | ||
35 | using OpenMetaverse; | ||
36 | using OpenSim.Data; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Framework.Communications; | ||
39 | using OpenSim.Framework.Servers; | ||
40 | |||
41 | namespace OpenSim.Grid.GridServer | ||
42 | { | ||
43 | public class GridRestModule | ||
44 | { | ||
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
46 | |||
47 | private GridDBService m_gridDBService; | ||
48 | private IGridCore m_gridCore; | ||
49 | |||
50 | protected GridConfig m_config; | ||
51 | |||
52 | /// <value> | ||
53 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
54 | /// </value> | ||
55 | private string m_opensimVersion; | ||
56 | |||
57 | protected BaseHttpServer m_httpServer; | ||
58 | |||
59 | /// <summary> | ||
60 | /// Constructor | ||
61 | /// </summary> | ||
62 | /// <param name="opensimVersion"> | ||
63 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
64 | /// </param> | ||
65 | public GridRestModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config) | ||
66 | { | ||
67 | m_opensimVersion = opensimVersion; | ||
68 | m_gridDBService = gridDBService; | ||
69 | m_gridCore = gridCore; | ||
70 | m_config = config; | ||
71 | m_httpServer = m_gridCore.GetHttpServer(); | ||
72 | } | ||
73 | |||
74 | public void Initialise() | ||
75 | { | ||
76 | m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/sims/", RestGetSimMethod)); | ||
77 | m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/sims/", RestSetSimMethod)); | ||
78 | |||
79 | m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/regions/", RestGetRegionMethod)); | ||
80 | m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/regions/", RestSetRegionMethod)); | ||
81 | } | ||
82 | |||
83 | /// <summary> | ||
84 | /// Performs a REST Get Operation | ||
85 | /// </summary> | ||
86 | /// <param name="request"></param> | ||
87 | /// <param name="path"></param> | ||
88 | /// <param name="param"></param> | ||
89 | /// <param name="httpRequest">HTTP request header object</param> | ||
90 | /// <param name="httpResponse">HTTP response header object</param> | ||
91 | /// <returns></returns> | ||
92 | public string RestGetRegionMethod(string request, string path, string param, | ||
93 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
94 | { | ||
95 | return RestGetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); | ||
96 | } | ||
97 | |||
98 | /// <summary> | ||
99 | /// Performs a REST Set Operation | ||
100 | /// </summary> | ||
101 | /// <param name="request"></param> | ||
102 | /// <param name="path"></param> | ||
103 | /// <param name="param"></param> | ||
104 | /// <param name="httpRequest">HTTP request header object</param> | ||
105 | /// <param name="httpResponse">HTTP response header object</param> | ||
106 | /// <returns></returns> | ||
107 | public string RestSetRegionMethod(string request, string path, string param, | ||
108 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
109 | { | ||
110 | return RestSetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); | ||
111 | } | ||
112 | |||
113 | /// <summary> | ||
114 | /// Returns information about a sim via a REST Request | ||
115 | /// </summary> | ||
116 | /// <param name="request"></param> | ||
117 | /// <param name="path"></param> | ||
118 | /// <param name="param">A string representing the sim's UUID</param> | ||
119 | /// <param name="httpRequest">HTTP request header object</param> | ||
120 | /// <param name="httpResponse">HTTP response header object</param> | ||
121 | /// <returns>Information about the sim in XML</returns> | ||
122 | public string RestGetSimMethod(string request, string path, string param, | ||
123 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
124 | { | ||
125 | string respstring = String.Empty; | ||
126 | |||
127 | RegionProfileData TheSim; | ||
128 | |||
129 | UUID UUID; | ||
130 | if (UUID.TryParse(param, out UUID)) | ||
131 | { | ||
132 | TheSim = m_gridDBService.GetRegion(UUID); | ||
133 | |||
134 | if (!(TheSim == null)) | ||
135 | { | ||
136 | respstring = "<Root>"; | ||
137 | respstring += "<authkey>" + TheSim.regionSendKey + "</authkey>"; | ||
138 | respstring += "<sim>"; | ||
139 | respstring += "<uuid>" + TheSim.UUID.ToString() + "</uuid>"; | ||
140 | respstring += "<regionname>" + TheSim.regionName + "</regionname>"; | ||
141 | respstring += "<sim_ip>" + TheSim.serverIP + "</sim_ip>"; | ||
142 | respstring += "<sim_port>" + TheSim.serverPort.ToString() + "</sim_port>"; | ||
143 | respstring += "<region_locx>" + TheSim.regionLocX.ToString() + "</region_locx>"; | ||
144 | respstring += "<region_locy>" + TheSim.regionLocY.ToString() + "</region_locy>"; | ||
145 | respstring += "<estate_id>1</estate_id>"; | ||
146 | respstring += "</sim>"; | ||
147 | respstring += "</Root>"; | ||
148 | } | ||
149 | } | ||
150 | else | ||
151 | { | ||
152 | respstring = "<Root>"; | ||
153 | respstring += "<error>Param must be a UUID</error>"; | ||
154 | respstring += "</Root>"; | ||
155 | } | ||
156 | |||
157 | return respstring; | ||
158 | } | ||
159 | |||
160 | /// <summary> | ||
161 | /// Creates or updates a sim via a REST Method Request | ||
162 | /// BROKEN with SQL Update | ||
163 | /// </summary> | ||
164 | /// <param name="request"></param> | ||
165 | /// <param name="path"></param> | ||
166 | /// <param name="param"></param> | ||
167 | /// <param name="httpRequest">HTTP request header object</param> | ||
168 | /// <param name="httpResponse">HTTP response header object</param> | ||
169 | /// <returns>"OK" or an error</returns> | ||
170 | public string RestSetSimMethod(string request, string path, string param, | ||
171 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
172 | { | ||
173 | Console.WriteLine("Processing region update via REST method"); | ||
174 | RegionProfileData theSim; | ||
175 | theSim = m_gridDBService.GetRegion(new UUID(param)); | ||
176 | if (theSim == null) | ||
177 | { | ||
178 | theSim = new RegionProfileData(); | ||
179 | UUID UUID = new UUID(param); | ||
180 | theSim.UUID = UUID; | ||
181 | theSim.regionRecvKey = m_config.SimRecvKey; | ||
182 | } | ||
183 | |||
184 | XmlDocument doc = new XmlDocument(); | ||
185 | doc.LoadXml(request); | ||
186 | XmlNode rootnode = doc.FirstChild; | ||
187 | XmlNode authkeynode = rootnode.ChildNodes[0]; | ||
188 | if (authkeynode.Name != "authkey") | ||
189 | { | ||
190 | return "ERROR! bad XML - expected authkey tag"; | ||
191 | } | ||
192 | |||
193 | XmlNode simnode = rootnode.ChildNodes[1]; | ||
194 | if (simnode.Name != "sim") | ||
195 | { | ||
196 | return "ERROR! bad XML - expected sim tag"; | ||
197 | } | ||
198 | |||
199 | //theSim.regionSendKey = Cfg; | ||
200 | theSim.regionRecvKey = m_config.SimRecvKey; | ||
201 | theSim.regionSendKey = m_config.SimSendKey; | ||
202 | theSim.regionSecret = m_config.SimRecvKey; | ||
203 | theSim.regionDataURI = String.Empty; | ||
204 | theSim.regionAssetURI = m_config.DefaultAssetServer; | ||
205 | theSim.regionAssetRecvKey = m_config.AssetRecvKey; | ||
206 | theSim.regionAssetSendKey = m_config.AssetSendKey; | ||
207 | theSim.regionUserURI = m_config.DefaultUserServer; | ||
208 | theSim.regionUserSendKey = m_config.UserSendKey; | ||
209 | theSim.regionUserRecvKey = m_config.UserRecvKey; | ||
210 | |||
211 | for (int i = 0; i < simnode.ChildNodes.Count; i++) | ||
212 | { | ||
213 | switch (simnode.ChildNodes[i].Name) | ||
214 | { | ||
215 | case "regionname": | ||
216 | theSim.regionName = simnode.ChildNodes[i].InnerText; | ||
217 | break; | ||
218 | |||
219 | case "sim_ip": | ||
220 | theSim.serverIP = simnode.ChildNodes[i].InnerText; | ||
221 | break; | ||
222 | |||
223 | case "sim_port": | ||
224 | theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText); | ||
225 | break; | ||
226 | |||
227 | case "region_locx": | ||
228 | theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); | ||
229 | theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); | ||
230 | break; | ||
231 | |||
232 | case "region_locy": | ||
233 | theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); | ||
234 | theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); | ||
235 | break; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/"; | ||
240 | bool requirePublic = false; | ||
241 | bool requireValid = true; | ||
242 | |||
243 | if (requirePublic && | ||
244 | (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") || | ||
245 | theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") || | ||
246 | theSim.serverIP.StartsWith("255."))) | ||
247 | { | ||
248 | return "ERROR! Servers must register with public addresses."; | ||
249 | } | ||
250 | |||
251 | if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255."))) | ||
252 | { | ||
253 | return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again"; | ||
254 | } | ||
255 | |||
256 | try | ||
257 | { | ||
258 | m_log.Info("[DATA]: " + | ||
259 | "Updating / adding via " + m_gridDBService.GetNumberOfPlugins() + " storage provider(s) registered."); | ||
260 | |||
261 | return m_gridDBService.CheckReservations(theSim, authkeynode); | ||
262 | } | ||
263 | catch (Exception e) | ||
264 | { | ||
265 | return "ERROR! Could not save to database! (" + e.ToString() + ")"; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | } | ||
diff --git a/OpenSim/Grid/GridServer/GridServerBase.cs b/OpenSim/Grid/GridServer/GridServerBase.cs index bcd1403..d4d268c 100644 --- a/OpenSim/Grid/GridServer/GridServerBase.cs +++ b/OpenSim/Grid/GridServer/GridServerBase.cs | |||
@@ -25,6 +25,7 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | ||
28 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
29 | using System.IO; | 30 | using System.IO; |
30 | using System.Reflection; | 31 | using System.Reflection; |
@@ -38,12 +39,18 @@ namespace OpenSim.Grid.GridServer | |||
38 | { | 39 | { |
39 | /// <summary> | 40 | /// <summary> |
40 | /// </summary> | 41 | /// </summary> |
41 | public class GridServerBase : BaseOpenSimServer | 42 | public class GridServerBase : BaseOpenSimServer, IGridCore |
42 | { | 43 | { |
43 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
44 | 45 | ||
45 | protected GridConfig m_config; | 46 | protected GridConfig m_config; |
46 | protected GridManager m_gridManager; | 47 | |
48 | protected GridXmlRpcModule m_gridXmlRpcModule; | ||
49 | protected GridMessagingModule m_gridMessageModule; | ||
50 | protected GridRestModule m_gridRestModule; | ||
51 | |||
52 | protected GridDBService m_gridDBService; | ||
53 | |||
47 | protected List<IGridPlugin> m_plugins = new List<IGridPlugin>(); | 54 | protected List<IGridPlugin> m_plugins = new List<IGridPlugin>(); |
48 | 55 | ||
49 | public void Work() | 56 | public void Work() |
@@ -66,14 +73,14 @@ namespace OpenSim.Grid.GridServer | |||
66 | { | 73 | { |
67 | switch (cmd[0]) | 74 | switch (cmd[0]) |
68 | { | 75 | { |
69 | case "enable": | 76 | case "enable": |
70 | m_config.AllowRegionRegistration = true; | 77 | m_config.AllowRegionRegistration = true; |
71 | m_log.Info("Region registration enabled"); | 78 | m_log.Info("Region registration enabled"); |
72 | break; | 79 | break; |
73 | case "disable": | 80 | case "disable": |
74 | m_config.AllowRegionRegistration = false; | 81 | m_config.AllowRegionRegistration = false; |
75 | m_log.Info("Region registration disabled"); | 82 | m_log.Info("Region registration disabled"); |
76 | break; | 83 | break; |
77 | } | 84 | } |
78 | } | 85 | } |
79 | 86 | ||
@@ -84,32 +91,32 @@ namespace OpenSim.Grid.GridServer | |||
84 | m_log.Info("Region registration enabled."); | 91 | m_log.Info("Region registration enabled."); |
85 | } | 92 | } |
86 | else | 93 | else |
87 | { | 94 | { |
88 | m_log.Info("Region registration disabled."); | 95 | m_log.Info("Region registration disabled."); |
89 | } | 96 | } |
90 | } | 97 | } |
91 | 98 | ||
92 | 99 | ||
93 | protected override void StartupSpecific() | 100 | protected override void StartupSpecific() |
94 | { | 101 | { |
95 | m_config = new GridConfig("GRID SERVER", (Path.Combine(Util.configDir(), "GridServer_Config.xml"))); | 102 | m_config = new GridConfig("GRID SERVER", (Path.Combine(Util.configDir(), "GridServer_Config.xml"))); |
96 | 103 | ||
97 | SetupGridManager(); | ||
98 | |||
99 | m_log.Info("[GRID]: Starting HTTP process"); | 104 | m_log.Info("[GRID]: Starting HTTP process"); |
100 | m_httpServer = new BaseHttpServer(m_config.HttpPort); | 105 | m_httpServer = new BaseHttpServer(m_config.HttpPort); |
101 | 106 | ||
107 | SetupGridServices(); | ||
108 | |||
102 | AddHttpHandlers(); | 109 | AddHttpHandlers(); |
103 | 110 | ||
104 | LoadPlugins(); | 111 | LoadPlugins(); |
105 | 112 | ||
106 | m_httpServer.Start(); | 113 | m_httpServer.Start(); |
107 | 114 | ||
108 | // m_log.Info("[GRID]: Starting sim status checker"); | 115 | // m_log.Info("[GRID]: Starting sim status checker"); |
109 | // | 116 | // |
110 | // Timer simCheckTimer = new Timer(3600000 * 3); // 3 Hours between updates. | 117 | // Timer simCheckTimer = new Timer(3600000 * 3); // 3 Hours between updates. |
111 | // simCheckTimer.Elapsed += new ElapsedEventHandler(CheckSims); | 118 | // simCheckTimer.Elapsed += new ElapsedEventHandler(CheckSims); |
112 | // simCheckTimer.Enabled = true; | 119 | // simCheckTimer.Enabled = true; |
113 | 120 | ||
114 | base.StartupSpecific(); | 121 | base.StartupSpecific(); |
115 | 122 | ||
@@ -130,38 +137,32 @@ namespace OpenSim.Grid.GridServer | |||
130 | 137 | ||
131 | protected void AddHttpHandlers() | 138 | protected void AddHttpHandlers() |
132 | { | 139 | { |
133 | m_httpServer.AddXmlRPCHandler("simulator_login", m_gridManager.XmlRpcSimulatorLoginMethod); | 140 | // Registering Handlers is now done in the components/modules |
134 | m_httpServer.AddXmlRPCHandler("simulator_data_request", m_gridManager.XmlRpcSimulatorDataRequestMethod); | ||
135 | m_httpServer.AddXmlRPCHandler("simulator_after_region_moved", m_gridManager.XmlRpcDeleteRegionMethod); | ||
136 | m_httpServer.AddXmlRPCHandler("map_block", m_gridManager.XmlRpcMapBlockMethod); | ||
137 | m_httpServer.AddXmlRPCHandler("search_for_region_by_name", m_gridManager.XmlRpcSearchForRegionMethod); | ||
138 | |||
139 | // Message Server ---> Grid Server | ||
140 | m_httpServer.AddXmlRPCHandler("register_messageserver", m_gridManager.XmlRPCRegisterMessageServer); | ||
141 | m_httpServer.AddXmlRPCHandler("deregister_messageserver", m_gridManager.XmlRPCDeRegisterMessageServer); | ||
142 | |||
143 | m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/sims/", m_gridManager.RestGetSimMethod)); | ||
144 | m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/sims/", m_gridManager.RestSetSimMethod)); | ||
145 | |||
146 | m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/regions/", m_gridManager.RestGetRegionMethod)); | ||
147 | m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/regions/", m_gridManager.RestSetRegionMethod)); | ||
148 | } | 141 | } |
149 | 142 | ||
150 | protected void LoadPlugins() | 143 | protected void LoadPlugins() |
151 | { | 144 | { |
152 | PluginLoader<IGridPlugin> loader = | 145 | PluginLoader<IGridPlugin> loader = |
153 | new PluginLoader<IGridPlugin> (new GridPluginInitialiser (this)); | 146 | new PluginLoader<IGridPlugin>(new GridPluginInitialiser(this)); |
154 | 147 | ||
155 | loader.Load ("/OpenSim/GridServer"); | 148 | loader.Load("/OpenSim/GridServer"); |
156 | m_plugins = loader.Plugins; | 149 | m_plugins = loader.Plugins; |
157 | } | 150 | } |
158 | 151 | ||
159 | protected virtual void SetupGridManager() | 152 | protected virtual void SetupGridServices() |
160 | { | 153 | { |
161 | m_log.Info("[DATA]: Connecting to Storage Server"); | 154 | m_log.Info("[DATA]: Connecting to Storage Server"); |
162 | m_gridManager = new GridManager(m_version); | 155 | m_gridDBService = new GridDBService(); |
163 | m_gridManager.AddPlugin(m_config.DatabaseProvider, m_config.DatabaseConnect); | 156 | m_gridDBService.AddPlugin(m_config.DatabaseProvider, m_config.DatabaseConnect); |
164 | m_gridManager.Config = m_config; | 157 | |
158 | m_gridMessageModule = new GridMessagingModule(m_version, m_gridDBService, this, m_config); | ||
159 | m_gridMessageModule.Initialise(); | ||
160 | |||
161 | m_gridXmlRpcModule = new GridXmlRpcModule(m_version, m_gridDBService, this, m_config); | ||
162 | m_gridXmlRpcModule.Initialise(); | ||
163 | |||
164 | m_gridRestModule = new GridRestModule(m_version, m_gridDBService, this, m_config); | ||
165 | m_gridRestModule.Initialise(); | ||
165 | } | 166 | } |
166 | 167 | ||
167 | public void CheckSims(object sender, ElapsedEventArgs e) | 168 | public void CheckSims(object sender, ElapsedEventArgs e) |
@@ -205,5 +206,43 @@ namespace OpenSim.Grid.GridServer | |||
205 | { | 206 | { |
206 | foreach (IGridPlugin plugin in m_plugins) plugin.Dispose(); | 207 | foreach (IGridPlugin plugin in m_plugins) plugin.Dispose(); |
207 | } | 208 | } |
209 | |||
210 | #region IGridCore | ||
211 | private readonly Dictionary<Type, object> m_gridInterfaces = new Dictionary<Type, object>(); | ||
212 | |||
213 | /// <summary> | ||
214 | /// Register an interface on this client, should only be called in the constructor. | ||
215 | /// </summary> | ||
216 | /// <typeparam name="T"></typeparam> | ||
217 | /// <param name="iface"></param> | ||
218 | public void RegisterInterface<T>(T iface) | ||
219 | { | ||
220 | lock (m_gridInterfaces) | ||
221 | { | ||
222 | m_gridInterfaces.Add(typeof(T), iface); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | public bool TryGet<T>(out T iface) | ||
227 | { | ||
228 | if (m_gridInterfaces.ContainsKey(typeof(T))) | ||
229 | { | ||
230 | iface = (T)m_gridInterfaces[typeof(T)]; | ||
231 | return true; | ||
232 | } | ||
233 | iface = default(T); | ||
234 | return false; | ||
235 | } | ||
236 | |||
237 | public T Get<T>() | ||
238 | { | ||
239 | return (T)m_gridInterfaces[typeof(T)]; | ||
240 | } | ||
241 | |||
242 | public BaseHttpServer GetHttpServer() | ||
243 | { | ||
244 | return m_httpServer; | ||
245 | } | ||
246 | #endregion | ||
208 | } | 247 | } |
209 | } | 248 | } |
diff --git a/OpenSim/Grid/GridServer/GridManager.cs b/OpenSim/Grid/GridServer/GridXmlRpcModule.cs index 5dc186c..0eb7d1f 100644 --- a/OpenSim/Grid/GridServer/GridManager.cs +++ b/OpenSim/Grid/GridServer/GridXmlRpcModule.cs | |||
@@ -1,1282 +1,844 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSim Project nor the | 12 | * * Neither the name of the OpenSim Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 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 | 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 | 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 | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Reflection; | 32 | using System.Reflection; |
33 | using System.Xml; | 33 | using System.Xml; |
34 | using log4net; | 34 | using log4net; |
35 | using Nwc.XmlRpc; | 35 | using Nwc.XmlRpc; |
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenSim.Data; | 37 | using OpenSim.Data; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Framework.Communications; | 39 | using OpenSim.Framework.Communications; |
40 | using OpenSim.Framework.Servers; | 40 | using OpenSim.Framework.Servers; |
41 | 41 | ||
42 | namespace OpenSim.Grid.GridServer | 42 | namespace OpenSim.Grid.GridServer |
43 | { | 43 | { |
44 | public class GridManager | 44 | public class GridXmlRpcModule |
45 | { | 45 | { |
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
47 | 47 | ||
48 | private List<IGridDataPlugin> _plugins = new List<IGridDataPlugin>(); | 48 | private GridDBService m_gridDBService; |
49 | private List<ILogDataPlugin> _logplugins = new List<ILogDataPlugin>(); | 49 | private IGridCore m_gridCore; |
50 | 50 | ||
51 | // This is here so that the grid server can hand out MessageServer settings to regions on registration | 51 | protected GridConfig m_config; |
52 | private List<MessageServerInfo> _MessageServers = new List<MessageServerInfo>(); | 52 | |
53 | 53 | /// <value> | |
54 | public GridConfig Config; | 54 | /// Used to notify old regions as to which OpenSim version to upgrade to |
55 | 55 | /// </value> | |
56 | /// <value> | 56 | private string m_opensimVersion; |
57 | /// Used to notify old regions as to which OpenSim version to upgrade to | 57 | |
58 | /// </value> | 58 | protected BaseHttpServer m_httpServer; |
59 | private string m_opensimVersion; | 59 | |
60 | 60 | /// <summary> | |
61 | /// <summary> | 61 | /// Constructor |
62 | /// Constructor | 62 | /// </summary> |
63 | /// </summary> | 63 | /// <param name="opensimVersion"> |
64 | /// <param name="opensimVersion"> | 64 | /// Used to notify old regions as to which OpenSim version to upgrade to |
65 | /// Used to notify old regions as to which OpenSim version to upgrade to | 65 | /// </param> |
66 | /// </param> | 66 | public GridXmlRpcModule(string opensimVersion, GridDBService gridDBService, IGridCore gridCore, GridConfig config) |
67 | public GridManager(string opensimVersion) | 67 | { |
68 | { | 68 | m_opensimVersion = opensimVersion; |
69 | m_opensimVersion = opensimVersion; | 69 | m_gridDBService = gridDBService; |
70 | } | 70 | m_gridCore = gridCore; |
71 | 71 | m_config = config; | |
72 | /// <summary> | 72 | m_httpServer = m_gridCore.GetHttpServer(); |
73 | /// Adds a list of grid and log data plugins, as described by | 73 | } |
74 | /// `provider' and `connect', to `_plugins' and `_logplugins', | 74 | |
75 | /// respectively. | 75 | public void Initialise() |
76 | /// </summary> | 76 | { |
77 | /// <param name="provider"> | 77 | m_httpServer.AddXmlRPCHandler("simulator_login", XmlRpcSimulatorLoginMethod); |
78 | /// The filename of the inventory server plugin DLL. | 78 | m_httpServer.AddXmlRPCHandler("simulator_data_request", XmlRpcSimulatorDataRequestMethod); |
79 | /// </param> | 79 | m_httpServer.AddXmlRPCHandler("simulator_after_region_moved", XmlRpcDeleteRegionMethod); |
80 | /// <param name="connect"> | 80 | m_httpServer.AddXmlRPCHandler("map_block", XmlRpcMapBlockMethod); |
81 | /// The connection string for the storage backend. | 81 | m_httpServer.AddXmlRPCHandler("search_for_region_by_name", XmlRpcSearchForRegionMethod); |
82 | /// </param> | 82 | } |
83 | public void AddPlugin(string provider, string connect) | 83 | |
84 | { | 84 | /// <summary> |
85 | _plugins = DataPluginFactory.LoadDataPlugins<IGridDataPlugin>(provider, connect); | 85 | /// Returns a XML String containing a list of the neighbouring regions |
86 | _logplugins = DataPluginFactory.LoadDataPlugins<ILogDataPlugin>(provider, connect); | 86 | /// </summary> |
87 | } | 87 | /// <param name="reqhandle">The regionhandle for the center sim</param> |
88 | 88 | /// <returns>An XML string containing neighbour entities</returns> | |
89 | /// <summary> | 89 | public string GetXMLNeighbours(ulong reqhandle) |
90 | /// Logs a piece of information to the database | 90 | { |
91 | /// </summary> | 91 | string response = String.Empty; |
92 | /// <param name="target">What you were operating on (in grid server, this will likely be the region UUIDs)</param> | 92 | RegionProfileData central_region = m_gridDBService.GetRegion(reqhandle); |
93 | /// <param name="method">Which method is being called?</param> | 93 | RegionProfileData neighbour; |
94 | /// <param name="args">What arguments are being passed?</param> | 94 | for (int x = -1; x < 2; x++) |
95 | /// <param name="priority">How high priority is this? 1 = Max, 6 = Verbose</param> | 95 | { |
96 | /// <param name="message">The message to log</param> | 96 | for (int y = -1; y < 2; y++) |
97 | private void logToDB(string target, string method, string args, int priority, string message) | 97 | { |
98 | { | 98 | if ( |
99 | foreach (ILogDataPlugin plugin in _logplugins) | 99 | m_gridDBService.GetRegion( |
100 | { | 100 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), |
101 | try | 101 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) |
102 | { | 102 | { |
103 | plugin.saveLog("Gridserver", target, method, args, priority, message); | 103 | neighbour = |
104 | } | 104 | m_gridDBService.GetRegion( |
105 | catch (Exception) | 105 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), |
106 | { | 106 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)); |
107 | m_log.Warn("[storage]: Unable to write log via " + plugin.Name); | 107 | |
108 | } | 108 | response += "<neighbour>"; |
109 | } | 109 | response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>"; |
110 | } | 110 | response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>"; |
111 | 111 | response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>"; | |
112 | /// <summary> | 112 | response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>"; |
113 | /// Returns a region by argument | 113 | response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>"; |
114 | /// </summary> | 114 | response += "</neighbour>"; |
115 | /// <param name="uuid">A UUID key of the region to return</param> | 115 | } |
116 | /// <returns>A SimProfileData for the region</returns> | 116 | } |
117 | public RegionProfileData GetRegion(UUID uuid) | 117 | } |
118 | { | 118 | return response; |
119 | foreach (IGridDataPlugin plugin in _plugins) | 119 | } |
120 | { | 120 | |
121 | try | 121 | /// <summary> |
122 | { | 122 | /// Checks that it's valid to replace the existing region data with new data |
123 | return plugin.GetProfileByUUID(uuid); | 123 | /// |
124 | } | 124 | /// Currently, this means ensure that the keys passed in by the new region |
125 | catch (Exception e) | 125 | /// match those in the original region. (XXX Is this correct? Shouldn't we simply check |
126 | { | 126 | /// against the keys in the current configuration?) |
127 | m_log.Warn("[storage]: GetRegion - " + e.Message); | 127 | /// </summary> |
128 | } | 128 | /// <param name="sim"></param> |
129 | } | 129 | /// <returns></returns> |
130 | return null; | 130 | protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) |
131 | } | 131 | { |
132 | 132 | if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) | |
133 | /// <summary> | 133 | { |
134 | /// Returns a region by argument | 134 | throw new LoginException( |
135 | /// </summary> | 135 | String.Format( |
136 | /// <param name="uuid">A regionHandle of the region to return</param> | 136 | "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" |
137 | /// <returns>A SimProfileData for the region</returns> | 137 | + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", |
138 | public RegionProfileData GetRegion(ulong handle) | 138 | sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, |
139 | { | 139 | sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), |
140 | foreach (IGridDataPlugin plugin in _plugins) | 140 | "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); |
141 | { | 141 | } |
142 | try | 142 | } |
143 | { | 143 | |
144 | return plugin.GetProfileByHandle(handle); | 144 | /// <summary> |
145 | } | 145 | /// Checks that the new region data is valid. |
146 | catch (Exception ex) | 146 | /// |
147 | { | 147 | /// Currently, this means checking that the keys passed in by the new region |
148 | m_log.Debug("[storage]: " + ex.Message); | 148 | /// match those in the grid server's configuration. |
149 | m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + plugin.Name); | 149 | /// </summary> |
150 | } | 150 | /// |
151 | } | 151 | /// <param name="sim"></param> |
152 | return null; | 152 | /// <exception cref="LoginException">Thrown if region login failed</exception> |
153 | } | 153 | protected virtual void ValidateNewRegionKeys(RegionProfileData sim) |
154 | 154 | { | |
155 | /// <summary> | 155 | if (!(sim.regionRecvKey == m_config.SimSendKey && sim.regionSendKey == m_config.SimRecvKey)) |
156 | /// Returns a region by argument | 156 | { |
157 | /// </summary> | 157 | throw new LoginException( |
158 | /// <param name="regionName">A partial regionName of the region to return</param> | 158 | String.Format( |
159 | /// <returns>A SimProfileData for the region</returns> | 159 | "Authentication failed when trying to login new region {0} at location {1} {2}" |
160 | public RegionProfileData GetRegion(string regionName) | 160 | + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", |
161 | { | 161 | sim.regionName, sim.regionLocX, sim.regionLocY, |
162 | foreach (IGridDataPlugin plugin in _plugins) | 162 | sim.regionSendKey, m_config.SimRecvKey, sim.regionRecvKey, m_config.SimSendKey), |
163 | { | 163 | "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); |
164 | try | 164 | } |
165 | { | 165 | } |
166 | return plugin.GetProfileByString(regionName); | 166 | |
167 | } | 167 | /// <summary> |
168 | catch | 168 | /// Check that a region's http uri is externally contactable. |
169 | { | 169 | /// </summary> |
170 | m_log.Warn("[storage]: Unable to find region " + regionName + " via " + plugin.Name); | 170 | /// <param name="sim"></param> |
171 | } | 171 | /// <exception cref="LoginException">Thrown if the region is not contactable</exception> |
172 | } | 172 | protected virtual void ValidateRegionContactable(RegionProfileData sim) |
173 | return null; | 173 | { |
174 | } | 174 | string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); |
175 | 175 | string regionStatusResponse; | |
176 | public List<RegionProfileData> GetRegions(uint xmin, uint ymin, uint xmax, uint ymax) | 176 | |
177 | { | 177 | RestClient rc = new RestClient(regionStatusUrl); |
178 | List<RegionProfileData> regions = new List<RegionProfileData>(); | 178 | rc.RequestMethod = "GET"; |
179 | 179 | ||
180 | foreach (IGridDataPlugin plugin in _plugins) | 180 | m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); |
181 | { | 181 | |
182 | try | 182 | try |
183 | { | 183 | { |
184 | regions.AddRange(plugin.GetProfilesInRange(xmin, ymin, xmax, ymax)); | 184 | Stream rs = rc.Request(); |
185 | } | 185 | StreamReader sr = new StreamReader(rs); |
186 | catch | 186 | regionStatusResponse = sr.ReadToEnd(); |
187 | { | 187 | sr.Close(); |
188 | m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); | 188 | } |
189 | } | 189 | catch (Exception e) |
190 | } | 190 | { |
191 | 191 | throw new LoginException( | |
192 | return regions; | 192 | String.Format("Region status request to {0} failed", regionStatusUrl), |
193 | } | 193 | String.Format( |
194 | 194 | "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", | |
195 | public List<RegionProfileData> GetRegions(string name, int maxNum) | 195 | regionStatusUrl), |
196 | { | 196 | e); |
197 | List<RegionProfileData> regions = new List<RegionProfileData>(); | 197 | } |
198 | foreach (IGridDataPlugin plugin in _plugins) | 198 | |
199 | { | 199 | if (!regionStatusResponse.Equals("OK")) |
200 | try | 200 | { |
201 | { | 201 | throw new LoginException( |
202 | int num = maxNum - regions.Count; | 202 | String.Format( |
203 | List <RegionProfileData> profiles = plugin.GetRegionsByName(name, (uint)num); | 203 | "Region {0} at {1} returned status response {2} rather than {3}", |
204 | if (profiles != null) regions.AddRange(profiles); | 204 | sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), |
205 | } | 205 | String.Format( |
206 | catch | 206 | "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", |
207 | { | 207 | regionStatusResponse, "OK")); |
208 | m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); | 208 | } |
209 | } | 209 | } |
210 | } | 210 | |
211 | 211 | /// <summary> | |
212 | return regions; | 212 | /// Construct an XMLRPC error response |
213 | } | 213 | /// </summary> |
214 | 214 | /// <param name="error"></param> | |
215 | /// <summary> | 215 | /// <returns></returns> |
216 | /// Returns a XML String containing a list of the neighbouring regions | 216 | public static XmlRpcResponse ErrorResponse(string error) |
217 | /// </summary> | 217 | { |
218 | /// <param name="reqhandle">The regionhandle for the center sim</param> | 218 | XmlRpcResponse errorResponse = new XmlRpcResponse(); |
219 | /// <returns>An XML string containing neighbour entities</returns> | 219 | Hashtable errorResponseData = new Hashtable(); |
220 | public string GetXMLNeighbours(ulong reqhandle) | 220 | errorResponse.Value = errorResponseData; |
221 | { | 221 | errorResponseData["error"] = error; |
222 | string response = String.Empty; | 222 | return errorResponse; |
223 | RegionProfileData central_region = GetRegion(reqhandle); | 223 | } |
224 | RegionProfileData neighbour; | 224 | |
225 | for (int x = -1; x < 2; x++) | 225 | /// <summary> |
226 | { | 226 | /// Performed when a region connects to the grid server initially. |
227 | for (int y = -1; y < 2; y++) | 227 | /// </summary> |
228 | { | 228 | /// <param name="request">The XML RPC Request</param> |
229 | if ( | 229 | /// <returns>Startup parameters</returns> |
230 | GetRegion( | 230 | public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) |
231 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), | 231 | { |
232 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) | 232 | RegionProfileData sim; |
233 | { | 233 | RegionProfileData existingSim; |
234 | neighbour = | 234 | |
235 | GetRegion( | 235 | Hashtable requestData = (Hashtable)request.Params[0]; |
236 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), | 236 | UUID uuid; |
237 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)); | 237 | |
238 | 238 | if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) | |
239 | response += "<neighbour>"; | 239 | { |
240 | response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>"; | 240 | m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); |
241 | response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>"; | 241 | return ErrorResponse("No UUID passed to grid server - unable to connect you"); |
242 | response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>"; | 242 | } |
243 | response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>"; | 243 | |
244 | response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>"; | 244 | try |
245 | response += "</neighbour>"; | 245 | { |
246 | } | 246 | sim = RegionFromRequest(requestData); |
247 | } | 247 | } |
248 | } | 248 | catch (FormatException e) |
249 | return response; | 249 | { |
250 | } | 250 | m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); |
251 | 251 | return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); | |
252 | /// <summary> | 252 | } |
253 | /// Checks that it's valid to replace the existing region data with new data | 253 | |
254 | /// | 254 | m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); |
255 | /// Currently, this means ensure that the keys passed in by the new region | 255 | |
256 | /// match those in the original region. (XXX Is this correct? Shouldn't we simply check | 256 | if (!m_config.AllowRegionRegistration) |
257 | /// against the keys in the current configuration?) | 257 | { |
258 | /// </summary> | 258 | m_log.DebugFormat( |
259 | /// <param name="sim"></param> | 259 | "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", |
260 | /// <returns></returns> | 260 | sim.regionName); |
261 | protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) | 261 | |
262 | { | 262 | return ErrorResponse("This grid is currently not accepting region registrations."); |
263 | if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) | 263 | } |
264 | { | 264 | |
265 | throw new LoginException( | 265 | int majorInterfaceVersion = 0; |
266 | String.Format( | 266 | if (requestData.ContainsKey("major_interface_version")) |
267 | "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" | 267 | int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); |
268 | + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", | 268 | |
269 | sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, | 269 | if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) |
270 | sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), | 270 | { |
271 | "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); | 271 | return ErrorResponse( |
272 | } | 272 | String.Format( |
273 | } | 273 | "Your region service implements OGS1 interface version {0}" |
274 | 274 | + " but this grid requires that the region implement OGS1 interface version {1} to connect." | |
275 | /// <summary> | 275 | + " Try changing to OpenSimulator {2}", |
276 | /// Checks that the new region data is valid. | 276 | majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); |
277 | /// | 277 | } |
278 | /// Currently, this means checking that the keys passed in by the new region | 278 | |
279 | /// match those in the grid server's configuration. | 279 | existingSim = m_gridDBService.GetRegion(sim.regionHandle); |
280 | /// </summary> | 280 | |
281 | /// | 281 | if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) |
282 | /// <param name="sim"></param> | 282 | { |
283 | /// <exception cref="LoginException">Thrown if region login failed</exception> | 283 | try |
284 | protected virtual void ValidateNewRegionKeys(RegionProfileData sim) | 284 | { |
285 | { | 285 | if (existingSim == null) |
286 | if (!(sim.regionRecvKey == Config.SimSendKey && sim.regionSendKey == Config.SimRecvKey)) | 286 | { |
287 | { | 287 | ValidateNewRegionKeys(sim); |
288 | throw new LoginException( | 288 | } |
289 | String.Format( | 289 | else |
290 | "Authentication failed when trying to login new region {0} at location {1} {2}" | 290 | { |
291 | + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", | 291 | ValidateOverwriteKeys(sim, existingSim); |
292 | sim.regionName, sim.regionLocX, sim.regionLocY, | 292 | } |
293 | sim.regionSendKey, Config.SimRecvKey, sim.regionRecvKey, Config.SimSendKey), | 293 | |
294 | "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); | 294 | ValidateRegionContactable(sim); |
295 | } | 295 | } |
296 | } | 296 | catch (LoginException e) |
297 | 297 | { | |
298 | /// <summary> | 298 | string logMsg = e.Message; |
299 | /// Check that a region's http uri is externally contactable. | 299 | if (e.InnerException != null) |
300 | /// </summary> | 300 | logMsg += ", " + e.InnerException.Message; |
301 | /// <param name="sim"></param> | 301 | |
302 | /// <exception cref="LoginException">Thrown if the region is not contactable</exception> | 302 | m_log.WarnFormat("[LOGIN END]: {0}", logMsg); |
303 | protected virtual void ValidateRegionContactable(RegionProfileData sim) | 303 | |
304 | { | 304 | return e.XmlRpcErrorResponse; |
305 | string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); | 305 | } |
306 | string regionStatusResponse; | 306 | |
307 | 307 | m_gridDBService.LoginRegion(sim, existingSim); | |
308 | RestClient rc = new RestClient(regionStatusUrl); | 308 | |
309 | rc.RequestMethod = "GET"; | 309 | XmlRpcResponse response = CreateLoginResponse(sim); |
310 | 310 | ||
311 | m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); | 311 | return response; |
312 | 312 | } | |
313 | try | 313 | else |
314 | { | 314 | { |
315 | Stream rs = rc.Request(); | 315 | m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); |
316 | StreamReader sr = new StreamReader(rs); | 316 | return ErrorResponse("Another region already exists at that location. Please try another."); |
317 | regionStatusResponse = sr.ReadToEnd(); | 317 | } |
318 | sr.Close(); | 318 | } |
319 | } | 319 | |
320 | catch (Exception e) | 320 | /// <summary> |
321 | { | 321 | /// Construct a successful response to a simulator's login attempt. |
322 | throw new LoginException( | 322 | /// </summary> |
323 | String.Format("Region status request to {0} failed", regionStatusUrl), | 323 | /// <param name="sim"></param> |
324 | String.Format( | 324 | /// <returns></returns> |
325 | "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", | 325 | private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) |
326 | regionStatusUrl), | 326 | { |
327 | e); | 327 | XmlRpcResponse response = new XmlRpcResponse(); |
328 | } | 328 | Hashtable responseData = new Hashtable(); |
329 | 329 | response.Value = responseData; | |
330 | if (!regionStatusResponse.Equals("OK")) | 330 | |
331 | { | 331 | ArrayList SimNeighboursData = GetSimNeighboursData(sim); |
332 | throw new LoginException( | 332 | |
333 | String.Format( | 333 | responseData["UUID"] = sim.UUID.ToString(); |
334 | "Region {0} at {1} returned status response {2} rather than {3}", | 334 | responseData["region_locx"] = sim.regionLocX.ToString(); |
335 | sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), | 335 | responseData["region_locy"] = sim.regionLocY.ToString(); |
336 | String.Format( | 336 | responseData["regionname"] = sim.regionName; |
337 | "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", | 337 | responseData["estate_id"] = "1"; |
338 | regionStatusResponse, "OK")); | 338 | responseData["neighbours"] = SimNeighboursData; |
339 | } | 339 | |
340 | } | 340 | responseData["sim_ip"] = sim.serverIP; |
341 | 341 | responseData["sim_port"] = sim.serverPort.ToString(); | |
342 | /// <summary> | 342 | responseData["asset_url"] = sim.regionAssetURI; |
343 | /// Construct an XMLRPC error response | 343 | responseData["asset_sendkey"] = sim.regionAssetSendKey; |
344 | /// </summary> | 344 | responseData["asset_recvkey"] = sim.regionAssetRecvKey; |
345 | /// <param name="error"></param> | 345 | responseData["user_url"] = sim.regionUserURI; |
346 | /// <returns></returns> | 346 | responseData["user_sendkey"] = sim.regionUserSendKey; |
347 | public static XmlRpcResponse ErrorResponse(string error) | 347 | responseData["user_recvkey"] = sim.regionUserRecvKey; |
348 | { | 348 | responseData["authkey"] = sim.regionSecret; |
349 | XmlRpcResponse errorResponse = new XmlRpcResponse(); | 349 | |
350 | Hashtable errorResponseData = new Hashtable(); | 350 | // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) |
351 | errorResponse.Value = errorResponseData; | 351 | responseData["data_uri"] = sim.regionDataURI; |
352 | errorResponseData["error"] = error; | 352 | |
353 | return errorResponse; | 353 | responseData["allow_forceful_banlines"] = m_config.AllowForcefulBanlines; |
354 | } | 354 | |
355 | 355 | // Instead of sending a multitude of message servers to the registering sim | |
356 | /// <summary> | 356 | // we should probably be sending a single one and parhaps it's backup |
357 | /// Performed when a region connects to the grid server initially. | 357 | // that has responsibility over routing it's messages. |
358 | /// </summary> | 358 | |
359 | /// <param name="request">The XML RPC Request</param> | 359 | // The Sim won't be contacting us again about any of the message server stuff during it's time up. |
360 | /// <returns>Startup parameters</returns> | 360 | |
361 | public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) | 361 | responseData["messageserver_count"] = 0; |
362 | { | 362 | |
363 | RegionProfileData sim; | 363 | IGridMessagingModule messagingModule; |
364 | RegionProfileData existingSim; | 364 | if (m_gridCore.TryGet<IGridMessagingModule>(out messagingModule)) |
365 | 365 | { | |
366 | Hashtable requestData = (Hashtable)request.Params[0]; | 366 | List<MessageServerInfo> messageServers = messagingModule.MessageServers; |
367 | UUID uuid; | 367 | responseData["messageserver_count"] = messageServers.Count; |
368 | 368 | ||
369 | if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) | 369 | for (int i = 0; i < messageServers.Count; i++) |
370 | { | 370 | { |
371 | m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); | 371 | responseData["messageserver_uri" + i] = messageServers[i].URI; |
372 | return ErrorResponse("No UUID passed to grid server - unable to connect you"); | 372 | responseData["messageserver_sendkey" + i] = messageServers[i].sendkey; |
373 | } | 373 | responseData["messageserver_recvkey" + i] = messageServers[i].recvkey; |
374 | 374 | } | |
375 | try | 375 | } |
376 | { | 376 | return response; |
377 | sim = RegionFromRequest(requestData); | 377 | } |
378 | } | 378 | |
379 | catch (FormatException e) | 379 | private ArrayList GetSimNeighboursData(RegionProfileData sim) |
380 | { | 380 | { |
381 | m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); | 381 | ArrayList SimNeighboursData = new ArrayList(); |
382 | return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); | 382 | |
383 | } | 383 | RegionProfileData neighbour; |
384 | 384 | Hashtable NeighbourBlock; | |
385 | m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); | 385 | |
386 | 386 | //First use the fast method. (not implemented in SQLLite) | |
387 | if (!Config.AllowRegionRegistration) | 387 | List<RegionProfileData> neighbours = m_gridDBService.GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); |
388 | { | 388 | |
389 | m_log.DebugFormat( | 389 | if (neighbours.Count > 0) |
390 | "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", | 390 | { |
391 | sim.regionName); | 391 | foreach (RegionProfileData aSim in neighbours) |
392 | 392 | { | |
393 | return ErrorResponse("This grid is currently not accepting region registrations."); | 393 | NeighbourBlock = new Hashtable(); |
394 | } | 394 | NeighbourBlock["sim_ip"] = aSim.serverIP; |
395 | 395 | NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); | |
396 | int majorInterfaceVersion = 0; | 396 | NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); |
397 | if (requestData.ContainsKey("major_interface_version")) | 397 | NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); |
398 | int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); | 398 | NeighbourBlock["UUID"] = aSim.ToString(); |
399 | 399 | NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); | |
400 | if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) | 400 | |
401 | { | 401 | if (aSim.UUID != sim.UUID) |
402 | return ErrorResponse( | 402 | { |
403 | String.Format( | 403 | SimNeighboursData.Add(NeighbourBlock); |
404 | "Your region service implements OGS1 interface version {0}" | 404 | } |
405 | + " but this grid requires that the region implement OGS1 interface version {1} to connect." | 405 | } |
406 | + " Try changing to OpenSimulator {2}", | 406 | } |
407 | majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); | 407 | else |
408 | } | 408 | { |
409 | 409 | for (int x = -1; x < 2; x++) | |
410 | existingSim = GetRegion(sim.regionHandle); | 410 | { |
411 | 411 | for (int y = -1; y < 2; y++) | |
412 | if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) | 412 | { |
413 | { | 413 | if ( |
414 | try | 414 | m_gridDBService.GetRegion( |
415 | { | 415 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), |
416 | if (existingSim == null) | 416 | (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) |
417 | { | 417 | { |
418 | ValidateNewRegionKeys(sim); | 418 | neighbour = |
419 | } | 419 | m_gridDBService.GetRegion( |
420 | else | 420 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), |
421 | { | 421 | (uint)(sim.regionLocY + y) * Constants.RegionSize)); |
422 | ValidateOverwriteKeys(sim, existingSim); | 422 | |
423 | } | 423 | NeighbourBlock = new Hashtable(); |
424 | 424 | NeighbourBlock["sim_ip"] = neighbour.serverIP; | |
425 | ValidateRegionContactable(sim); | 425 | NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); |
426 | } | 426 | NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); |
427 | catch (LoginException e) | 427 | NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); |
428 | { | 428 | NeighbourBlock["UUID"] = neighbour.UUID.ToString(); |
429 | string logMsg = e.Message; | 429 | NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); |
430 | if (e.InnerException != null) | 430 | |
431 | logMsg += ", " + e.InnerException.Message; | 431 | if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); |
432 | 432 | } | |
433 | m_log.WarnFormat("[LOGIN END]: {0}", logMsg); | 433 | } |
434 | 434 | } | |
435 | return e.XmlRpcErrorResponse; | 435 | } |
436 | } | 436 | return SimNeighboursData; |
437 | 437 | } | |
438 | foreach (IGridDataPlugin plugin in _plugins) | 438 | |
439 | { | 439 | /// <summary> |
440 | try | 440 | /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region |
441 | { | 441 | /// </summary> |
442 | DataResponse insertResponse; | 442 | /// <param name="requestData"></param> |
443 | 443 | /// <returns></returns> | |
444 | if (existingSim == null) | 444 | private RegionProfileData RegionFromRequest(Hashtable requestData) |
445 | { | 445 | { |
446 | insertResponse = plugin.AddProfile(sim); | 446 | RegionProfileData sim; |
447 | } | 447 | sim = new RegionProfileData(); |
448 | else | 448 | |
449 | { | 449 | sim.UUID = new UUID((string)requestData["UUID"]); |
450 | insertResponse = plugin.UpdateProfile(sim); | 450 | sim.originUUID = new UUID((string)requestData["originUUID"]); |
451 | } | 451 | |
452 | 452 | sim.regionRecvKey = String.Empty; | |
453 | switch (insertResponse) | 453 | sim.regionSendKey = String.Empty; |
454 | { | 454 | |
455 | case DataResponse.RESPONSE_OK: | 455 | if (requestData.ContainsKey("region_secret")) |
456 | m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); | 456 | { |
457 | break; | 457 | string regionsecret = (string)requestData["region_secret"]; |
458 | case DataResponse.RESPONSE_ERROR: | 458 | if (regionsecret.Length > 0) |
459 | m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); | 459 | sim.regionSecret = regionsecret; |
460 | break; | 460 | else |
461 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | 461 | sim.regionSecret = m_config.SimRecvKey; |
462 | m_log.Warn("[LOGIN END]: " + | 462 | |
463 | "Sim login failed (Invalid Credentials): " + sim.regionName); | 463 | } |
464 | break; | 464 | else |
465 | case DataResponse.RESPONSE_AUTHREQUIRED: | 465 | { |
466 | m_log.Warn("[LOGIN END]: " + | 466 | sim.regionSecret = m_config.SimRecvKey; |
467 | "Sim login failed (Authentication Required): " + | 467 | } |
468 | sim.regionName); | 468 | |
469 | break; | 469 | sim.regionDataURI = String.Empty; |
470 | } | 470 | sim.regionAssetURI = m_config.DefaultAssetServer; |
471 | } | 471 | sim.regionAssetRecvKey = m_config.AssetRecvKey; |
472 | catch (Exception e) | 472 | sim.regionAssetSendKey = m_config.AssetSendKey; |
473 | { | 473 | sim.regionUserURI = m_config.DefaultUserServer; |
474 | m_log.Warn("[LOGIN END]: " + | 474 | sim.regionUserSendKey = m_config.UserSendKey; |
475 | "Unable to login region " + sim.ToString() + " via " + plugin.Name); | 475 | sim.regionUserRecvKey = m_config.UserRecvKey; |
476 | m_log.Warn("[LOGIN END]: " + e.ToString()); | 476 | |
477 | } | 477 | sim.serverIP = (string)requestData["sim_ip"]; |
478 | } | 478 | sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); |
479 | 479 | sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); | |
480 | XmlRpcResponse response = CreateLoginResponse(sim); | 480 | sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); |
481 | 481 | sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); | |
482 | return response; | 482 | sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); |
483 | } | 483 | sim.regionLocZ = 0; |
484 | else | 484 | |
485 | { | 485 | UUID textureID; |
486 | m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); | 486 | if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) |
487 | return ErrorResponse("Another region already exists at that location. Please try another."); | 487 | { |
488 | } | 488 | sim.regionMapTextureID = textureID; |
489 | } | 489 | } |
490 | 490 | ||
491 | /// <summary> | 491 | // part of an initial brutish effort to provide accurate information (as per the xml region spec) |
492 | /// Construct a successful response to a simulator's login attempt. | 492 | // wrt the ownership of a given region |
493 | /// </summary> | 493 | // the (very bad) assumption is that this value is being read and handled inconsistently or |
494 | /// <param name="sim"></param> | 494 | // not at all. Current strategy is to put the code in place to support the validity of this information |
495 | /// <returns></returns> | 495 | // and to roll forward debugging any issues from that point |
496 | private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) | 496 | // |
497 | { | 497 | // this particular section of the mod attempts to receive a value from the region's xml file by way of |
498 | XmlRpcResponse response = new XmlRpcResponse(); | 498 | // OSG1GridServices for the region's owner |
499 | Hashtable responseData = new Hashtable(); | 499 | sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; |
500 | response.Value = responseData; | 500 | |
501 | 501 | try | |
502 | ArrayList SimNeighboursData = GetSimNeighboursData(sim); | 502 | { |
503 | 503 | sim.regionRecvKey = (string)requestData["recvkey"]; | |
504 | responseData["UUID"] = sim.UUID.ToString(); | 504 | sim.regionSendKey = (string)requestData["authkey"]; |
505 | responseData["region_locx"] = sim.regionLocX.ToString(); | 505 | } |
506 | responseData["region_locy"] = sim.regionLocY.ToString(); | 506 | catch (KeyNotFoundException) { } |
507 | responseData["regionname"] = sim.regionName; | 507 | |
508 | responseData["estate_id"] = "1"; | 508 | sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); |
509 | responseData["neighbours"] = SimNeighboursData; | 509 | sim.serverURI = (string)requestData["server_uri"]; |
510 | 510 | ||
511 | responseData["sim_ip"] = sim.serverIP; | 511 | sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; |
512 | responseData["sim_port"] = sim.serverPort.ToString(); | 512 | |
513 | responseData["asset_url"] = sim.regionAssetURI; | 513 | sim.regionName = (string)requestData["sim_name"]; |
514 | responseData["asset_sendkey"] = sim.regionAssetSendKey; | 514 | return sim; |
515 | responseData["asset_recvkey"] = sim.regionAssetRecvKey; | 515 | } |
516 | responseData["user_url"] = sim.regionUserURI; | 516 | |
517 | responseData["user_sendkey"] = sim.regionUserSendKey; | 517 | /// <summary> |
518 | responseData["user_recvkey"] = sim.regionUserRecvKey; | 518 | /// Returns an XML RPC response to a simulator profile request |
519 | responseData["authkey"] = sim.regionSecret; | 519 | /// Performed after moving a region. |
520 | 520 | /// </summary> | |
521 | // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) | 521 | /// <param name="request"></param> |
522 | responseData["data_uri"] = sim.regionDataURI; | 522 | /// <returns></returns> |
523 | 523 | /// <param name="request">The XMLRPC Request</param> | |
524 | responseData["allow_forceful_banlines"] = Config.AllowForcefulBanlines; | 524 | /// <returns>Processing parameters</returns> |
525 | 525 | public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request) | |
526 | // Instead of sending a multitude of message servers to the registering sim | 526 | { |
527 | // we should probably be sending a single one and parhaps it's backup | 527 | XmlRpcResponse response = new XmlRpcResponse(); |
528 | // that has responsibility over routing it's messages. | 528 | Hashtable responseData = new Hashtable(); |
529 | 529 | response.Value = responseData; | |
530 | // The Sim won't be contacting us again about any of the message server stuff during it's time up. | 530 | |
531 | 531 | //RegionProfileData TheSim = null; | |
532 | responseData["messageserver_count"] = _MessageServers.Count; | 532 | string uuid; |
533 | 533 | Hashtable requestData = (Hashtable)request.Params[0]; | |
534 | for (int i = 0; i < _MessageServers.Count; i++) | 534 | |
535 | { | 535 | if (requestData.ContainsKey("UUID")) |
536 | responseData["messageserver_uri" + i] = _MessageServers[i].URI; | 536 | { |
537 | responseData["messageserver_sendkey" + i] = _MessageServers[i].sendkey; | 537 | //TheSim = GetRegion(new UUID((string) requestData["UUID"])); |
538 | responseData["messageserver_recvkey" + i] = _MessageServers[i].recvkey; | 538 | uuid = requestData["UUID"].ToString(); |
539 | } | 539 | m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); |
540 | return response; | 540 | // logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); |
541 | } | 541 | } |
542 | 542 | else | |
543 | private ArrayList GetSimNeighboursData(RegionProfileData sim) | 543 | { |
544 | { | 544 | responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; |
545 | ArrayList SimNeighboursData = new ArrayList(); | 545 | return response; |
546 | 546 | } | |
547 | RegionProfileData neighbour; | 547 | |
548 | Hashtable NeighbourBlock; | 548 | DataResponse insertResponse = m_gridDBService.DeleteRegion(uuid); |
549 | 549 | ||
550 | //First use the fast method. (not implemented in SQLLite) | 550 | string insertResp = ""; |
551 | List<RegionProfileData> neighbours = GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); | 551 | switch (insertResponse) |
552 | 552 | { | |
553 | if (neighbours.Count > 0) | 553 | case DataResponse.RESPONSE_OK: |
554 | { | 554 | //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); |
555 | foreach (RegionProfileData aSim in neighbours) | 555 | insertResp = "Deleting region successful: " + uuid; |
556 | { | 556 | break; |
557 | NeighbourBlock = new Hashtable(); | 557 | case DataResponse.RESPONSE_ERROR: |
558 | NeighbourBlock["sim_ip"] = aSim.serverIP; | 558 | //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); |
559 | NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); | 559 | insertResp = "Deleting region failed (Error): " + uuid; |
560 | NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); | 560 | break; |
561 | NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); | 561 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: |
562 | NeighbourBlock["UUID"] = aSim.ToString(); | 562 | //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); |
563 | NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); | 563 | insertResp = "Deleting region (Invalid Credentials): " + uuid; |
564 | 564 | break; | |
565 | if (aSim.UUID != sim.UUID) | 565 | case DataResponse.RESPONSE_AUTHREQUIRED: |
566 | { | 566 | //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); |
567 | SimNeighboursData.Add(NeighbourBlock); | 567 | insertResp = "Deleting region (Authentication Required): " + uuid; |
568 | } | 568 | break; |
569 | } | 569 | } |
570 | } | 570 | |
571 | else | 571 | responseData["status"] = insertResp; |
572 | { | 572 | |
573 | for (int x = -1; x < 2; x++) | 573 | return response; |
574 | { | 574 | } |
575 | for (int y = -1; y < 2; y++) | 575 | |
576 | { | 576 | /// <summary> |
577 | if ( | 577 | /// Returns an XML RPC response to a simulator profile request |
578 | GetRegion( | 578 | /// </summary> |
579 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), | 579 | /// <param name="request"></param> |
580 | (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) | 580 | /// <returns></returns> |
581 | { | 581 | public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) |
582 | neighbour = | 582 | { |
583 | GetRegion( | 583 | Hashtable requestData = (Hashtable)request.Params[0]; |
584 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), | 584 | Hashtable responseData = new Hashtable(); |
585 | (uint)(sim.regionLocY + y) * Constants.RegionSize)); | 585 | RegionProfileData simData = null; |
586 | 586 | if (requestData.ContainsKey("region_UUID")) | |
587 | NeighbourBlock = new Hashtable(); | 587 | { |
588 | NeighbourBlock["sim_ip"] = neighbour.serverIP; | 588 | UUID regionID = new UUID((string)requestData["region_UUID"]); |
589 | NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); | 589 | simData = m_gridDBService.GetRegion(regionID); |
590 | NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); | 590 | if (simData == null) |
591 | NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); | 591 | { |
592 | NeighbourBlock["UUID"] = neighbour.UUID.ToString(); | 592 | m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", |
593 | NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); | 593 | regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); |
594 | 594 | } | |
595 | if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); | 595 | } |
596 | } | 596 | else if (requestData.ContainsKey("region_handle")) |
597 | } | 597 | { |
598 | } | 598 | //CFK: The if/else below this makes this message redundant. |
599 | } | 599 | //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); |
600 | return SimNeighboursData; | 600 | ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); |
601 | } | 601 | simData = m_gridDBService.GetRegion(regionHandle); |
602 | 602 | if (simData == null) | |
603 | /// <summary> | 603 | { |
604 | /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region | 604 | m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", |
605 | /// </summary> | 605 | regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); |
606 | /// <param name="requestData"></param> | 606 | } |
607 | /// <returns></returns> | 607 | } |
608 | private RegionProfileData RegionFromRequest(Hashtable requestData) | 608 | else if (requestData.ContainsKey("region_name_search")) |
609 | { | 609 | { |
610 | RegionProfileData sim; | 610 | string regionName = (string)requestData["region_name_search"]; |
611 | sim = new RegionProfileData(); | 611 | simData = m_gridDBService.GetRegion(regionName); |
612 | 612 | if (simData == null) | |
613 | sim.UUID = new UUID((string)requestData["UUID"]); | 613 | { |
614 | sim.originUUID = new UUID((string)requestData["originUUID"]); | 614 | m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", |
615 | 615 | regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | |
616 | sim.regionRecvKey = String.Empty; | 616 | } |
617 | sim.regionSendKey = String.Empty; | 617 | } |
618 | 618 | else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); | |
619 | if (requestData.ContainsKey("region_secret")) | 619 | |
620 | { | 620 | if (simData == null) |
621 | string regionsecret = (string)requestData["region_secret"]; | 621 | { |
622 | if (regionsecret.Length > 0) | 622 | //Sim does not exist |
623 | sim.regionSecret = regionsecret; | 623 | responseData["error"] = "Sim does not exist"; |
624 | else | 624 | } |
625 | sim.regionSecret = Config.SimRecvKey; | 625 | else |
626 | 626 | { | |
627 | } | 627 | m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + |
628 | else | 628 | (string)requestData["region_handle"]); |
629 | { | 629 | responseData["sim_ip"] = simData.serverIP; |
630 | sim.regionSecret = Config.SimRecvKey; | 630 | responseData["sim_port"] = simData.serverPort.ToString(); |
631 | } | 631 | responseData["server_uri"] = simData.serverURI; |
632 | 632 | responseData["http_port"] = simData.httpPort.ToString(); | |
633 | sim.regionDataURI = String.Empty; | 633 | responseData["remoting_port"] = simData.remotingPort.ToString(); |
634 | sim.regionAssetURI = Config.DefaultAssetServer; | 634 | responseData["region_locx"] = simData.regionLocX.ToString(); |
635 | sim.regionAssetRecvKey = Config.AssetRecvKey; | 635 | responseData["region_locy"] = simData.regionLocY.ToString(); |
636 | sim.regionAssetSendKey = Config.AssetSendKey; | 636 | responseData["region_UUID"] = simData.UUID.Guid.ToString(); |
637 | sim.regionUserURI = Config.DefaultUserServer; | 637 | responseData["region_name"] = simData.regionName; |
638 | sim.regionUserSendKey = Config.UserSendKey; | 638 | responseData["regionHandle"] = simData.regionHandle.ToString(); |
639 | sim.regionUserRecvKey = Config.UserRecvKey; | 639 | } |
640 | 640 | ||
641 | sim.serverIP = (string)requestData["sim_ip"]; | 641 | XmlRpcResponse response = new XmlRpcResponse(); |
642 | sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); | 642 | response.Value = responseData; |
643 | sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); | 643 | return response; |
644 | sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); | 644 | } |
645 | sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); | 645 | |
646 | sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); | 646 | public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) |
647 | sim.regionLocZ = 0; | 647 | { |
648 | 648 | int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; | |
649 | UUID textureID; | 649 | |
650 | if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) | 650 | Hashtable requestData = (Hashtable)request.Params[0]; |
651 | { | 651 | if (requestData.ContainsKey("xmin")) |
652 | sim.regionMapTextureID = textureID; | 652 | { |
653 | } | 653 | xmin = (Int32)requestData["xmin"]; |
654 | 654 | } | |
655 | // part of an initial brutish effort to provide accurate information (as per the xml region spec) | 655 | if (requestData.ContainsKey("ymin")) |
656 | // wrt the ownership of a given region | 656 | { |
657 | // the (very bad) assumption is that this value is being read and handled inconsistently or | 657 | ymin = (Int32)requestData["ymin"]; |
658 | // not at all. Current strategy is to put the code in place to support the validity of this information | 658 | } |
659 | // and to roll forward debugging any issues from that point | 659 | if (requestData.ContainsKey("xmax")) |
660 | // | 660 | { |
661 | // this particular section of the mod attempts to receive a value from the region's xml file by way of | 661 | xmax = (Int32)requestData["xmax"]; |
662 | // OSG1GridServices for the region's owner | 662 | } |
663 | sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; | 663 | if (requestData.ContainsKey("ymax")) |
664 | 664 | { | |
665 | try | 665 | ymax = (Int32)requestData["ymax"]; |
666 | { | 666 | } |
667 | sim.regionRecvKey = (string)requestData["recvkey"]; | 667 | //CFK: The second log is more meaningful and either standard or fast generally occurs. |
668 | sim.regionSendKey = (string)requestData["authkey"]; | 668 | //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); |
669 | } | 669 | |
670 | catch (KeyNotFoundException) { } | 670 | XmlRpcResponse response = new XmlRpcResponse(); |
671 | 671 | Hashtable responseData = new Hashtable(); | |
672 | sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); | 672 | response.Value = responseData; |
673 | sim.serverURI = (string)requestData["server_uri"]; | 673 | IList simProfileList = new ArrayList(); |
674 | 674 | ||
675 | sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; | 675 | bool fastMode = (m_config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || m_config.DatabaseProvider == "OpenSim.Data.MSSQL.dll"); |
676 | 676 | ||
677 | sim.regionName = (string)requestData["sim_name"]; | 677 | if (fastMode) |
678 | return sim; | 678 | { |
679 | } | 679 | List<RegionProfileData> neighbours = m_gridDBService.GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax); |
680 | 680 | ||
681 | /// <summary> | 681 | foreach (RegionProfileData aSim in neighbours) |
682 | /// Returns an XML RPC response to a simulator profile request | 682 | { |
683 | /// Performed after moving a region. | 683 | Hashtable simProfileBlock = new Hashtable(); |
684 | /// </summary> | 684 | simProfileBlock["x"] = aSim.regionLocX.ToString(); |
685 | /// <param name="request"></param> | 685 | simProfileBlock["y"] = aSim.regionLocY.ToString(); |
686 | /// <returns></returns> | 686 | //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY); |
687 | /// <param name="request">The XMLRPC Request</param> | 687 | simProfileBlock["name"] = aSim.regionName; |
688 | /// <returns>Processing parameters</returns> | 688 | simProfileBlock["access"] = 21; |
689 | public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request) | 689 | simProfileBlock["region-flags"] = 512; |
690 | { | 690 | simProfileBlock["water-height"] = 0; |
691 | XmlRpcResponse response = new XmlRpcResponse(); | 691 | simProfileBlock["agents"] = 1; |
692 | Hashtable responseData = new Hashtable(); | 692 | simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString(); |
693 | response.Value = responseData; | 693 | |
694 | 694 | // For Sugilite compatibility | |
695 | //RegionProfileData TheSim = null; | 695 | simProfileBlock["regionhandle"] = aSim.regionHandle.ToString(); |
696 | string uuid; | 696 | simProfileBlock["sim_ip"] = aSim.serverIP; |
697 | Hashtable requestData = (Hashtable)request.Params[0]; | 697 | simProfileBlock["sim_port"] = aSim.serverPort.ToString(); |
698 | 698 | simProfileBlock["sim_uri"] = aSim.serverURI.ToString(); | |
699 | if (requestData.ContainsKey("UUID")) | 699 | simProfileBlock["uuid"] = aSim.UUID.ToString(); |
700 | { | 700 | simProfileBlock["remoting_port"] = aSim.remotingPort.ToString(); |
701 | //TheSim = GetRegion(new UUID((string) requestData["UUID"])); | 701 | simProfileBlock["http_port"] = aSim.httpPort.ToString(); |
702 | uuid = requestData["UUID"].ToString(); | 702 | |
703 | m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); | 703 | simProfileList.Add(simProfileBlock); |
704 | // logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); | 704 | } |
705 | } | 705 | m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + |
706 | else | 706 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); |
707 | { | 707 | } |
708 | responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; | 708 | else |
709 | return response; | 709 | { |
710 | } | 710 | RegionProfileData simProfile; |
711 | 711 | for (int x = xmin; x < xmax + 1; x++) | |
712 | foreach (IGridDataPlugin plugin in _plugins) | 712 | { |
713 | { | 713 | for (int y = ymin; y < ymax + 1; y++) |
714 | //OpenSim.Data.MySQL.MySQLGridData dbengine = new OpenSim.Data.MySQL.MySQLGridData(); | 714 | { |
715 | try | 715 | ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); |
716 | { | 716 | simProfile = m_gridDBService.GetRegion(regHandle); |
717 | //Nice are we not using multiple databases? | 717 | if (simProfile != null) |
718 | //MySQLGridData mysqldata = (MySQLGridData)(plugin); | 718 | { |
719 | 719 | Hashtable simProfileBlock = new Hashtable(); | |
720 | //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim); | 720 | simProfileBlock["x"] = x; |
721 | DataResponse insertResponse = plugin.DeleteProfile(uuid); | 721 | simProfileBlock["y"] = y; |
722 | 722 | simProfileBlock["name"] = simProfile.regionName; | |
723 | switch (insertResponse) | 723 | simProfileBlock["access"] = 0; |
724 | { | 724 | simProfileBlock["region-flags"] = 0; |
725 | case DataResponse.RESPONSE_OK: | 725 | simProfileBlock["water-height"] = 20; |
726 | //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); | 726 | simProfileBlock["agents"] = 1; |
727 | responseData["status"] = "Deleting region successful: " + uuid; | 727 | simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); |
728 | break; | 728 | |
729 | case DataResponse.RESPONSE_ERROR: | 729 | // For Sugilite compatibility |
730 | //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); | 730 | simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); |
731 | responseData["status"] = "Deleting region failed (Error): " + uuid; | 731 | simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); |
732 | break; | 732 | simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); |
733 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | 733 | simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); |
734 | //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); | 734 | simProfileBlock["uuid"] = simProfile.UUID.ToString(); |
735 | responseData["status"] = "Deleting region (Invalid Credentials): " + uuid; | 735 | simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString(); |
736 | break; | 736 | simProfileBlock["http_port"] = simProfile.httpPort; |
737 | case DataResponse.RESPONSE_AUTHREQUIRED: | 737 | |
738 | //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); | 738 | simProfileList.Add(simProfileBlock); |
739 | responseData["status"] = "Deleting region (Authentication Required): " + uuid; | 739 | } |
740 | break; | 740 | } |
741 | } | 741 | } |
742 | } | 742 | m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + |
743 | catch (Exception) | 743 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); |
744 | { | 744 | } |
745 | m_log.Error("storage Unable to delete region " + uuid + " via " + plugin.Name); | 745 | |
746 | //MainLog.Instance.Warn("storage", e.ToString()); | 746 | responseData["sim-profiles"] = simProfileList; |
747 | } | 747 | |
748 | } | 748 | return response; |
749 | 749 | } | |
750 | return response; | 750 | |
751 | } | 751 | /// <summary> |
752 | 752 | /// Returns up to <code>maxNumber</code> profiles of regions that have a name starting with <code>name</code> | |
753 | /// <summary> | 753 | /// </summary> |
754 | /// Returns an XML RPC response to a simulator profile request | 754 | /// <param name="request"></param> |
755 | /// </summary> | 755 | /// <returns></returns> |
756 | /// <param name="request"></param> | 756 | public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request) |
757 | /// <returns></returns> | 757 | { |
758 | public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) | 758 | Hashtable requestData = (Hashtable)request.Params[0]; |
759 | { | 759 | |
760 | Hashtable requestData = (Hashtable)request.Params[0]; | 760 | if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber")) |
761 | Hashtable responseData = new Hashtable(); | 761 | { |
762 | RegionProfileData simData = null; | 762 | m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber"); |
763 | if (requestData.ContainsKey("region_UUID")) | 763 | return new XmlRpcResponse(500, "Missing name or maxNumber in region search request"); |
764 | { | 764 | } |
765 | UUID regionID = new UUID((string)requestData["region_UUID"]); | 765 | |
766 | simData = GetRegion(regionID); | 766 | Hashtable responseData = new Hashtable(); |
767 | if (simData == null) | 767 | |
768 | { | 768 | string name = (string)requestData["name"]; |
769 | m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", | 769 | int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]); |
770 | regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | 770 | if (maxNumber == 0 || name.Length < 3) |
771 | } | 771 | { |
772 | } | 772 | // either we didn't want any, or we were too unspecific |
773 | else if (requestData.ContainsKey("region_handle")) | 773 | responseData["numFound"] = 0; |
774 | { | 774 | } |
775 | //CFK: The if/else below this makes this message redundant. | 775 | else |
776 | //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); | 776 | { |
777 | ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); | 777 | List<RegionProfileData> sims = m_gridDBService.GetRegions(name, maxNumber); |
778 | simData = GetRegion(regionHandle); | 778 | |
779 | if (simData == null) | 779 | responseData["numFound"] = sims.Count; |
780 | { | 780 | for (int i = 0; i < sims.Count; ++i) |
781 | m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", | 781 | { |
782 | regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | 782 | RegionProfileData sim = sims[i]; |
783 | } | 783 | string prefix = "region" + i + "."; |
784 | } | 784 | responseData[prefix + "region_name"] = sim.regionName; |
785 | else if (requestData.ContainsKey("region_name_search")) | 785 | responseData[prefix + "region_UUID"] = sim.UUID.ToString(); |
786 | { | 786 | responseData[prefix + "region_locx"] = sim.regionLocX.ToString(); |
787 | string regionName = (string)requestData["region_name_search"]; | 787 | responseData[prefix + "region_locy"] = sim.regionLocY.ToString(); |
788 | simData = GetRegion(regionName); | 788 | responseData[prefix + "sim_ip"] = sim.serverIP.ToString(); |
789 | if (simData == null) | 789 | responseData[prefix + "sim_port"] = sim.serverPort.ToString(); |
790 | { | 790 | responseData[prefix + "remoting_port"] = sim.remotingPort.ToString(); |
791 | m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", | 791 | responseData[prefix + "http_port"] = sim.httpPort.ToString(); |
792 | regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | 792 | responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString(); |
793 | } | 793 | } |
794 | } | 794 | } |
795 | else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); | 795 | |
796 | 796 | XmlRpcResponse response = new XmlRpcResponse(); | |
797 | if (simData == null) | 797 | response.Value = responseData; |
798 | { | 798 | return response; |
799 | //Sim does not exist | 799 | } |
800 | responseData["error"] = "Sim does not exist"; | 800 | |
801 | } | 801 | /// <summary> |
802 | else | 802 | /// Construct an XMLRPC registration disabled response |
803 | { | 803 | /// </summary> |
804 | m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + | 804 | /// <param name="error"></param> |
805 | (string)requestData["region_handle"]); | 805 | /// <returns></returns> |
806 | responseData["sim_ip"] = simData.serverIP; | 806 | public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error) |
807 | responseData["sim_port"] = simData.serverPort.ToString(); | 807 | { |
808 | responseData["server_uri"] = simData.serverURI; | 808 | XmlRpcResponse errorResponse = new XmlRpcResponse(); |
809 | responseData["http_port"] = simData.httpPort.ToString(); | 809 | Hashtable errorResponseData = new Hashtable(); |
810 | responseData["remoting_port"] = simData.remotingPort.ToString(); | 810 | errorResponse.Value = errorResponseData; |
811 | responseData["region_locx"] = simData.regionLocX.ToString(); | 811 | errorResponseData["restricted"] = error; |
812 | responseData["region_locy"] = simData.regionLocY.ToString(); | 812 | return errorResponse; |
813 | responseData["region_UUID"] = simData.UUID.Guid.ToString(); | 813 | } |
814 | responseData["region_name"] = simData.regionName; | 814 | } |
815 | responseData["regionHandle"] = simData.regionHandle.ToString(); | 815 | |
816 | } | 816 | /// <summary> |
817 | 817 | /// Exception generated when a simulator fails to login to the grid | |
818 | XmlRpcResponse response = new XmlRpcResponse(); | 818 | /// </summary> |
819 | response.Value = responseData; | 819 | public class LoginException : Exception |
820 | return response; | 820 | { |
821 | } | 821 | /// <summary> |
822 | 822 | /// Return an XmlRpcResponse version of the exception message suitable for sending to a client | |
823 | public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) | 823 | /// </summary> |
824 | { | 824 | /// <param name="message"></param> |
825 | int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; | 825 | /// <param name="xmlRpcMessage"></param> |
826 | 826 | public XmlRpcResponse XmlRpcErrorResponse | |
827 | Hashtable requestData = (Hashtable)request.Params[0]; | 827 | { |
828 | if (requestData.ContainsKey("xmin")) | 828 | get { return m_xmlRpcErrorResponse; } |
829 | { | 829 | } |
830 | xmin = (Int32)requestData["xmin"]; | 830 | private XmlRpcResponse m_xmlRpcErrorResponse; |
831 | } | 831 | |
832 | if (requestData.ContainsKey("ymin")) | 832 | public LoginException(string message, string xmlRpcMessage) : base(message) |
833 | { | 833 | { |
834 | ymin = (Int32)requestData["ymin"]; | 834 | // FIXME: Might be neater to refactor and put the method inside here |
835 | } | 835 | m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage); |
836 | if (requestData.ContainsKey("xmax")) | 836 | } |
837 | { | 837 | |
838 | xmax = (Int32)requestData["xmax"]; | 838 | public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e) |
839 | } | 839 | { |
840 | if (requestData.ContainsKey("ymax")) | 840 | // FIXME: Might be neater to refactor and put the method inside here |
841 | { | 841 | m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage); |
842 | ymax = (Int32)requestData["ymax"]; | 842 | } |
843 | } | 843 | } |
844 | //CFK: The second log is more meaningful and either standard or fast generally occurs. | 844 | } |
845 | //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
846 | |||
847 | XmlRpcResponse response = new XmlRpcResponse(); | ||
848 | Hashtable responseData = new Hashtable(); | ||
849 | response.Value = responseData; | ||
850 | IList simProfileList = new ArrayList(); | ||
851 | |||
852 | bool fastMode = (Config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || Config.DatabaseProvider == "OpenSim.Data.MSSQL.dll"); | ||
853 | |||
854 | if (fastMode) | ||
855 | { | ||
856 | List<RegionProfileData> neighbours = GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax); | ||
857 | |||
858 | foreach (RegionProfileData aSim in neighbours) | ||
859 | { | ||
860 | Hashtable simProfileBlock = new Hashtable(); | ||
861 | simProfileBlock["x"] = aSim.regionLocX.ToString(); | ||
862 | simProfileBlock["y"] = aSim.regionLocY.ToString(); | ||
863 | //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY); | ||
864 | simProfileBlock["name"] = aSim.regionName; | ||
865 | simProfileBlock["access"] = 21; | ||
866 | simProfileBlock["region-flags"] = 512; | ||
867 | simProfileBlock["water-height"] = 0; | ||
868 | simProfileBlock["agents"] = 1; | ||
869 | simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString(); | ||
870 | |||
871 | // For Sugilite compatibility | ||
872 | simProfileBlock["regionhandle"] = aSim.regionHandle.ToString(); | ||
873 | simProfileBlock["sim_ip"] = aSim.serverIP; | ||
874 | simProfileBlock["sim_port"] = aSim.serverPort.ToString(); | ||
875 | simProfileBlock["sim_uri"] = aSim.serverURI.ToString(); | ||
876 | simProfileBlock["uuid"] = aSim.UUID.ToString(); | ||
877 | simProfileBlock["remoting_port"] = aSim.remotingPort.ToString(); | ||
878 | simProfileBlock["http_port"] = aSim.httpPort.ToString(); | ||
879 | |||
880 | simProfileList.Add(simProfileBlock); | ||
881 | } | ||
882 | m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + | ||
883 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
884 | } | ||
885 | else | ||
886 | { | ||
887 | RegionProfileData simProfile; | ||
888 | for (int x = xmin; x < xmax + 1; x++) | ||
889 | { | ||
890 | for (int y = ymin; y < ymax + 1; y++) | ||
891 | { | ||
892 | ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); | ||
893 | simProfile = GetRegion(regHandle); | ||
894 | if (simProfile != null) | ||
895 | { | ||
896 | Hashtable simProfileBlock = new Hashtable(); | ||
897 | simProfileBlock["x"] = x; | ||
898 | simProfileBlock["y"] = y; | ||
899 | simProfileBlock["name"] = simProfile.regionName; | ||
900 | simProfileBlock["access"] = 0; | ||
901 | simProfileBlock["region-flags"] = 0; | ||
902 | simProfileBlock["water-height"] = 20; | ||
903 | simProfileBlock["agents"] = 1; | ||
904 | simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); | ||
905 | |||
906 | // For Sugilite compatibility | ||
907 | simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); | ||
908 | simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); | ||
909 | simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); | ||
910 | simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); | ||
911 | simProfileBlock["uuid"] = simProfile.UUID.ToString(); | ||
912 | simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString(); | ||
913 | simProfileBlock["http_port"] = simProfile.httpPort; | ||
914 | |||
915 | simProfileList.Add(simProfileBlock); | ||
916 | } | ||
917 | } | ||
918 | } | ||
919 | m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + | ||
920 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
921 | } | ||
922 | |||
923 | responseData["sim-profiles"] = simProfileList; | ||
924 | |||
925 | return response; | ||
926 | } | ||
927 | |||
928 | /// <summary> | ||
929 | /// Returns up to <code>maxNumber</code> profiles of regions that have a name starting with <code>name</code> | ||
930 | /// </summary> | ||
931 | /// <param name="request"></param> | ||
932 | /// <returns></returns> | ||
933 | public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request) | ||
934 | { | ||
935 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
936 | |||
937 | if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber")) | ||
938 | { | ||
939 | m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber"); | ||
940 | return new XmlRpcResponse(500, "Missing name or maxNumber in region search request"); | ||
941 | } | ||
942 | |||
943 | Hashtable responseData = new Hashtable(); | ||
944 | |||
945 | string name = (string)requestData["name"]; | ||
946 | int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]); | ||
947 | if (maxNumber == 0 || name.Length < 3) | ||
948 | { | ||
949 | // either we didn't want any, or we were too unspecific | ||
950 | responseData["numFound"] = 0; | ||
951 | } | ||
952 | else | ||
953 | { | ||
954 | List<RegionProfileData> sims = GetRegions(name, maxNumber); | ||
955 | |||
956 | responseData["numFound"] = sims.Count; | ||
957 | for (int i = 0; i < sims.Count; ++i) | ||
958 | { | ||
959 | RegionProfileData sim = sims[i]; | ||
960 | string prefix = "region" + i + "."; | ||
961 | responseData[prefix + "region_name"] = sim.regionName; | ||
962 | responseData[prefix + "region_UUID"] = sim.UUID.ToString(); | ||
963 | responseData[prefix + "region_locx"] = sim.regionLocX.ToString(); | ||
964 | responseData[prefix + "region_locy"] = sim.regionLocY.ToString(); | ||
965 | responseData[prefix + "sim_ip"] = sim.serverIP.ToString(); | ||
966 | responseData[prefix + "sim_port"] = sim.serverPort.ToString(); | ||
967 | responseData[prefix + "remoting_port"] = sim.remotingPort.ToString(); | ||
968 | responseData[prefix + "http_port"] = sim.httpPort.ToString(); | ||
969 | responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString(); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | XmlRpcResponse response = new XmlRpcResponse(); | ||
974 | response.Value = responseData; | ||
975 | return response; | ||
976 | } | ||
977 | |||
978 | /// <summary> | ||
979 | /// Performs a REST Get Operation | ||
980 | /// </summary> | ||
981 | /// <param name="request"></param> | ||
982 | /// <param name="path"></param> | ||
983 | /// <param name="param"></param> | ||
984 | /// <param name="httpRequest">HTTP request header object</param> | ||
985 | /// <param name="httpResponse">HTTP response header object</param> | ||
986 | /// <returns></returns> | ||
987 | public string RestGetRegionMethod(string request, string path, string param, | ||
988 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
989 | { | ||
990 | return RestGetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); | ||
991 | } | ||
992 | |||
993 | /// <summary> | ||
994 | /// Performs a REST Set Operation | ||
995 | /// </summary> | ||
996 | /// <param name="request"></param> | ||
997 | /// <param name="path"></param> | ||
998 | /// <param name="param"></param> | ||
999 | /// <param name="httpRequest">HTTP request header object</param> | ||
1000 | /// <param name="httpResponse">HTTP response header object</param> | ||
1001 | /// <returns></returns> | ||
1002 | public string RestSetRegionMethod(string request, string path, string param, | ||
1003 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
1004 | { | ||
1005 | return RestSetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); | ||
1006 | } | ||
1007 | |||
1008 | /// <summary> | ||
1009 | /// Returns information about a sim via a REST Request | ||
1010 | /// </summary> | ||
1011 | /// <param name="request"></param> | ||
1012 | /// <param name="path"></param> | ||
1013 | /// <param name="param">A string representing the sim's UUID</param> | ||
1014 | /// <param name="httpRequest">HTTP request header object</param> | ||
1015 | /// <param name="httpResponse">HTTP response header object</param> | ||
1016 | /// <returns>Information about the sim in XML</returns> | ||
1017 | public string RestGetSimMethod(string request, string path, string param, | ||
1018 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
1019 | { | ||
1020 | string respstring = String.Empty; | ||
1021 | |||
1022 | RegionProfileData TheSim; | ||
1023 | |||
1024 | UUID UUID; | ||
1025 | if (UUID.TryParse(param, out UUID)) | ||
1026 | { | ||
1027 | TheSim = GetRegion(UUID); | ||
1028 | |||
1029 | if (!(TheSim == null)) | ||
1030 | { | ||
1031 | respstring = "<Root>"; | ||
1032 | respstring += "<authkey>" + TheSim.regionSendKey + "</authkey>"; | ||
1033 | respstring += "<sim>"; | ||
1034 | respstring += "<uuid>" + TheSim.UUID.ToString() + "</uuid>"; | ||
1035 | respstring += "<regionname>" + TheSim.regionName + "</regionname>"; | ||
1036 | respstring += "<sim_ip>" + TheSim.serverIP + "</sim_ip>"; | ||
1037 | respstring += "<sim_port>" + TheSim.serverPort.ToString() + "</sim_port>"; | ||
1038 | respstring += "<region_locx>" + TheSim.regionLocX.ToString() + "</region_locx>"; | ||
1039 | respstring += "<region_locy>" + TheSim.regionLocY.ToString() + "</region_locy>"; | ||
1040 | respstring += "<estate_id>1</estate_id>"; | ||
1041 | respstring += "</sim>"; | ||
1042 | respstring += "</Root>"; | ||
1043 | } | ||
1044 | } | ||
1045 | else | ||
1046 | { | ||
1047 | respstring = "<Root>"; | ||
1048 | respstring += "<error>Param must be a UUID</error>"; | ||
1049 | respstring += "</Root>"; | ||
1050 | } | ||
1051 | |||
1052 | return respstring; | ||
1053 | } | ||
1054 | |||
1055 | /// <summary> | ||
1056 | /// Creates or updates a sim via a REST Method Request | ||
1057 | /// BROKEN with SQL Update | ||
1058 | /// </summary> | ||
1059 | /// <param name="request"></param> | ||
1060 | /// <param name="path"></param> | ||
1061 | /// <param name="param"></param> | ||
1062 | /// <param name="httpRequest">HTTP request header object</param> | ||
1063 | /// <param name="httpResponse">HTTP response header object</param> | ||
1064 | /// <returns>"OK" or an error</returns> | ||
1065 | public string RestSetSimMethod(string request, string path, string param, | ||
1066 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
1067 | { | ||
1068 | Console.WriteLine("Processing region update via REST method"); | ||
1069 | RegionProfileData theSim; | ||
1070 | theSim = GetRegion(new UUID(param)); | ||
1071 | if (theSim == null) | ||
1072 | { | ||
1073 | theSim = new RegionProfileData(); | ||
1074 | UUID UUID = new UUID(param); | ||
1075 | theSim.UUID = UUID; | ||
1076 | theSim.regionRecvKey = Config.SimRecvKey; | ||
1077 | } | ||
1078 | |||
1079 | XmlDocument doc = new XmlDocument(); | ||
1080 | doc.LoadXml(request); | ||
1081 | XmlNode rootnode = doc.FirstChild; | ||
1082 | XmlNode authkeynode = rootnode.ChildNodes[0]; | ||
1083 | if (authkeynode.Name != "authkey") | ||
1084 | { | ||
1085 | return "ERROR! bad XML - expected authkey tag"; | ||
1086 | } | ||
1087 | |||
1088 | XmlNode simnode = rootnode.ChildNodes[1]; | ||
1089 | if (simnode.Name != "sim") | ||
1090 | { | ||
1091 | return "ERROR! bad XML - expected sim tag"; | ||
1092 | } | ||
1093 | |||
1094 | //theSim.regionSendKey = Cfg; | ||
1095 | theSim.regionRecvKey = Config.SimRecvKey; | ||
1096 | theSim.regionSendKey = Config.SimSendKey; | ||
1097 | theSim.regionSecret = Config.SimRecvKey; | ||
1098 | theSim.regionDataURI = String.Empty; | ||
1099 | theSim.regionAssetURI = Config.DefaultAssetServer; | ||
1100 | theSim.regionAssetRecvKey = Config.AssetRecvKey; | ||
1101 | theSim.regionAssetSendKey = Config.AssetSendKey; | ||
1102 | theSim.regionUserURI = Config.DefaultUserServer; | ||
1103 | theSim.regionUserSendKey = Config.UserSendKey; | ||
1104 | theSim.regionUserRecvKey = Config.UserRecvKey; | ||
1105 | |||
1106 | for (int i = 0; i < simnode.ChildNodes.Count; i++) | ||
1107 | { | ||
1108 | switch (simnode.ChildNodes[i].Name) | ||
1109 | { | ||
1110 | case "regionname": | ||
1111 | theSim.regionName = simnode.ChildNodes[i].InnerText; | ||
1112 | break; | ||
1113 | |||
1114 | case "sim_ip": | ||
1115 | theSim.serverIP = simnode.ChildNodes[i].InnerText; | ||
1116 | break; | ||
1117 | |||
1118 | case "sim_port": | ||
1119 | theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText); | ||
1120 | break; | ||
1121 | |||
1122 | case "region_locx": | ||
1123 | theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); | ||
1124 | theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); | ||
1125 | break; | ||
1126 | |||
1127 | case "region_locy": | ||
1128 | theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); | ||
1129 | theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); | ||
1130 | break; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/"; | ||
1135 | bool requirePublic = false; | ||
1136 | bool requireValid = true; | ||
1137 | |||
1138 | if (requirePublic && | ||
1139 | (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") || | ||
1140 | theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") || | ||
1141 | theSim.serverIP.StartsWith("255."))) | ||
1142 | { | ||
1143 | return "ERROR! Servers must register with public addresses."; | ||
1144 | } | ||
1145 | |||
1146 | if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255."))) | ||
1147 | { | ||
1148 | return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again"; | ||
1149 | } | ||
1150 | |||
1151 | try | ||
1152 | { | ||
1153 | m_log.Info("[DATA]: " + | ||
1154 | "Updating / adding via " + _plugins.Count + " storage provider(s) registered."); | ||
1155 | |||
1156 | foreach (IGridDataPlugin plugin in _plugins) | ||
1157 | { | ||
1158 | try | ||
1159 | { | ||
1160 | //Check reservations | ||
1161 | ReservationData reserveData = | ||
1162 | plugin.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY); | ||
1163 | if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) || | ||
1164 | (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey)) | ||
1165 | { | ||
1166 | plugin.AddProfile(theSim); | ||
1167 | m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")"); | ||
1168 | logToDB(theSim.ToString(), "RestSetSimMethod", String.Empty, 5, | ||
1169 | "Region successfully updated and connected to grid."); | ||
1170 | } | ||
1171 | else | ||
1172 | { | ||
1173 | m_log.Warn("[grid]: " + | ||
1174 | "Unable to update region (RestSetSimMethod): Incorrect reservation auth key."); | ||
1175 | // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + "."); | ||
1176 | return "Unable to update region (RestSetSimMethod): Incorrect auth key."; | ||
1177 | } | ||
1178 | } | ||
1179 | catch (Exception e) | ||
1180 | { | ||
1181 | m_log.Warn("[GRID]: GetRegionPlugin Handle " + plugin.Name + " unable to add new sim: " + | ||
1182 | e.ToString()); | ||
1183 | } | ||
1184 | } | ||
1185 | return "OK"; | ||
1186 | } | ||
1187 | catch (Exception e) | ||
1188 | { | ||
1189 | return "ERROR! Could not save to database! (" + e.ToString() + ")"; | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) | ||
1194 | { | ||
1195 | XmlRpcResponse response = new XmlRpcResponse(); | ||
1196 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1197 | Hashtable responseData = new Hashtable(); | ||
1198 | |||
1199 | if (requestData.Contains("uri")) | ||
1200 | { | ||
1201 | string URI = (string)requestData["URI"]; | ||
1202 | string sendkey = (string)requestData["sendkey"]; | ||
1203 | string recvkey = (string)requestData["recvkey"]; | ||
1204 | MessageServerInfo m = new MessageServerInfo(); | ||
1205 | m.URI = URI; | ||
1206 | m.sendkey = sendkey; | ||
1207 | m.recvkey = recvkey; | ||
1208 | if (!_MessageServers.Contains(m)) | ||
1209 | _MessageServers.Add(m); | ||
1210 | responseData["responsestring"] = "TRUE"; | ||
1211 | response.Value = responseData; | ||
1212 | } | ||
1213 | return response; | ||
1214 | } | ||
1215 | |||
1216 | public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) | ||
1217 | { | ||
1218 | XmlRpcResponse response = new XmlRpcResponse(); | ||
1219 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1220 | Hashtable responseData = new Hashtable(); | ||
1221 | |||
1222 | if (requestData.Contains("uri")) | ||
1223 | { | ||
1224 | string URI = (string)requestData["uri"]; | ||
1225 | string sendkey = (string)requestData["sendkey"]; | ||
1226 | string recvkey = (string)requestData["recvkey"]; | ||
1227 | MessageServerInfo m = new MessageServerInfo(); | ||
1228 | m.URI = URI; | ||
1229 | m.sendkey = sendkey; | ||
1230 | m.recvkey = recvkey; | ||
1231 | if (_MessageServers.Contains(m)) | ||
1232 | _MessageServers.Remove(m); | ||
1233 | responseData["responsestring"] = "TRUE"; | ||
1234 | response.Value = responseData; | ||
1235 | } | ||
1236 | return response; | ||
1237 | } | ||
1238 | |||
1239 | /// <summary> | ||
1240 | /// Construct an XMLRPC registration disabled response | ||
1241 | /// </summary> | ||
1242 | /// <param name="error"></param> | ||
1243 | /// <returns></returns> | ||
1244 | public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error) | ||
1245 | { | ||
1246 | XmlRpcResponse errorResponse = new XmlRpcResponse(); | ||
1247 | Hashtable errorResponseData = new Hashtable(); | ||
1248 | errorResponse.Value = errorResponseData; | ||
1249 | errorResponseData["restricted"] = error; | ||
1250 | return errorResponse; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | /// <summary> | ||
1255 | /// Exception generated when a simulator fails to login to the grid | ||
1256 | /// </summary> | ||
1257 | public class LoginException : Exception | ||
1258 | { | ||
1259 | /// <summary> | ||
1260 | /// Return an XmlRpcResponse version of the exception message suitable for sending to a client | ||
1261 | /// </summary> | ||
1262 | /// <param name="message"></param> | ||
1263 | /// <param name="xmlRpcMessage"></param> | ||
1264 | public XmlRpcResponse XmlRpcErrorResponse | ||
1265 | { | ||
1266 | get { return m_xmlRpcErrorResponse; } | ||
1267 | } | ||
1268 | private XmlRpcResponse m_xmlRpcErrorResponse; | ||
1269 | |||
1270 | public LoginException(string message, string xmlRpcMessage) : base(message) | ||
1271 | { | ||
1272 | // FIXME: Might be neater to refactor and put the method inside here | ||
1273 | m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage); | ||
1274 | } | ||
1275 | |||
1276 | public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e) | ||
1277 | { | ||
1278 | // FIXME: Might be neater to refactor and put the method inside here | ||
1279 | m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage); | ||
1280 | } | ||
1281 | } | ||
1282 | } | ||
diff --git a/OpenSim/Grid/GridServer/IGridCore.cs b/OpenSim/Grid/GridServer/IGridCore.cs new file mode 100644 index 0000000..dd0d140 --- /dev/null +++ b/OpenSim/Grid/GridServer/IGridCore.cs | |||
@@ -0,0 +1,13 @@ | |||
1 | using System; | ||
2 | using OpenSim.Framework.Servers; | ||
3 | |||
4 | namespace OpenSim.Grid.GridServer | ||
5 | { | ||
6 | public interface IGridCore | ||
7 | { | ||
8 | T Get<T>(); | ||
9 | void RegisterInterface<T>(T iface); | ||
10 | bool TryGet<T>(out T iface); | ||
11 | BaseHttpServer GetHttpServer(); | ||
12 | } | ||
13 | } | ||
diff --git a/OpenSim/Grid/GridServer/IGridMessagingModule.cs b/OpenSim/Grid/GridServer/IGridMessagingModule.cs new file mode 100644 index 0000000..969910e --- /dev/null +++ b/OpenSim/Grid/GridServer/IGridMessagingModule.cs | |||
@@ -0,0 +1,11 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using OpenSim.Framework.Servers; | ||
4 | |||
5 | namespace OpenSim.Grid.GridServer | ||
6 | { | ||
7 | public interface IGridMessagingModule | ||
8 | { | ||
9 | List<MessageServerInfo> MessageServers { get; } | ||
10 | } | ||
11 | } | ||