diff options
Diffstat (limited to 'OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs')
-rw-r--r-- | OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs | 928 |
1 files changed, 928 insertions, 0 deletions
diff --git a/OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs b/OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs new file mode 100644 index 0000000..4dc26e0 --- /dev/null +++ b/OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs | |||
@@ -0,0 +1,928 @@ | |||
1 | /** | ||
2 | * Copyright (c) 2008, Contributors. All rights reserved. | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without modification, | ||
6 | * are permitted provided that the following conditions are met: | ||
7 | * | ||
8 | * * Redistributions of source code must retain the above copyright notice, | ||
9 | * this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright notice, | ||
11 | * this list of conditions and the following disclaimer in the documentation | ||
12 | * and/or other materials provided with the distribution. | ||
13 | * * Neither the name of the Organizations nor the names of Individual | ||
14 | * Contributors may be used to endorse or promote products derived from | ||
15 | * this software without specific prior written permission. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
20 | * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | ||
22 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
23 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
24 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
25 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Net; | ||
32 | using System.Net.Sockets; | ||
33 | using System.Reflection; | ||
34 | using System.Runtime.Remoting; | ||
35 | using System.Runtime.Remoting.Channels; | ||
36 | using System.Runtime.Remoting.Channels.Tcp; | ||
37 | using System.Security.Authentication; | ||
38 | |||
39 | using OpenSim.Framework; | ||
40 | using OpenSim.Framework.Communications; | ||
41 | using OpenSim.Framework.Communications.Cache; | ||
42 | using OpenSim.Framework.Servers; | ||
43 | using OpenSim.Region.Communications.Local; | ||
44 | using OpenSim.Region.Communications.OGS1; | ||
45 | using OpenSim.Region.Environment.Scenes; | ||
46 | |||
47 | using OpenMetaverse; | ||
48 | using Nwc.XmlRpc; | ||
49 | using log4net; | ||
50 | |||
51 | namespace OpenSim.Region.Communications.Hypergrid | ||
52 | { | ||
53 | public class HGGridServicesStandalone : HGGridServices | ||
54 | { | ||
55 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
56 | |||
57 | /// <summary> | ||
58 | /// Encapsulate local backend services for manipulation of local regions | ||
59 | /// </summary> | ||
60 | protected LocalBackEndServices m_localBackend = new LocalBackEndServices(); | ||
61 | |||
62 | private Dictionary<ulong, int> m_deadRegionCache = new Dictionary<ulong, int>(); | ||
63 | |||
64 | public LocalBackEndServices LocalBackend | ||
65 | { | ||
66 | get { return m_localBackend; } | ||
67 | } | ||
68 | |||
69 | public override string gdebugRegionName | ||
70 | { | ||
71 | get { return m_localBackend.gdebugRegionName; } | ||
72 | set { m_localBackend.gdebugRegionName = value; } | ||
73 | } | ||
74 | |||
75 | public override bool RegionLoginsEnabled | ||
76 | { | ||
77 | get { return m_localBackend.RegionLoginsEnabled; } | ||
78 | set { m_localBackend.RegionLoginsEnabled = value; } | ||
79 | } | ||
80 | |||
81 | |||
82 | public HGGridServicesStandalone(NetworkServersInfo servers_info, BaseHttpServer httpServe, AssetCache asscache, SceneManager sman) | ||
83 | : base(servers_info, httpServe, asscache, sman) | ||
84 | { | ||
85 | //Respond to Grid Services requests | ||
86 | httpServer.AddXmlRPCHandler("logoff_user", LogOffUser); | ||
87 | httpServer.AddXmlRPCHandler("check", PingCheckReply); | ||
88 | httpServer.AddXmlRPCHandler("land_data", LandData); | ||
89 | |||
90 | StartRemoting(); | ||
91 | } | ||
92 | |||
93 | #region IGridServices interface | ||
94 | |||
95 | public override RegionCommsListener RegisterRegion(RegionInfo regionInfo) | ||
96 | { | ||
97 | if (!regionInfo.RegionID.Equals(UUID.Zero)) | ||
98 | { | ||
99 | m_regionsOnInstance.Add(regionInfo); | ||
100 | return m_localBackend.RegisterRegion(regionInfo); | ||
101 | } | ||
102 | else | ||
103 | return base.RegisterRegion(regionInfo); | ||
104 | |||
105 | } | ||
106 | |||
107 | public override bool DeregisterRegion(RegionInfo regionInfo) | ||
108 | { | ||
109 | bool success = m_localBackend.DeregisterRegion(regionInfo); | ||
110 | if (!success) | ||
111 | success = base.DeregisterRegion(regionInfo); | ||
112 | return success; | ||
113 | } | ||
114 | |||
115 | public override List<SimpleRegionInfo> RequestNeighbours(uint x, uint y) | ||
116 | { | ||
117 | List<SimpleRegionInfo> neighbours = m_localBackend.RequestNeighbours(x, y); | ||
118 | List<SimpleRegionInfo> remotes = base.RequestNeighbours(x, y); | ||
119 | neighbours.AddRange(remotes); | ||
120 | |||
121 | return neighbours; | ||
122 | } | ||
123 | |||
124 | public override RegionInfo RequestNeighbourInfo(UUID Region_UUID) | ||
125 | { | ||
126 | RegionInfo info = m_localBackend.RequestNeighbourInfo(Region_UUID); | ||
127 | if (info == null) | ||
128 | info = base.RequestNeighbourInfo(Region_UUID); | ||
129 | return info; | ||
130 | } | ||
131 | |||
132 | public override RegionInfo RequestNeighbourInfo(ulong regionHandle) | ||
133 | { | ||
134 | RegionInfo info = m_localBackend.RequestNeighbourInfo(regionHandle); | ||
135 | //m_log.Info("[HGrid] Request neighbor info, local backend returned " + info); | ||
136 | if (info == null) | ||
137 | info = base.RequestNeighbourInfo(regionHandle); | ||
138 | return info; | ||
139 | } | ||
140 | |||
141 | public override RegionInfo RequestClosestRegion(string regionName) | ||
142 | { | ||
143 | RegionInfo info = m_localBackend.RequestClosestRegion(regionName); | ||
144 | if (info == null) | ||
145 | info = base.RequestClosestRegion(regionName); | ||
146 | return info; | ||
147 | } | ||
148 | |||
149 | public override List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY) | ||
150 | { | ||
151 | //m_log.Info("[HGrid] Request map blocks " + minX + "-" + minY + "-" + maxX + "-" + maxY); | ||
152 | List<MapBlockData> neighbours = m_localBackend.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); | ||
153 | List<MapBlockData> remotes = base.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); | ||
154 | neighbours.AddRange(remotes); | ||
155 | |||
156 | return neighbours; | ||
157 | } | ||
158 | |||
159 | public override LandData RequestLandData(ulong regionHandle, uint x, uint y) | ||
160 | { | ||
161 | LandData land = m_localBackend.RequestLandData(regionHandle, x, y); | ||
162 | if (land == null) | ||
163 | land = base.RequestLandData(regionHandle, x, y); | ||
164 | return land; | ||
165 | } | ||
166 | |||
167 | public override List<RegionInfo> RequestNamedRegions(string name, int maxNumber) | ||
168 | { | ||
169 | List<RegionInfo> infos = m_localBackend.RequestNamedRegions(name, maxNumber); | ||
170 | List<RegionInfo> remotes = base.RequestNamedRegions(name, maxNumber); | ||
171 | infos.AddRange(remotes); | ||
172 | return infos; | ||
173 | } | ||
174 | |||
175 | #endregion | ||
176 | |||
177 | #region XML Request Handlers | ||
178 | |||
179 | /// <summary> | ||
180 | /// A ping / version check | ||
181 | /// </summary> | ||
182 | /// <param name="request"></param> | ||
183 | /// <returns></returns> | ||
184 | public virtual XmlRpcResponse PingCheckReply(XmlRpcRequest request) | ||
185 | { | ||
186 | XmlRpcResponse response = new XmlRpcResponse(); | ||
187 | |||
188 | Hashtable respData = new Hashtable(); | ||
189 | respData["online"] = "true"; | ||
190 | |||
191 | m_localBackend.PingCheckReply(respData); | ||
192 | |||
193 | response.Value = respData; | ||
194 | |||
195 | return response; | ||
196 | } | ||
197 | |||
198 | |||
199 | // Grid Request Processing | ||
200 | /// <summary> | ||
201 | /// Ooops, our Agent must be dead if we're getting this request! | ||
202 | /// </summary> | ||
203 | /// <param name="request"></param> | ||
204 | /// <returns></returns> | ||
205 | public XmlRpcResponse LogOffUser(XmlRpcRequest request) | ||
206 | { | ||
207 | m_log.Debug("[HGrid]: LogOff User Called"); | ||
208 | |||
209 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
210 | string message = (string)requestData["message"]; | ||
211 | UUID agentID = UUID.Zero; | ||
212 | UUID RegionSecret = UUID.Zero; | ||
213 | UUID.TryParse((string)requestData["agent_id"], out agentID); | ||
214 | UUID.TryParse((string)requestData["region_secret"], out RegionSecret); | ||
215 | |||
216 | ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); | ||
217 | |||
218 | m_localBackend.TriggerLogOffUser(regionHandle, agentID, RegionSecret, message); | ||
219 | |||
220 | return new XmlRpcResponse(); | ||
221 | } | ||
222 | |||
223 | /// <summary> | ||
224 | /// Someone asked us about parcel-information | ||
225 | /// </summary> | ||
226 | /// <param name="request"></param> | ||
227 | /// <returns></returns> | ||
228 | public XmlRpcResponse LandData(XmlRpcRequest request) | ||
229 | { | ||
230 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
231 | ulong regionHandle = Convert.ToUInt64(requestData["region_handle"]); | ||
232 | uint x = Convert.ToUInt32(requestData["x"]); | ||
233 | uint y = Convert.ToUInt32(requestData["y"]); | ||
234 | m_log.DebugFormat("[HGrid]: Got XML reqeuest for land data at {0}, {1} in region {2}", x, y, regionHandle); | ||
235 | |||
236 | LandData landData = m_localBackend.RequestLandData(regionHandle, x, y); | ||
237 | Hashtable hash = new Hashtable(); | ||
238 | if (landData != null) | ||
239 | { | ||
240 | // for now, only push out the data we need for answering a ParcelInfoReqeust | ||
241 | hash["AABBMax"] = landData.AABBMax.ToString(); | ||
242 | hash["AABBMin"] = landData.AABBMin.ToString(); | ||
243 | hash["Area"] = landData.Area.ToString(); | ||
244 | hash["AuctionID"] = landData.AuctionID.ToString(); | ||
245 | hash["Description"] = landData.Description; | ||
246 | hash["Flags"] = landData.Flags.ToString(); | ||
247 | hash["GlobalID"] = landData.GlobalID.ToString(); | ||
248 | hash["Name"] = landData.Name; | ||
249 | hash["OwnerID"] = landData.OwnerID.ToString(); | ||
250 | hash["SalePrice"] = landData.SalePrice.ToString(); | ||
251 | hash["SnapshotID"] = landData.SnapshotID.ToString(); | ||
252 | hash["UserLocation"] = landData.UserLocation.ToString(); | ||
253 | } | ||
254 | |||
255 | XmlRpcResponse response = new XmlRpcResponse(); | ||
256 | response.Value = hash; | ||
257 | return response; | ||
258 | } | ||
259 | |||
260 | #endregion | ||
261 | |||
262 | #region Remoting | ||
263 | |||
264 | /// <summary> | ||
265 | /// Start listening for .net remoting calls from other regions. | ||
266 | /// </summary> | ||
267 | private void StartRemoting() | ||
268 | { | ||
269 | m_log.Info("[HGrid]: Start remoting..."); | ||
270 | TcpChannel ch; | ||
271 | try | ||
272 | { | ||
273 | ch = new TcpChannel((int)NetworkServersInfo.RemotingListenerPort); | ||
274 | ChannelServices.RegisterChannel(ch, false); // Disabled security as Mono doesn't support this. | ||
275 | } | ||
276 | catch (Exception ex) | ||
277 | { | ||
278 | m_log.Error("[HGrid]: Exception while attempting to listen on TCP port " + (int)NetworkServersInfo.RemotingListenerPort + "."); | ||
279 | throw (ex); | ||
280 | } | ||
281 | |||
282 | WellKnownServiceTypeEntry wellType = | ||
283 | new WellKnownServiceTypeEntry(typeof(OGS1InterRegionRemoting), "InterRegions", | ||
284 | WellKnownObjectMode.Singleton); | ||
285 | RemotingConfiguration.RegisterWellKnownServiceType(wellType); | ||
286 | InterRegionSingleton.Instance.OnArrival += TriggerExpectAvatarCrossing; | ||
287 | InterRegionSingleton.Instance.OnChildAgent += IncomingChildAgent; | ||
288 | InterRegionSingleton.Instance.OnPrimGroupArrival += IncomingPrim; | ||
289 | InterRegionSingleton.Instance.OnPrimGroupNear += TriggerExpectPrimCrossing; | ||
290 | InterRegionSingleton.Instance.OnRegionUp += TriggerRegionUp; | ||
291 | InterRegionSingleton.Instance.OnChildAgentUpdate += TriggerChildAgentUpdate; | ||
292 | InterRegionSingleton.Instance.OnTellRegionToCloseChildConnection += TriggerTellRegionToCloseChildConnection; | ||
293 | } | ||
294 | |||
295 | |||
296 | #endregion | ||
297 | |||
298 | #region IInterRegionCommunications interface (Methods called by regions in this instance) | ||
299 | |||
300 | public override bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) | ||
301 | { | ||
302 | int failures = 0; | ||
303 | lock (m_deadRegionCache) | ||
304 | { | ||
305 | if (m_deadRegionCache.ContainsKey(regionHandle)) | ||
306 | { | ||
307 | failures = m_deadRegionCache[regionHandle]; | ||
308 | } | ||
309 | } | ||
310 | if (failures <= 3) | ||
311 | { | ||
312 | RegionInfo regInfo = null; | ||
313 | try | ||
314 | { | ||
315 | if (m_localBackend.ChildAgentUpdate(regionHandle, cAgentData)) | ||
316 | { | ||
317 | return true; | ||
318 | } | ||
319 | |||
320 | regInfo = RequestNeighbourInfo(regionHandle); | ||
321 | if (regInfo != null) | ||
322 | { | ||
323 | //don't want to be creating a new link to the remote instance every time like we are here | ||
324 | bool retValue = false; | ||
325 | |||
326 | |||
327 | OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( | ||
328 | typeof(OGS1InterRegionRemoting), | ||
329 | "tcp://" + regInfo.RemotingAddress + | ||
330 | ":" + regInfo.RemotingPort + | ||
331 | "/InterRegions"); | ||
332 | |||
333 | if (remObject != null) | ||
334 | { | ||
335 | retValue = remObject.ChildAgentUpdate(regionHandle, cAgentData); | ||
336 | } | ||
337 | else | ||
338 | { | ||
339 | m_log.Warn("[HGrid]: remoting object not found"); | ||
340 | } | ||
341 | remObject = null; | ||
342 | |||
343 | return retValue; | ||
344 | } | ||
345 | NoteDeadRegion(regionHandle); | ||
346 | |||
347 | return false; | ||
348 | } | ||
349 | catch (RemotingException e) | ||
350 | { | ||
351 | NoteDeadRegion(regionHandle); | ||
352 | |||
353 | m_log.WarnFormat( | ||
354 | "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", | ||
355 | regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); | ||
356 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
357 | |||
358 | return false; | ||
359 | } | ||
360 | catch (SocketException e) | ||
361 | { | ||
362 | NoteDeadRegion(regionHandle); | ||
363 | |||
364 | m_log.WarnFormat( | ||
365 | "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", | ||
366 | regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); | ||
367 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
368 | |||
369 | return false; | ||
370 | } | ||
371 | catch (InvalidCredentialException e) | ||
372 | { | ||
373 | NoteDeadRegion(regionHandle); | ||
374 | |||
375 | m_log.WarnFormat( | ||
376 | "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", | ||
377 | regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); | ||
378 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
379 | |||
380 | return false; | ||
381 | } | ||
382 | catch (AuthenticationException e) | ||
383 | { | ||
384 | NoteDeadRegion(regionHandle); | ||
385 | |||
386 | m_log.WarnFormat( | ||
387 | "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", | ||
388 | regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); | ||
389 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
390 | |||
391 | return false; | ||
392 | } | ||
393 | catch (Exception e) | ||
394 | { | ||
395 | NoteDeadRegion(regionHandle); | ||
396 | |||
397 | m_log.WarnFormat("[HGrid]: Unable to connect to adjacent region: {0} {1},{2}", | ||
398 | regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); | ||
399 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
400 | |||
401 | return false; | ||
402 | } | ||
403 | } | ||
404 | else | ||
405 | { | ||
406 | //m_log.Info("[INTERREGION]: Skipped Sending Child Update to a region because it failed too many times:" + regionHandle.ToString()); | ||
407 | return false; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /// <summary> | ||
412 | /// Inform a region that a child agent will be on the way from a client. | ||
413 | /// </summary> | ||
414 | /// <param name="regionHandle"></param> | ||
415 | /// <param name="agentData"></param> | ||
416 | /// <returns></returns> | ||
417 | public override bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData) | ||
418 | { | ||
419 | |||
420 | if (m_localBackend.InformRegionOfChildAgent(regionHandle, agentData)) | ||
421 | { | ||
422 | return true; | ||
423 | } | ||
424 | return base.InformRegionOfChildAgent(regionHandle, agentData); | ||
425 | } | ||
426 | |||
427 | // UGLY! | ||
428 | public override bool RegionUp(SerializableRegionInfo region, ulong regionhandle) | ||
429 | { | ||
430 | if (m_localBackend.RegionUp(region, regionhandle)) | ||
431 | return true; | ||
432 | return base.RegionUp(region, regionhandle); | ||
433 | } | ||
434 | |||
435 | /// <summary> | ||
436 | /// | ||
437 | /// </summary> | ||
438 | /// <param name="regionHandle"></param> | ||
439 | /// <param name="agentData"></param> | ||
440 | /// <returns></returns> | ||
441 | public override bool InformRegionOfPrimCrossing(ulong regionHandle, UUID primID, string objData, int XMLMethod) | ||
442 | { | ||
443 | int failures = 0; | ||
444 | lock (m_deadRegionCache) | ||
445 | { | ||
446 | if (m_deadRegionCache.ContainsKey(regionHandle)) | ||
447 | { | ||
448 | failures = m_deadRegionCache[regionHandle]; | ||
449 | } | ||
450 | } | ||
451 | if (failures <= 1) | ||
452 | { | ||
453 | RegionInfo regInfo = null; | ||
454 | try | ||
455 | { | ||
456 | if (m_localBackend.InformRegionOfPrimCrossing(regionHandle, primID, objData, XMLMethod)) | ||
457 | { | ||
458 | return true; | ||
459 | } | ||
460 | |||
461 | regInfo = RequestNeighbourInfo(regionHandle); | ||
462 | if (regInfo != null) | ||
463 | { | ||
464 | //don't want to be creating a new link to the remote instance every time like we are here | ||
465 | bool retValue = false; | ||
466 | |||
467 | OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( | ||
468 | typeof(OGS1InterRegionRemoting), | ||
469 | "tcp://" + regInfo.RemotingAddress + | ||
470 | ":" + regInfo.RemotingPort + | ||
471 | "/InterRegions"); | ||
472 | |||
473 | if (remObject != null) | ||
474 | { | ||
475 | retValue = remObject.InformRegionOfPrimCrossing(regionHandle, primID.Guid, objData, XMLMethod); | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | m_log.Warn("[HGrid]: Remoting object not found"); | ||
480 | } | ||
481 | remObject = null; | ||
482 | |||
483 | return retValue; | ||
484 | } | ||
485 | NoteDeadRegion(regionHandle); | ||
486 | return false; | ||
487 | } | ||
488 | catch (RemotingException e) | ||
489 | { | ||
490 | NoteDeadRegion(regionHandle); | ||
491 | m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); | ||
492 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
493 | return false; | ||
494 | } | ||
495 | catch (SocketException e) | ||
496 | { | ||
497 | NoteDeadRegion(regionHandle); | ||
498 | m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); | ||
499 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
500 | return false; | ||
501 | } | ||
502 | catch (InvalidCredentialException e) | ||
503 | { | ||
504 | NoteDeadRegion(regionHandle); | ||
505 | m_log.Warn("[HGrid]: Invalid Credential Exception: Invalid Credentials : " + regionHandle); | ||
506 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
507 | return false; | ||
508 | } | ||
509 | catch (AuthenticationException e) | ||
510 | { | ||
511 | NoteDeadRegion(regionHandle); | ||
512 | m_log.Warn("[HGrid]: Authentication exception: Unable to connect to adjacent region: " + regionHandle); | ||
513 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
514 | return false; | ||
515 | } | ||
516 | catch (Exception e) | ||
517 | { | ||
518 | NoteDeadRegion(regionHandle); | ||
519 | m_log.Warn("[HGrid]: Unknown exception: Unable to connect to adjacent region: " + regionHandle); | ||
520 | m_log.DebugFormat("[HGrid]: {0}", e); | ||
521 | return false; | ||
522 | } | ||
523 | } | ||
524 | else | ||
525 | { | ||
526 | return false; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | /// <summary> | ||
531 | /// | ||
532 | /// </summary> | ||
533 | /// <param name="regionHandle"></param> | ||
534 | /// <param name="agentID"></param> | ||
535 | /// <param name="position"></param> | ||
536 | /// <returns></returns> | ||
537 | public override bool ExpectAvatarCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isFlying) | ||
538 | { | ||
539 | |||
540 | RegionInfo[] regions = m_regionsOnInstance.ToArray(); | ||
541 | bool banned = false; | ||
542 | bool localregion = false; | ||
543 | |||
544 | for (int i = 0; i < regions.Length; i++) | ||
545 | { | ||
546 | if (regions[i] != null) | ||
547 | { | ||
548 | if (regions[i].RegionHandle == regionHandle) | ||
549 | { | ||
550 | localregion = true; | ||
551 | if (regions[i].EstateSettings.IsBanned(agentID)) | ||
552 | { | ||
553 | banned = true; | ||
554 | break; | ||
555 | } | ||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | if (banned) | ||
561 | return false; | ||
562 | if (localregion) | ||
563 | return m_localBackend.ExpectAvatarCrossing(regionHandle, agentID, position, isFlying); | ||
564 | |||
565 | return base.ExpectAvatarCrossing(regionHandle, agentID, position, isFlying); | ||
566 | |||
567 | } | ||
568 | |||
569 | public override bool ExpectPrimCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isPhysical) | ||
570 | { | ||
571 | RegionInfo regInfo = null; | ||
572 | try | ||
573 | { | ||
574 | if (m_localBackend.TriggerExpectPrimCrossing(regionHandle, agentID, position, isPhysical)) | ||
575 | { | ||
576 | return true; | ||
577 | } | ||
578 | |||
579 | regInfo = RequestNeighbourInfo(regionHandle); | ||
580 | if (regInfo != null) | ||
581 | { | ||
582 | bool retValue = false; | ||
583 | OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( | ||
584 | typeof(OGS1InterRegionRemoting), | ||
585 | "tcp://" + regInfo.RemotingAddress + | ||
586 | ":" + regInfo.RemotingPort + | ||
587 | "/InterRegions"); | ||
588 | |||
589 | if (remObject != null) | ||
590 | { | ||
591 | retValue = | ||
592 | remObject.ExpectAvatarCrossing(regionHandle, agentID.Guid, new sLLVector3(position), | ||
593 | isPhysical); | ||
594 | } | ||
595 | else | ||
596 | { | ||
597 | m_log.Warn("[HGrid]: Remoting object not found"); | ||
598 | } | ||
599 | remObject = null; | ||
600 | |||
601 | return retValue; | ||
602 | } | ||
603 | //TODO need to see if we know about where this region is and use .net remoting | ||
604 | // to inform it. | ||
605 | NoteDeadRegion(regionHandle); | ||
606 | return false; | ||
607 | } | ||
608 | catch (RemotingException e) | ||
609 | { | ||
610 | NoteDeadRegion(regionHandle); | ||
611 | m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); | ||
612 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
613 | return false; | ||
614 | } | ||
615 | catch (SocketException e) | ||
616 | { | ||
617 | NoteDeadRegion(regionHandle); | ||
618 | m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); | ||
619 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
620 | return false; | ||
621 | } | ||
622 | catch (InvalidCredentialException e) | ||
623 | { | ||
624 | NoteDeadRegion(regionHandle); | ||
625 | m_log.Warn("[HGrid]: Invalid Credential Exception: Invalid Credentials : " + regionHandle); | ||
626 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
627 | return false; | ||
628 | } | ||
629 | catch (AuthenticationException e) | ||
630 | { | ||
631 | NoteDeadRegion(regionHandle); | ||
632 | m_log.Warn("[HGrid]: Authentication exception: Unable to connect to adjacent region: " + regionHandle); | ||
633 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
634 | return false; | ||
635 | } | ||
636 | catch (Exception e) | ||
637 | { | ||
638 | NoteDeadRegion(regionHandle); | ||
639 | m_log.Warn("[HGrid]: Unknown exception: Unable to connect to adjacent region: " + regionHandle); | ||
640 | m_log.DebugFormat("[HGrid]: {0}", e); | ||
641 | return false; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | public override bool TellRegionToCloseChildConnection(ulong regionHandle, UUID agentID) | ||
646 | { | ||
647 | RegionInfo regInfo = null; | ||
648 | try | ||
649 | { | ||
650 | if (m_localBackend.TriggerTellRegionToCloseChildConnection(regionHandle, agentID)) | ||
651 | { | ||
652 | return true; | ||
653 | } | ||
654 | |||
655 | regInfo = RequestNeighbourInfo(regionHandle); | ||
656 | if (regInfo != null) | ||
657 | { | ||
658 | // bool retValue = false; | ||
659 | OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( | ||
660 | typeof(OGS1InterRegionRemoting), | ||
661 | "tcp://" + regInfo.RemotingAddress + | ||
662 | ":" + regInfo.RemotingPort + | ||
663 | "/InterRegions"); | ||
664 | |||
665 | if (remObject != null) | ||
666 | { | ||
667 | // retValue = | ||
668 | remObject.TellRegionToCloseChildConnection(regionHandle, agentID.Guid); | ||
669 | } | ||
670 | else | ||
671 | { | ||
672 | m_log.Warn("[HGrid]: Remoting object not found"); | ||
673 | } | ||
674 | remObject = null; | ||
675 | |||
676 | return true; | ||
677 | } | ||
678 | //TODO need to see if we know about where this region is and use .net remoting | ||
679 | // to inform it. | ||
680 | NoteDeadRegion(regionHandle); | ||
681 | return false; | ||
682 | } | ||
683 | catch (RemotingException) | ||
684 | { | ||
685 | NoteDeadRegion(regionHandle); | ||
686 | m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region to tell it to close child agents: " + regInfo.RegionName + | ||
687 | " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); | ||
688 | //m_log.Debug(e.ToString()); | ||
689 | return false; | ||
690 | } | ||
691 | catch (SocketException e) | ||
692 | { | ||
693 | NoteDeadRegion(regionHandle); | ||
694 | m_log.Warn("[HGridS]: Socket Error: Unable to connect to adjacent region using tcp://" + | ||
695 | regInfo.RemotingAddress + | ||
696 | ":" + regInfo.RemotingPort + | ||
697 | "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + | ||
698 | " - Is this neighbor up?"); | ||
699 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
700 | return false; | ||
701 | } | ||
702 | catch (InvalidCredentialException e) | ||
703 | { | ||
704 | NoteDeadRegion(regionHandle); | ||
705 | m_log.Warn("[HGrid]: Invalid Credentials: Unable to connect to adjacent region using tcp://" + | ||
706 | regInfo.RemotingAddress + | ||
707 | ":" + regInfo.RemotingPort + | ||
708 | "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); | ||
709 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
710 | return false; | ||
711 | } | ||
712 | catch (AuthenticationException e) | ||
713 | { | ||
714 | NoteDeadRegion(regionHandle); | ||
715 | m_log.Warn("[HGrid]: Authentication exception: Unable to connect to adjacent region using tcp://" + | ||
716 | regInfo.RemotingAddress + | ||
717 | ":" + regInfo.RemotingPort + | ||
718 | "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); | ||
719 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
720 | return false; | ||
721 | } | ||
722 | catch (WebException e) | ||
723 | { | ||
724 | NoteDeadRegion(regionHandle); | ||
725 | m_log.Warn("[HGrid]: WebException exception: Unable to connect to adjacent region using tcp://" + | ||
726 | regInfo.RemotingAddress + | ||
727 | ":" + regInfo.RemotingPort + | ||
728 | "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); | ||
729 | m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); | ||
730 | return false; | ||
731 | } | ||
732 | catch (Exception e) | ||
733 | { | ||
734 | NoteDeadRegion(regionHandle); | ||
735 | // This line errors with a Null Reference Exception.. Why? @.@ | ||
736 | //m_log.Warn("Unknown exception: Unable to connect to adjacent region using tcp://" + regInfo.RemotingAddress + | ||
737 | // ":" + regInfo.RemotingPort + | ||
738 | //"/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + " - This is likely caused by an incompatibility in the protocol between this sim and that one"); | ||
739 | m_log.DebugFormat("[HGrid]: {0}", e); | ||
740 | return false; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | public override bool AcknowledgeAgentCrossed(ulong regionHandle, UUID agentId) | ||
745 | { | ||
746 | return m_localBackend.AcknowledgeAgentCrossed(regionHandle, agentId); | ||
747 | } | ||
748 | |||
749 | public override bool AcknowledgePrimCrossed(ulong regionHandle, UUID primId) | ||
750 | { | ||
751 | return m_localBackend.AcknowledgePrimCrossed(regionHandle, primId); | ||
752 | } | ||
753 | |||
754 | #endregion | ||
755 | |||
756 | #region Methods triggered by calls from external instances | ||
757 | |||
758 | /// <summary> | ||
759 | /// | ||
760 | /// </summary> | ||
761 | /// <param name="regionHandle"></param> | ||
762 | /// <param name="agentData"></param> | ||
763 | /// <returns></returns> | ||
764 | public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData) | ||
765 | { | ||
766 | HGIncomingChildAgent(regionHandle, agentData); | ||
767 | |||
768 | m_log.Info("[HGrid]: " + gdebugRegionName + ": Incoming HGrid Agent " + agentData.firstname + " " + agentData.lastname); | ||
769 | |||
770 | return m_localBackend.IncomingChildAgent(regionHandle, agentData); | ||
771 | } | ||
772 | |||
773 | public bool TriggerRegionUp(RegionUpData regionData, ulong regionhandle) | ||
774 | { | ||
775 | m_log.Info( | ||
776 | "[HGrid]: " + | ||
777 | m_localBackend._gdebugRegionName + "Incoming HGrid RegionUpReport: " + "(" + regionData.X + | ||
778 | "," + regionData.Y + "). Giving this region a fresh set of 'dead' tries"); | ||
779 | |||
780 | RegionInfo nRegionInfo = new RegionInfo(); | ||
781 | nRegionInfo.SetEndPoint("127.0.0.1", regionData.PORT); | ||
782 | nRegionInfo.ExternalHostName = regionData.IPADDR; | ||
783 | nRegionInfo.RegionLocX = regionData.X; | ||
784 | nRegionInfo.RegionLocY = regionData.Y; | ||
785 | |||
786 | lock (m_deadRegionCache) | ||
787 | { | ||
788 | if (m_deadRegionCache.ContainsKey(nRegionInfo.RegionHandle)) | ||
789 | { | ||
790 | m_deadRegionCache.Remove(nRegionInfo.RegionHandle); | ||
791 | } | ||
792 | } | ||
793 | |||
794 | return m_localBackend.TriggerRegionUp(nRegionInfo, regionhandle); | ||
795 | } | ||
796 | |||
797 | public bool TriggerChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) | ||
798 | { | ||
799 | //m_log.Info("[INTER]: Incoming HGrid Child Agent Data Update"); | ||
800 | |||
801 | return m_localBackend.TriggerChildAgentUpdate(regionHandle, cAgentData); | ||
802 | } | ||
803 | |||
804 | /// <summary> | ||
805 | /// | ||
806 | /// </summary> | ||
807 | /// <param name="regionHandle"></param> | ||
808 | /// <param name="agentData"></param> | ||
809 | /// <returns></returns> | ||
810 | public bool IncomingPrim(ulong regionHandle, UUID primID, string objData, int XMLMethod) | ||
811 | { | ||
812 | m_localBackend.TriggerExpectPrim(regionHandle, primID, objData, XMLMethod); | ||
813 | |||
814 | return true; | ||
815 | } | ||
816 | |||
817 | /// <summary> | ||
818 | /// | ||
819 | /// </summary> | ||
820 | /// <param name="regionHandle"></param> | ||
821 | /// <param name="agentID"></param> | ||
822 | /// <param name="position"></param> | ||
823 | /// <returns></returns> | ||
824 | public bool TriggerExpectAvatarCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isFlying) | ||
825 | { | ||
826 | return m_localBackend.TriggerExpectAvatarCrossing(regionHandle, agentID, position, isFlying); | ||
827 | } | ||
828 | |||
829 | public bool TriggerExpectPrimCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isPhysical) | ||
830 | { | ||
831 | return m_localBackend.TriggerExpectPrimCrossing(regionHandle, agentID, position, isPhysical); | ||
832 | } | ||
833 | |||
834 | public bool TriggerTellRegionToCloseChildConnection(ulong regionHandle, UUID agentID) | ||
835 | { | ||
836 | return m_localBackend.TriggerTellRegionToCloseChildConnection(regionHandle, agentID); | ||
837 | } | ||
838 | |||
839 | int timeOut = 10; //10 seconds | ||
840 | /// <summary> | ||
841 | /// Check that a region is available for TCP comms. This is necessary for .NET remoting between regions. | ||
842 | /// </summary> | ||
843 | /// <param name="address"></param> | ||
844 | /// <param name="port"></param> | ||
845 | /// <param name="retry"></param> | ||
846 | /// <returns></returns> | ||
847 | public bool CheckRegion(string address, uint port, bool retry) | ||
848 | { | ||
849 | bool available = false; | ||
850 | bool timed_out = true; | ||
851 | |||
852 | IPAddress ia; | ||
853 | IPAddress.TryParse(address, out ia); | ||
854 | IPEndPoint m_EndPoint = new IPEndPoint(ia, (int)port); | ||
855 | |||
856 | AsyncCallback callback = delegate(IAsyncResult iar) | ||
857 | { | ||
858 | Socket s = (Socket)iar.AsyncState; | ||
859 | try | ||
860 | { | ||
861 | s.EndConnect(iar); | ||
862 | available = true; | ||
863 | timed_out = false; | ||
864 | } | ||
865 | catch (Exception e) | ||
866 | { | ||
867 | m_log.DebugFormat( | ||
868 | "[HGrid]: Callback EndConnect exception: {0}:{1}", e.Message, e.StackTrace); | ||
869 | } | ||
870 | |||
871 | s.Close(); | ||
872 | }; | ||
873 | |||
874 | try | ||
875 | { | ||
876 | Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); | ||
877 | IAsyncResult ar = socket.BeginConnect(m_EndPoint, callback, socket); | ||
878 | ar.AsyncWaitHandle.WaitOne(timeOut * 1000, false); | ||
879 | } | ||
880 | catch (Exception e) | ||
881 | { | ||
882 | m_log.DebugFormat( | ||
883 | "[HGrid]: CheckRegion Socket Setup exception: {0}:{1}", e.Message, e.StackTrace); | ||
884 | |||
885 | return false; | ||
886 | } | ||
887 | |||
888 | if (timed_out) | ||
889 | { | ||
890 | m_log.DebugFormat( | ||
891 | "[HGrid]: socket [{0}] timed out ({1}) waiting to obtain a connection.", | ||
892 | m_EndPoint, timeOut * 1000); | ||
893 | |||
894 | if (retry) | ||
895 | { | ||
896 | return CheckRegion(address, port, false); | ||
897 | } | ||
898 | } | ||
899 | |||
900 | return available; | ||
901 | } | ||
902 | |||
903 | public override bool CheckRegion(string address, uint port) | ||
904 | { | ||
905 | return CheckRegion(address, port, true); | ||
906 | } | ||
907 | |||
908 | public void NoteDeadRegion(ulong regionhandle) | ||
909 | { | ||
910 | lock (m_deadRegionCache) | ||
911 | { | ||
912 | if (m_deadRegionCache.ContainsKey(regionhandle)) | ||
913 | { | ||
914 | m_deadRegionCache[regionhandle] = m_deadRegionCache[regionhandle] + 1; | ||
915 | } | ||
916 | else | ||
917 | { | ||
918 | m_deadRegionCache.Add(regionhandle, 1); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | } | ||
923 | |||
924 | #endregion | ||
925 | |||
926 | |||
927 | } | ||
928 | } | ||