aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs1094
-rw-r--r--ThirdParty/3Di/LoadBalancer/Resources/LoadBalancer.addin.xml12
-rw-r--r--ThirdParty/3Di/LoadBalancer/TcpClient.cs225
-rw-r--r--ThirdParty/3Di/LoadBalancer/TcpServer.cs219
-rw-r--r--ThirdParty/3Di/README.txt82
-rw-r--r--ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MonitorGUI/View.pm214
-rw-r--r--ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MyCGI.pm91
-rw-r--r--ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/XML/RPC.pm100
-rw-r--r--ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/monitor.cgi202
-rw-r--r--ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/readme.txt21
-rw-r--r--ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs554
-rw-r--r--ThirdParty/3Di/RegionProxy/Resources/RegionProxy.addin.xml11
12 files changed, 0 insertions, 2825 deletions
diff --git a/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs b/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs
deleted file mode 100644
index b3b66da..0000000
--- a/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs
+++ /dev/null
@@ -1,1094 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34using System.Threading;
35using OpenMetaverse;
36using OpenMetaverse.Packets;
37using log4net;
38using Mono.Addins;
39using Nwc.XmlRpc;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Region.ClientStack;
43using OpenSim.Region.ClientStack.LindenUDP;
44using OpenSim.Region.Environment.Scenes;
45
46// TODO: remove LindenUDP dependency
47
48namespace OpenSim.ApplicationPlugins.LoadBalancer
49{
50 public class LoadBalancerPlugin : IApplicationPlugin
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private BaseHttpServer commandServer;
55 private bool[] isLocalNeighbour;
56 private bool isSplit;
57 private TcpServer mTcpServer;
58 private readonly object padlock = new object();
59
60 private int proxyOffset;
61 private string proxyURL;
62 private List<RegionInfo> regionData;
63 private int[] regionPortList;
64 private SceneManager sceneManager;
65 private string[] sceneURL;
66 private string serializeDir;
67 private OpenSimBase simMain;
68 private TcpClient[] tcpClientList;
69 private List<IClientNetworkServer> m_clientServers;
70
71 #region IApplicationPlugin Members
72 // TODO: required by IPlugin, but likely not at all right
73 string m_name = "LoadBalancer";
74 string m_version = "0.1";
75
76 public string Version { get { return m_version; } }
77 public string Name { get { return m_name; } }
78
79 public void Initialise()
80 {
81 m_log.Info("[BALANCER]: " + Name + " cannot be default-initialized!");
82 throw new PluginNotInitialisedException (Name);
83 }
84
85 public void Initialise(OpenSimBase openSim)
86 {
87 m_log.Info("[BALANCER]: " + "Entering Initialize()");
88
89 proxyURL = openSim.ConfigSource.Source.Configs["Network"].GetString("proxy_url", "");
90 if (proxyURL.Length == 0) return;
91
92 StartTcpServer();
93
94 LLClientView.SynchronizeClient = SynchronizePackets;
95 AsynchronousSocketListener.PacketHandler = SynchronizePacketRecieve;
96
97 sceneManager = openSim.SceneManager;
98 m_clientServers = openSim.ClientServers;
99 regionData = openSim.RegionData;
100 simMain = openSim;
101 commandServer = openSim.HttpServer;
102
103 proxyOffset = Int32.Parse(openSim.ConfigSource.Source.Configs["Network"].GetString("proxy_offset", "0"));
104 serializeDir = openSim.ConfigSource.Source.Configs["Network"].GetString("serialize_dir", "/tmp/");
105
106 commandServer.AddXmlRPCHandler("SerializeRegion", SerializeRegion);
107 commandServer.AddXmlRPCHandler("DeserializeRegion_Move", DeserializeRegion_Move);
108 commandServer.AddXmlRPCHandler("DeserializeRegion_Clone", DeserializeRegion_Clone);
109 commandServer.AddXmlRPCHandler("TerminateRegion", TerminateRegion);
110
111 commandServer.AddXmlRPCHandler("SplitRegion", SplitRegion);
112 commandServer.AddXmlRPCHandler("MergeRegions", MergeRegions);
113 commandServer.AddXmlRPCHandler("UpdatePhysics", UpdatePhysics);
114 commandServer.AddXmlRPCHandler("GetStatus", GetStatus);
115
116 m_log.Info("[BALANCER] " + "Exiting Initialize()");
117 }
118
119 public void Dispose()
120 {
121 }
122
123 #endregion
124
125 private void StartTcpServer()
126 {
127 Thread server_thread = new Thread(new ThreadStart(
128 delegate
129 {
130 mTcpServer = new TcpServer(10001);
131 mTcpServer.start();
132 }));
133 server_thread.Start();
134 }
135
136 private XmlRpcResponse GetStatus(XmlRpcRequest request)
137 {
138 XmlRpcResponse response = new XmlRpcResponse();
139 try
140 {
141 m_log.Info("[BALANCER] " + "Entering RegionStatus()");
142
143 int src_port = Convert.ToInt32(request.Params[0]);
144 Scene scene;
145 // try to get the scene object
146 RegionInfo src_region = SearchRegionFromPortNum(src_port);
147 if (sceneManager.TryGetScene(src_region.RegionID, out scene) == false)
148 {
149 m_log.Error("[BALANCER] " + "The Scene is not found");
150 return response;
151 }
152 // serialization of client's informations
153 List<ScenePresence> presences = scene.GetScenePresences();
154 int get_scene_presence = presences.Count;
155 int get_scene_presence_filter = 0;
156 foreach (ScenePresence pre in presences)
157 {
158 IClientAPI client = pre.ControllingClient;
159 //if (pre.MovementFlag!=0 && client.PacketProcessingEnabled==true)
160 if (client.IsActive)
161 {
162 get_scene_presence_filter++;
163 }
164 }
165 List<ScenePresence> avatars = scene.GetAvatars();
166 int get_avatar = avatars.Count;
167 int get_avatar_filter = 0;
168 string avatar_names = "";
169 foreach (ScenePresence pre in avatars)
170 {
171 IClientAPI client = pre.ControllingClient;
172 //if (pre.MovementFlag!=0 && client.PacketProcessingEnabled==true)
173 if (client.IsActive)
174 {
175 get_avatar_filter++;
176 avatar_names += pre.Firstname + " " + pre.Lastname + "; ";
177 }
178 }
179
180 Hashtable responseData = new Hashtable();
181 responseData["get_scene_presence_filter"] = get_scene_presence_filter;
182 responseData["get_scene_presence"] = get_scene_presence;
183 responseData["get_avatar_filter"] = get_avatar_filter;
184 responseData["get_avatar"] = get_avatar;
185 responseData["avatar_names"] = avatar_names;
186 response.Value = responseData;
187
188 m_log.Info("[BALANCER] " + "Exiting RegionStatus()");
189 }
190 catch (Exception e)
191 {
192 m_log.Error("[BALANCER] " + e);
193 m_log.Error("[BALANCER] " + e.StackTrace);
194 }
195 return response;
196 }
197
198 private XmlRpcResponse SerializeRegion(XmlRpcRequest request)
199 {
200 try
201 {
202 m_log.Info("[BALANCER] " + "Entering SerializeRegion()");
203
204 string src_url = (string) request.Params[0];
205 int src_port = (int) request.Params[1];
206
207 SerializeRegion(src_url, src_port);
208
209 m_log.Info("[BALANCER] " + "Exiting SerializeRegion()");
210 }
211 catch (Exception e)
212 {
213 m_log.Error("[BALANCER] " + e);
214 m_log.Error("[BALANCER] " + e.StackTrace);
215 }
216
217 return new XmlRpcResponse();
218 }
219
220 private XmlRpcResponse DeserializeRegion_Move(XmlRpcRequest request)
221 {
222 try
223 {
224 m_log.Info("[BALANCER] " + "Entering DeserializeRegion_Move()");
225
226 string src_url = (string) request.Params[0];
227 int src_port = (int) request.Params[1];
228 string dst_url = (string) request.Params[2];
229 int dst_port = (int) request.Params[3];
230
231 DeserializeRegion_Move(src_port, dst_port, src_url, dst_url);
232
233 m_log.Info("[BALANCER] " + "Exiting DeserializeRegion_Move()");
234 }
235 catch (Exception e)
236 {
237 m_log.Error("[BALANCER] " + e);
238 m_log.Error("[BALANCER] " + e.StackTrace);
239 }
240
241 return new XmlRpcResponse();
242 }
243
244 private XmlRpcResponse DeserializeRegion_Clone(XmlRpcRequest request)
245 {
246 try
247 {
248 m_log.Info("[BALANCER] " + "Entering DeserializeRegion_Clone()");
249
250 string src_url = (string) request.Params[0];
251 int src_port = (int) request.Params[1];
252 string dst_url = (string) request.Params[2];
253 int dst_port = (int) request.Params[3];
254
255 DeserializeRegion_Clone(src_port, dst_port, src_url, dst_url);
256
257 m_log.Info("[BALANCER] " + "Exiting DeserializeRegion_Clone()");
258 }
259 catch (Exception e)
260 {
261 m_log.Error("[BALANCER] " + e);
262 m_log.Error("[BALANCER] " + e.StackTrace);
263 throw;
264 }
265
266 return new XmlRpcResponse();
267 }
268
269 private XmlRpcResponse TerminateRegion(XmlRpcRequest request)
270 {
271 try
272 {
273 m_log.Info("[BALANCER] " + "Entering TerminateRegion()");
274
275 int src_port = (int) request.Params[0];
276
277 // backgroud
278 WaitCallback callback = TerminateRegion;
279 ThreadPool.QueueUserWorkItem(callback, src_port);
280
281 m_log.Info("[BALANCER] " + "Exiting TerminateRegion()");
282 }
283 catch (Exception e)
284 {
285 m_log.Error("[BALANCER] " + e);
286 m_log.Error("[BALANCER] " + e.StackTrace);
287 }
288
289 return new XmlRpcResponse();
290 }
291
292 // internal functions
293
294 private void SerializeRegion(string src_url, int src_port)
295 {
296 //------------------------------------------
297 // Processing of origin region
298 //------------------------------------------
299
300 // search origin region
301 RegionInfo src_region = SearchRegionFromPortNum(src_port);
302
303 if (src_region == null)
304 {
305 m_log.Error("[BALANCER] " + "Region not found");
306 return;
307 }
308
309 Util.XmlRpcCommand(src_region.proxyUrl, "BlockClientMessages", src_url, src_port + proxyOffset);
310
311 // serialization of origin region's data
312 SerializeRegion(src_region, serializeDir);
313 }
314
315 private void DeserializeRegion_Move(int src_port, int dst_port, string src_url, string dst_url)
316 {
317 //------------------------------------------
318 // Processing of destination region
319 //------------------------------------------
320
321 // import the source region's data
322 RegionInfo dst_region = DeserializeRegion(dst_port, serializeDir);
323
324 Util.XmlRpcCommand(dst_region.proxyUrl, "ChangeRegion", src_port + proxyOffset, src_url, dst_port + proxyOffset, dst_url);
325 Util.XmlRpcCommand(dst_region.proxyUrl, "UnblockClientMessages", dst_url, dst_port + proxyOffset);
326 }
327
328 private void DeserializeRegion_Clone(int src_port, int dst_port, string src_url, string dst_url)
329 {
330 //------------------------------------------
331 // Processing of destination region
332 //------------------------------------------
333
334 // import the source region's data
335 RegionInfo dst_region = DeserializeRegion(dst_port, serializeDir);
336
337 // Decide who is in charge for each section
338 int[] port = new int[] {src_port, dst_port};
339 string[] url = new string[] {"http://" + src_url + ":" + commandServer.Port, "http://" + dst_url + ":" + commandServer.Port};
340 for (int i = 0; i < 2; i++) Util.XmlRpcCommand(url[i], "SplitRegion", i, 2, port[0], port[1], url[0], url[1]);
341
342 // Enable the proxy
343 Util.XmlRpcCommand(dst_region.proxyUrl, "AddRegion", src_port + proxyOffset, src_url, dst_port + proxyOffset, dst_url);
344 Util.XmlRpcCommand(dst_region.proxyUrl, "UnblockClientMessages", dst_url, dst_port + proxyOffset);
345 }
346
347 private void TerminateRegion(object param)
348 {
349 int src_port = (int) param;
350
351 //------------------------------------------
352 // Processing of remove region
353 //------------------------------------------
354
355 // search origin region
356 RegionInfo src_region = SearchRegionFromPortNum(src_port);
357
358 if (src_region == null)
359 {
360 m_log.Error("[BALANCER] " + "Region not found");
361 return;
362 }
363
364 isSplit = false;
365
366 // remove client resources
367 RemoveAllClientResource(src_region);
368 // remove old region
369 RemoveRegion(src_region.RegionID, src_region.InternalEndPoint.Port);
370
371 m_log.Info("[BALANCER] " + "Region terminated");
372 }
373
374 private RegionInfo SearchRegionFromPortNum(int portnum)
375 {
376 RegionInfo result = null;
377
378 foreach (RegionInfo rinfo in regionData)
379 {
380 if (rinfo.InternalEndPoint.Port == portnum)
381 {
382// m_log.Info("BALANCER",
383// "Region found. Internal Port = {0}, Handle={1}",
384// rinfo.InternalEndPoint.Port, rinfo.RegionHandle);
385 result = rinfo;
386 break;
387 }
388 }
389
390 return result;
391 }
392
393 private IClientNetworkServer SearchClientServerFromPortNum(int portnum)
394 {
395 return m_clientServers.Find(
396 delegate(IClientNetworkServer server)
397 {
398// ReSharper disable PossibleNullReferenceException
399 return (portnum + proxyOffset == ((IPEndPoint) server.Server.LocalEndPoint).Port);
400// ReSharper restore PossibleNullReferenceException
401 }
402 );
403 }
404
405 private void SerializeRegion(RegionInfo src_region, string export_dir)
406 {
407 Scene scene;
408 int i = 0;
409
410 // try to get the scene object
411 if (sceneManager.TryGetScene(src_region.RegionID, out scene) == false)
412 {
413 m_log.Error("[BALANCER] " + "The Scene is not found");
414 return;
415 }
416
417 // create export directory
418 DirectoryInfo dirinfo = new DirectoryInfo(export_dir);
419 if (!dirinfo.Exists)
420 {
421 dirinfo.Create();
422 }
423
424 // serialization of client's informations
425 List<ScenePresence> presences = scene.GetScenePresences();
426
427 foreach (ScenePresence pre in presences)
428 {
429 SerializeClient(i, scene, pre, export_dir);
430 i++;
431 }
432
433 // serialization of region data
434 SerializableRegionInfo dst_region = new SerializableRegionInfo(src_region);
435
436 string filename = export_dir + "RegionInfo_" + src_region.RegionID + ".bin";
437 Util.SerializeToFile(filename, dst_region);
438
439 // backup current scene's entities
440 //scene.Backup();
441
442 m_log.InfoFormat("[BALANCER] " + "region serialization completed [{0}]",
443 src_region.RegionID.ToString());
444 }
445
446 private static void SerializeClient(int idx, IScene scene, EntityBase pre, string export_dir)
447 {
448 string filename;
449 IClientAPI controller;
450
451 m_log.InfoFormat("[BALANCER] " + "agent id : {0}", pre.UUID);
452
453 uint[] circuits = scene.ClientManager.GetAllCircuits(pre.UUID);
454
455 foreach (uint code in circuits)
456 {
457 m_log.InfoFormat("[BALANCER] " + "circuit code : {0}", code);
458
459 if (scene.ClientManager.TryGetClient(code, out controller))
460 {
461 ClientInfo info = controller.GetClientInfo();
462
463 filename = export_dir + "ClientInfo-" + String.Format("{0:0000}", idx) + "_" + controller.CircuitCode + ".bin";
464
465 Util.SerializeToFile(filename, info);
466
467 m_log.InfoFormat("[BALANCER] " + "client info serialized [filename={0}]", filename);
468 }
469 }
470
471 //filename = export_dir + "Presence_" + controller.AgentId.ToString() + ".bin";
472 filename = export_dir + "Presence_" + String.Format("{0:0000}", idx) + ".bin";
473
474 Util.SerializeToFile(filename, pre);
475
476 m_log.InfoFormat("[BALANCER] " + "scene presence serialized [filename={0}]", filename);
477 }
478
479 private RegionInfo DeserializeRegion(int dst_port, string import_dir)
480 {
481 RegionInfo dst_region = null;
482
483 try
484 {
485 // deserialization of region data
486 string[] files = Directory.GetFiles(import_dir, "RegionInfo_*.bin");
487
488 foreach (string filename in files)
489 {
490 m_log.InfoFormat("[BALANCER] RegionInfo filename = [{0}]", filename);
491
492 dst_region = new RegionInfo((SerializableRegionInfo) Util.DeserializeFromFile(filename));
493
494 m_log.InfoFormat("[BALANCER] " + "RegionID = [{0}]", dst_region.RegionID.ToString());
495 m_log.InfoFormat("[BALANCER] " + "RegionHandle = [{0}]", dst_region.RegionHandle);
496 m_log.InfoFormat("[BALANCER] " + "ProxyUrl = [{0}]", dst_region.proxyUrl);
497 m_log.InfoFormat("[BALANCER] " + "OriginRegionID = [{0}]", dst_region.originRegionID.ToString());
498
499 CreateCloneRegion(dst_region, dst_port, true);
500
501 File.Delete(filename);
502
503 m_log.InfoFormat("[BALANCER] " + "region deserialized [{0}]", dst_region.RegionID);
504 }
505
506 if (dst_region != null)
507 {
508 // deserialization of client data
509 DeserializeClient(dst_region, import_dir);
510
511 m_log.InfoFormat("[BALANCER] " + "region deserialization completed [{0}]",
512 dst_region.ToString());
513 }
514 }
515 catch (Exception e)
516 {
517 m_log.Error("[BALANCER] " + e);
518 m_log.Error("[BALANCER] " + e.StackTrace);
519 throw;
520 }
521
522 return dst_region;
523 }
524
525 private void DeserializeClient(SimpleRegionInfo dst_region, string import_dir)
526 {
527 ScenePresence sp;
528 ClientInfo data;
529 Scene scene;
530 IClientAPI controller;
531
532 if (sceneManager.TryGetScene(dst_region.RegionID, out scene))
533 {
534 IClientNetworkServer clientserv = SearchClientServerFromPortNum(scene.RegionInfo.InternalEndPoint.Port);
535
536 // restore the scene presence
537 for (int i = 0;; i++)
538 {
539 string filename = import_dir + "Presence_" + String.Format("{0:0000}", i) + ".bin";
540
541 if (!File.Exists(filename))
542 {
543 break;
544 }
545
546 sp = (ScenePresence) Util.DeserializeFromFile(filename);
547 Console.WriteLine("agent id = {0}", sp.UUID);
548
549 scene.m_restorePresences.Add(sp.UUID, sp);
550 File.Delete(filename);
551
552 m_log.InfoFormat("[BALANCER] " + "scene presence deserialized [{0}]", sp.UUID);
553
554 // restore the ClientView
555
556 string[] files = Directory.GetFiles(import_dir, "ClientInfo-" + String.Format("{0:0000}", i) + "_*.bin");
557
558 foreach (string fname in files)
559 {
560 int start = fname.IndexOf('_');
561 int end = fname.LastIndexOf('.');
562 uint circuit_code = uint.Parse(fname.Substring(start + 1, end - start - 1));
563 m_log.InfoFormat("[BALANCER] " + "client circuit code = {0}", circuit_code);
564
565 data = (ClientInfo) Util.DeserializeFromFile(fname);
566
567 AgentCircuitData agentdata = new AgentCircuitData(data.agentcircuit);
568 scene.AuthenticateHandler.AddNewCircuit(circuit_code, agentdata);
569
570 // TODO: This needs to be abstracted and converted into IClientNetworkServer
571 if (clientserv is LLUDPServer)
572 {
573 ((LLUDPServer) clientserv).RestoreClient(agentdata, data.userEP, data.proxyEP);
574 }
575
576 // waiting for the scene-presense restored
577 lock (scene.m_restorePresences)
578 {
579 Monitor.Wait(scene.m_restorePresences, 3000);
580 }
581
582 if (scene.ClientManager.TryGetClient(circuit_code, out controller))
583 {
584 m_log.InfoFormat("[BALANCER] " + "get client [{0}]", circuit_code);
585 controller.SetClientInfo(data);
586 }
587
588 File.Delete(fname);
589
590 m_log.InfoFormat("[BALANCER] " + "client info deserialized [{0}]", circuit_code);
591 }
592
593 // backup new scene's entities
594 //scene.Backup();
595 }
596 }
597 }
598
599 private void CreateCloneRegion(RegionInfo dst_region, int dst_port, bool createID_flag)
600 {
601 if (createID_flag)
602 {
603 dst_region.RegionID = UUID.Random();
604 }
605
606 // change RegionInfo (memory only)
607 dst_region.InternalEndPoint.Port = dst_port;
608 dst_region.ExternalHostName = proxyURL.Split(new char[] {'/', ':'})[3];
609
610 // Create new region
611 simMain.CreateRegion(dst_region, false);
612 }
613
614 private void RemoveRegion(UUID regionID, int port)
615 {
616 Scene killScene;
617 if (sceneManager.TryGetScene(regionID, out killScene))
618 {
619 Console.WriteLine("scene found.");
620
621 if ((sceneManager.CurrentScene != null)
622 && (sceneManager.CurrentScene.RegionInfo.RegionID == killScene.RegionInfo.RegionID))
623 {
624 sceneManager.TrySetCurrentScene("..");
625 }
626
627 m_log.Info("Removing region : " + killScene.RegionInfo.RegionName);
628 regionData.Remove(killScene.RegionInfo);
629 sceneManager.CloseScene(killScene);
630 }
631
632 // Shutting down the UDP server
633 IClientNetworkServer clientsvr = SearchClientServerFromPortNum(port);
634
635 if (clientsvr != null)
636 {
637 clientsvr.Server.Close();
638 m_clientServers.Remove(clientsvr);
639 }
640 }
641
642 private void RemoveAllClientResource(SimpleRegionInfo src_region)
643 {
644 Scene scene;
645 IClientAPI controller;
646
647 // try to get the scene object
648 if (sceneManager.TryGetScene(src_region.RegionID, out scene) == false)
649 {
650 m_log.Error("[BALANCER] " + "The Scene is not found");
651 return;
652 }
653
654 // serialization of client's informations
655 List<ScenePresence> presences = scene.GetScenePresences();
656
657 // remove all scene presences
658 foreach (ScenePresence pre in presences)
659 {
660 uint[] circuits = scene.ClientManager.GetAllCircuits(pre.UUID);
661
662 foreach (uint code in circuits)
663 {
664 m_log.InfoFormat("[BALANCER] " + "circuit code : {0}", code);
665
666 if (scene.ClientManager.TryGetClient(code, out controller))
667 {
668 // stopping clientview thread
669 if ((controller).IsActive)
670 {
671 controller.Stop();
672 (controller).IsActive = false;
673 }
674 // teminateing clientview thread
675 controller.Terminate();
676 m_log.Info("[BALANCER] " + "client thread stopped");
677 }
678 }
679
680 // remove scene presence
681 scene.RemoveClient(pre.UUID);
682 }
683 }
684
685 /*
686 * This section implements scene splitting and synchronization
687 */
688
689 private XmlRpcResponse SplitRegion(XmlRpcRequest request)
690 {
691 try
692 {
693 int myID = (int) request.Params[0];
694 int numRegions = (int) request.Params[1];
695 regionPortList = new int[numRegions];
696 sceneURL = new string[numRegions];
697 tcpClientList = new TcpClient[numRegions];
698
699 for (int i = 0; i < numRegions; i++)
700 {
701 regionPortList[i] = (int) request.Params[i + 2];
702 sceneURL[i] = (string) request.Params[i + 2 + numRegions];
703 }
704
705 for (int i = 0; i < numRegions; i++)
706 {
707 string hostname = sceneURL[i].Split(new char[] {'/', ':'})[3];
708 m_log.InfoFormat("[SPLITSCENE] " + "creating tcp client host:{0}", hostname);
709 tcpClientList[i] = new TcpClient(hostname, 10001);
710 }
711
712 bool isMaster = (myID == 0);
713
714 isLocalNeighbour = new bool[numRegions];
715 for (int i = 0; i < numRegions; i++) isLocalNeighbour[i] = (sceneURL[i] == sceneURL[myID]);
716
717 RegionInfo region = SearchRegionFromPortNum(regionPortList[myID]);
718
719 //Console.WriteLine("\n === SplitRegion {0}\n", region.RegionID);
720
721 Scene scene;
722 if (sceneManager.TryGetScene(region.RegionID, out scene))
723 {
724 // Disable event updates, backups etc in the slave(s)
725 scene.Region_Status = isMaster ? RegionStatus.Up : RegionStatus.SlaveScene;
726
727 //Console.WriteLine("=== SplitRegion {0}: Scene found, status {1}", region.RegionID, scene.Region_Status);
728
729 // Disabling half of the avatars in master, and the other half in slave
730
731 int i = 0;
732
733 List<uint> circuits = scene.ClientManager.GetAllCircuitCodes();
734 circuits.Sort();
735
736 foreach (uint code in circuits)
737 {
738 m_log.InfoFormat("[BALANCER] " + "circuit code : {0}", code);
739
740 IClientAPI controller;
741 if (scene.ClientManager.TryGetClient(code, out controller))
742 {
743 // Divide the presences evenly over the set of subscenes
744 LLClientView client = (LLClientView) controller;
745 client.IsActive = (((i + myID) % sceneURL.Length) == 0);
746
747 m_log.InfoFormat("[SPLITSCENE] === SplitRegion {0}: SP.PacketEnabled {1}", region.RegionID, client.IsActive);
748
749 if (!client.IsActive)
750 {
751 // stopping clientview thread
752 client.Stop();
753 }
754
755 ++i;
756 }
757 }
758
759 scene.splitID = myID;
760 scene.SynchronizeScene = SynchronizeScenes;
761 isSplit = true;
762 }
763 else
764 {
765 m_log.Error("[SPLITSCENE] " + String.Format("Scene not found {0}", region.RegionID));
766 }
767 }
768 catch (Exception e)
769 {
770 m_log.Error("[SPLITSCENE] " + e);
771 m_log.Error("[SPLITSCENE] " + e.StackTrace);
772 }
773
774 return new XmlRpcResponse();
775 }
776
777 private XmlRpcResponse MergeRegions(XmlRpcRequest request)
778 {
779 // This should only be called for the master scene
780 try
781 {
782 m_log.Info("[BALANCER] " + "Entering MergeRegions()");
783
784 string src_url = (string) request.Params[0];
785 int src_port = (int) request.Params[1];
786
787 RegionInfo region = SearchRegionFromPortNum(src_port);
788
789 Util.XmlRpcCommand(region.proxyUrl, "BlockClientMessages", src_url, src_port + proxyOffset);
790
791 Scene scene;
792 if (sceneManager.TryGetScene(region.RegionID, out scene))
793 {
794 isSplit = false;
795
796 scene.SynchronizeScene = null;
797 scene.Region_Status = RegionStatus.Up;
798
799 List<ScenePresence> presences = scene.GetScenePresences();
800 foreach (ScenePresence pre in presences)
801 {
802 LLClientView client = (LLClientView) pre.ControllingClient;
803 if (!client.IsActive)
804 {
805 client.Restart();
806 client.IsActive = true;
807 }
808 }
809 }
810
811 // Delete the slave scenes
812 for (int i = 1; i < sceneURL.Length; i++)
813 {
814 string url = (sceneURL[i].Split('/')[2]).Split(':')[0]; // get URL part from EP
815 Util.XmlRpcCommand(region.proxyUrl, "DeleteRegion", regionPortList[i] + proxyOffset, url);
816 Thread.Sleep(1000);
817 Util.XmlRpcCommand(sceneURL[i], "TerminateRegion", regionPortList[i]); // TODO: need + proxyOffset?
818 }
819
820 Util.XmlRpcCommand(region.proxyUrl, "UnblockClientMessages", src_url, src_port + proxyOffset);
821 }
822 catch (Exception e)
823 {
824 m_log.Error("[BALANCER] " + e);
825 m_log.Error("[BALANCER] " + e.StackTrace);
826 throw;
827 }
828
829 return new XmlRpcResponse();
830 }
831
832 private XmlRpcResponse UpdatePhysics(XmlRpcRequest request)
833 {
834 // this callback receives physic scene updates from the other sub-scenes (in split mode)
835
836 int regionPort = (int) request.Params[0];
837 UUID scenePresenceID = new UUID((byte[]) request.Params[1], 0);
838 Vector3 position = new Vector3((byte[]) request.Params[2], 0);
839 Vector3 velocity = new Vector3((byte[]) request.Params[3], 0);
840 bool flying = (bool) request.Params[4];
841
842 LocalUpdatePhysics(regionPort, scenePresenceID, position, velocity, flying);
843
844 return new XmlRpcResponse();
845 }
846
847 private void LocalUpdatePhysics(int regionPort, UUID scenePresenceID, Vector3 position, Vector3 velocity, bool flying)
848 {
849 //m_log.Info("[SPLITSCENE] "+String.Format("UpdatePhysics called {0}", regionID));
850
851 //m_log.Info("[SPLITSCENE] "+"LocalUpdatePhysics [region port:{0}, client:{1}, position:{2}, velocity:{3}, flying:{4}]",
852 // regionPort, scenePresenceID.ToString(), position.ToString(),
853 // velocity.ToString(), flying);
854
855 RegionInfo region = SearchRegionFromPortNum(regionPort);
856
857 // Find and update the scene precense
858 Scene scene;
859 if (sceneManager.TryGetScene(region.RegionID, out scene))
860 {
861 ScenePresence pre = scene.GetScenePresences().Find(delegate(ScenePresence x) { return x.UUID == scenePresenceID; });
862
863 if (pre == null)
864 {
865 m_log.ErrorFormat("[SPLITSCENE] [LocalUpdatePhysics] ScenePresence is missing... ({0})", scenePresenceID.ToString());
866 return;
867 }
868
869// m_log.Info("[SPLITSCENE] "+"LocalUpdatePhysics [region:{0}, client:{1}]",
870// regionID.ToString(), pre.ToString());
871
872 pre.AbsolutePosition = position; // will set PhysicsActor.Position
873 pre.Velocity = velocity; // will set PhysicsActor.Velocity
874 pre.PhysicsActor.Flying = flying;
875 }
876 }
877
878 private void SynchronizeScenes(Scene scene)
879 {
880 if (!isSplit)
881 {
882 return;
883 }
884
885 lock (padlock)
886 {
887 // Callback activated after a physics scene update
888// int i = 0;
889 List<ScenePresence> presences = scene.GetScenePresences();
890 foreach (ScenePresence pre in presences)
891 {
892 LLClientView client = (LLClientView) pre.ControllingClient;
893
894 // Because data changes by the physics simulation when the client doesn't move,
895 // if MovementFlag is false, It is necessary to synchronize.
896 //if (pre.MovementFlag!=0 && client.PacketProcessingEnabled==true)
897 if (client.IsActive)
898 {
899 //m_log.Info("[SPLITSCENE] "+String.Format("Client moving in {0} {1}", scene.RegionInfo.RegionID, pre.AbsolutePosition));
900
901 for (int i = 0; i < sceneURL.Length; i++)
902 {
903 if (i == scene.splitID)
904 {
905 continue;
906 }
907
908 if (isLocalNeighbour[i])
909 {
910 //m_log.Info("[SPLITSCENE] "+"Synchronize ScenePresence (Local) [region:{0}=>{1}, client:{2}]",
911 // scene.RegionInfo.RegionID, regionPortList[i], pre.ToString());
912 LocalUpdatePhysics(regionPortList[i], pre.UUID, pre.AbsolutePosition, pre.Velocity, pre.PhysicsActor.Flying);
913 }
914 else
915 {
916 //m_log.Info("[SPLITSCENE] "+"Synchronize ScenePresence (Remote) [region port:{0}, client:{1}, position:{2}, velocity:{3}, flying:{4}]",
917 // regionPortList[i], pre.ToString(), pre.AbsolutePosition.ToString(),
918 // pre.Velocity.ToString(), pre.PhysicsActor.Flying);
919
920
921 Util.XmlRpcCommand(sceneURL[i], "UpdatePhysics",
922 regionPortList[i], pre.UUID.GetBytes(),
923 pre.AbsolutePosition.GetBytes(), pre.Velocity.GetBytes(),
924 pre.PhysicsActor.Flying);
925
926/*
927 byte[] buff = new byte[12+12+1];
928
929 Buffer.BlockCopy(pre.AbsolutePosition.GetBytes(), 0, buff, 0, 12);
930 Buffer.BlockCopy(pre.Velocity.GetBytes(), 0, buff, 12, 12);
931 buff[24] = (byte)((pre.PhysicsActor.Flying)?1:0);
932
933 // create header
934 InternalPacketHeader header = new InternalPacketHeader();
935
936 header.type = 1;
937 header.throttlePacketType = 0;
938 header.numbytes = buff.Length;
939 header.agent_id = pre.UUID.Guid;
940 header.region_port = regionPortList[i];
941
942 //Send
943 tcpClientList[i].send(header, buff);
944*/
945 }
946 }
947 }
948// ++i;
949 }
950 }
951 }
952
953 public bool SynchronizePackets(IScene scene, Packet packet, UUID agentID, ThrottleOutPacketType throttlePacketType)
954 {
955 if (!isSplit)
956 {
957 return false;
958 }
959
960 Scene localScene = (Scene) scene;
961
962 for (int i = 0; i < sceneURL.Length; i++)
963 {
964 if (i == localScene.splitID)
965 {
966 continue;
967 }
968
969 if (isLocalNeighbour[i])
970 {
971 //m_log.Info("[SPLITSCENE] "+"Synchronize Packet (Local) [type:{0}, client:{1}]",
972 // packet.Type.ToString(), agentID.ToString());
973 LocalUpdatePacket(regionPortList[i], agentID, packet, throttlePacketType);
974 }
975 else
976 {
977 //m_log.Info("[SPLITSCENE] "+"Synchronize Packet (Remote) [type:{0}, client:{1}]",
978 // packet.Type.ToString(), agentID.ToString());
979 // to bytes
980 byte[] buff = packet.ToBytes();
981
982 // create header
983 InternalPacketHeader header = new InternalPacketHeader();
984
985 header.type = 0;
986 header.throttlePacketType = (int) throttlePacketType;
987 header.numbytes = buff.Length;
988 header.agent_id = agentID.Guid;
989 header.region_port = regionPortList[i];
990
991 //Send
992 tcpClientList[i].send(header, buff);
993
994 PacketPool.Instance.ReturnPacket(packet);
995 }
996 }
997
998 return true;
999 }
1000
1001 private void LocalUpdatePacket(int regionPort, UUID agentID, Packet packet, ThrottleOutPacketType throttlePacketType)
1002 {
1003 Scene scene;
1004
1005 RegionInfo region = SearchRegionFromPortNum(regionPort);
1006
1007// m_log.Info("[SPLITSCENE] "+"LocalUpdatePacket [region port:{0}, client:{1}, packet type:{2}]",
1008// regionPort, agentID.ToString(), packet.GetType().ToString());
1009
1010 if (sceneManager.TryGetScene(region.RegionID, out scene))
1011 {
1012 ScenePresence pre = scene.GetScenePresences().Find(delegate(ScenePresence x) { return x.UUID == agentID; });
1013
1014 if (pre == null)
1015 {
1016 m_log.ErrorFormat("[SPLITSCENE] [LocalUpdatePacket] ScenePresence is missing... ({0})", agentID.ToString());
1017 return;
1018 }
1019 if (pre.ControllingClient is LLClientView)
1020 {
1021 if (((LLClientView)pre.ControllingClient).IsActive)
1022 {
1023 ((LLClientView)pre.ControllingClient).OutPacket(packet, throttlePacketType);
1024 }
1025 else
1026 {
1027 PacketPool.Instance.ReturnPacket(packet);
1028 }
1029 }
1030 else
1031 {
1032 PacketPool.Instance.ReturnPacket(packet);
1033 }
1034 }
1035 }
1036
1037 public void SynchronizePacketRecieve(InternalPacketHeader header, byte[] buff)
1038 {
1039// m_log.Info("[SPLITSCENE] "+"entering SynchronizePacketRecieve[type={0}]", header.type);
1040
1041 if (!isSplit)
1042 {
1043 return;
1044 }
1045
1046 switch (header.type)
1047 {
1048 case 0:
1049
1050 byte[] zero = new byte[3000];
1051
1052 // deserialize packet
1053 int packetEnd = buff.Length - 1;
1054// packetEnd = buff.Length;
1055
1056 try
1057 {
1058 //m_log.Info("[SPLITSCENE] "+"PacketPool.Instance : {0}", (PacketPool.Instance == null)?"null":"not null");
1059 //m_log.Info("[SPLITSCENE] "+"buff length={0}", buff.Length);
1060
1061 Packet packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero);
1062
1063 LocalUpdatePacket(header.region_port, new UUID(header.agent_id),
1064 packet, (ThrottleOutPacketType) header.throttlePacketType);
1065 }
1066 catch (Exception e)
1067 {
1068 m_log.Error("[SPLITSCENE] " + e);
1069 m_log.Error("[SPLITSCENE] " + e.StackTrace);
1070 }
1071
1072 break;
1073
1074 case 1:
1075
1076 int regionPort = header.region_port;
1077 UUID scenePresenceID = new UUID(header.agent_id);
1078 Vector3 position = new Vector3(buff, 0);
1079 Vector3 velocity = new Vector3(buff, 12);
1080 bool flying = ((buff[24] == 1) ? true : false);
1081
1082 LocalUpdatePhysics(regionPort, scenePresenceID, position, velocity, flying);
1083
1084 break;
1085
1086 default:
1087 m_log.Info("[SPLITSCENE] " + "Invalid type");
1088 break;
1089 }
1090
1091// m_log.Info("[SPLITSCENE] "+"exiting SynchronizePacketRecieve");
1092 }
1093 }
1094}
diff --git a/ThirdParty/3Di/LoadBalancer/Resources/LoadBalancer.addin.xml b/ThirdParty/3Di/LoadBalancer/Resources/LoadBalancer.addin.xml
deleted file mode 100644
index ac6ac15..0000000
--- a/ThirdParty/3Di/LoadBalancer/Resources/LoadBalancer.addin.xml
+++ /dev/null
@@ -1,12 +0,0 @@
1<Addin id="LoadBalancer" version="0.1">
2 <Runtime>
3 <Import assembly="OpenSim.ApplicationPlugins.LoadBalancer.dll" />
4 </Runtime>
5 <Dependencies>
6 <Addin id="OpenSim" version="0.5" />
7 <Addin id="RegionProxy" version="0.1" />
8 </Dependencies>
9 <Extension path="/OpenSim/Startup">
10 <Plugin id="LoadBalancer" type="OpenSim.ApplicationPlugins.LoadBalancer.LoadBalancerPlugin" />
11 </Extension>
12</Addin>
diff --git a/ThirdParty/3Di/LoadBalancer/TcpClient.cs b/ThirdParty/3Di/LoadBalancer/TcpClient.cs
deleted file mode 100644
index 1acba24..0000000
--- a/ThirdParty/3Di/LoadBalancer/TcpClient.cs
+++ /dev/null
@@ -1,225 +0,0 @@
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
28using System;
29using System.IO;
30using System.Net;
31using System.Net.Sockets;
32using System.Threading;
33
34namespace OpenSim.ApplicationPlugins.LoadBalancer
35{
36 public class AsynchronousClient
37 {
38 private static ManualResetEvent connectDone = new ManualResetEvent(false);
39 private static ManualResetEvent sendDone = new ManualResetEvent(false);
40
41 public static Socket StartClient(string hostname, int port)
42 {
43 try
44 {
45 IPHostEntry ipHostInfo = Dns.GetHostEntry(hostname);
46 IPAddress ipAddress = ipHostInfo.AddressList[0];
47 IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
48
49 Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
50 client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
51 connectDone.WaitOne();
52 /*
53 Send(client,"This is a test<EOF>");
54 sendDone.WaitOne();
55 Receive(client);
56 receiveDone.WaitOne();
57 client.Shutdown(SocketShutdown.Both);
58 client.Close();
59 */
60 return client;
61 }
62 catch (Exception e)
63 {
64 Console.WriteLine(e.ToString());
65 throw new Exception("socket error !!");
66 }
67 }
68
69 private static void ConnectCallback(IAsyncResult ar)
70 {
71 try
72 {
73 Socket client = (Socket) ar.AsyncState;
74 client.EndConnect(ar);
75 Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
76 connectDone.Set();
77 }
78 catch (Exception e)
79 {
80 Console.WriteLine(e.ToString());
81 }
82 }
83
84 public static void Send(Socket client, byte[] byteData)
85 {
86 client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
87 }
88
89 private static void SendCallback(IAsyncResult ar)
90 {
91 try
92 {
93 Socket client = (Socket) ar.AsyncState;
94 int bytesSent = client.EndSend(ar);
95 if (bytesSent > 0)
96 {
97 //Console.WriteLine("Sent {0} bytes to server.", bytesSent);
98 }
99 sendDone.Set();
100 }
101 catch (Exception e)
102 {
103 Console.WriteLine(e.ToString());
104 }
105 }
106 }
107
108 public class InternalPacketHeader
109 {
110 public Guid agent_id;
111 private byte[] buffer = new byte[32];
112 public int numbytes;
113 public int region_port;
114 public int throttlePacketType;
115 public int type;
116
117 public void FromBytes(byte[] bytes)
118 {
119 MemoryStream memstr = new MemoryStream(bytes);
120 memstr.Seek(0, SeekOrigin.Begin);
121 BinaryReader binread = new BinaryReader(memstr);
122
123 type = binread.ReadInt32();
124 throttlePacketType = binread.ReadInt32();
125 numbytes = binread.ReadInt32();
126 agent_id = new Guid(binread.ReadBytes(16));
127 region_port = binread.ReadInt32();
128
129 binread.Close();
130 }
131
132 public byte[] ToBytes()
133 {
134 int i = 0;
135 buffer[i++] = (byte) (type % 256);
136 buffer[i++] = (byte) ((type >> 8) % 256);
137 buffer[i++] = (byte) ((type >> 16) % 256);
138 buffer[i++] = (byte) ((type >> 24) % 256);
139
140 buffer[i++] = (byte) (throttlePacketType % 256);
141 buffer[i++] = (byte) ((throttlePacketType >> 8) % 256);
142 buffer[i++] = (byte) ((throttlePacketType >> 16) % 256);
143 buffer[i++] = (byte) ((throttlePacketType >> 24) % 256);
144
145 buffer[i++] = (byte) (numbytes % 256);
146 buffer[i++] = (byte) ((numbytes >> 8) % 256);
147 buffer[i++] = (byte) ((numbytes >> 16) % 256);
148 buffer[i++] = (byte) ((numbytes >> 24) % 256);
149
150 // no endian care
151 Buffer.BlockCopy(agent_id.ToByteArray(), 0, buffer, i, 16);
152 i += 16;
153
154 buffer[i++] = (byte) (region_port % 256);
155 buffer[i++] = (byte) ((region_port >> 8) % 256);
156 buffer[i++] = (byte) ((region_port >> 16) % 256);
157 buffer[i++] = (byte) ((region_port >> 24) % 256);
158
159 return buffer;
160 }
161 }
162
163 public class TcpClient
164 {
165 public static int internalPacketHeaderSize = 4 * 4 + 16 * 1;
166 private Socket mConnection;
167
168 private string mHostname;
169 private int mPort;
170
171 public TcpClient(string hostname, int port)
172 {
173 mHostname = hostname;
174 mPort = port;
175 mConnection = null;
176 }
177
178 public void connect()
179 {
180 mConnection = AsynchronousClient.StartClient(mHostname, mPort);
181 }
182
183/*
184 public void receive()
185 {
186 if (mConnection == null)
187 {
188 throw new Exception("client not initialized");
189 }
190 try
191 {
192 AsynchronousClient.Receive(this.mConnection);
193 }
194 catch (Exception e)
195 {
196 Console.WriteLine(e.ToString());
197 mConnection = null;
198 }
199 }
200*/
201
202 public void send(InternalPacketHeader header, byte[] packet)
203 {
204 lock (this)
205 {
206 if (mConnection == null)
207 {
208// throw new Exception("client not initialized");
209 connect();
210 }
211
212 AsynchronousClient.Send(mConnection, header.ToBytes());
213
214/*
215for (int i = 0; i < 10; i++)
216{
217 Console.Write(packet[i] + " ");
218}
219Console.WriteLine("");
220*/
221 AsynchronousClient.Send(mConnection, packet);
222 }
223 }
224 }
225} \ No newline at end of file
diff --git a/ThirdParty/3Di/LoadBalancer/TcpServer.cs b/ThirdParty/3Di/LoadBalancer/TcpServer.cs
deleted file mode 100644
index 376c0a5..0000000
--- a/ThirdParty/3Di/LoadBalancer/TcpServer.cs
+++ /dev/null
@@ -1,219 +0,0 @@
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
28using System;
29using System.IO;
30using System.Net;
31using System.Net.Sockets;
32using System.Threading;
33
34namespace OpenSim.ApplicationPlugins.LoadBalancer
35{
36 public class StateObject
37 {
38 public const int BufferSize = 2048;
39 public byte[] buffer = new byte[BufferSize];
40 public InternalPacketHeader header = null;
41 public MemoryStream ms_ptr = new MemoryStream();
42 public Socket workSocket = null;
43 }
44
45 public class AsynchronousSocketListener
46 {
47 public static ManualResetEvent allDone = new ManualResetEvent(false);
48 public static string data = null;
49
50 #region KIRYU
51
52 #region Delegates
53
54 public delegate void PacketRecieveHandler(InternalPacketHeader header, byte[] buff);
55
56 #endregion
57
58 public static PacketRecieveHandler PacketHandler = null;
59
60 #endregion
61
62 public AsynchronousSocketListener()
63 {
64 }
65
66 public static void StartListening(int port)
67 {
68 IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
69 IPAddress ipAddress = ipHostInfo.AddressList[0];
70 IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
71
72 Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
73 try
74 {
75 listener.Bind(localEndPoint);
76 listener.Listen(100);
77 while (true)
78 {
79 allDone.Reset();
80 listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
81 allDone.WaitOne();
82 }
83 }
84 catch (Exception e)
85 {
86 Console.WriteLine(e.ToString());
87 }
88 /*
89 Console.WriteLine("\nPress ENTER to continue...");
90 Console.Read();
91 */
92 }
93
94 public static void AcceptCallback(IAsyncResult ar)
95 {
96 allDone.Set();
97 Socket listener = (Socket) ar.AsyncState;
98 Socket handler = listener.EndAccept(ar);
99 StateObject state = new StateObject();
100 state.workSocket = handler;
101 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
102 }
103
104 public static void ReadCallback(IAsyncResult ar)
105 {
106 StateObject state = (StateObject) ar.AsyncState;
107 Socket handler = state.workSocket;
108
109 try
110 {
111 int bytesRead = handler.EndReceive(ar);
112
113 //MainLog.Instance.Verbose("TCPSERVER", "Received packet [{0}]", bytesRead);
114
115 if (bytesRead > 0)
116 {
117 state.ms_ptr.Write(state.buffer, 0, bytesRead);
118 }
119 else
120 {
121 //MainLog.Instance.Verbose("TCPSERVER", "Connection terminated");
122 return;
123 }
124
125 long rest_size = state.ms_ptr.Length;
126 long current_pos = 0;
127 while (rest_size > TcpClient.internalPacketHeaderSize)
128 {
129 if ((state.header == null) && (rest_size >= TcpClient.internalPacketHeaderSize))
130 {
131 //MainLog.Instance.Verbose("TCPSERVER", "Processing header");
132
133 // reading header
134 state.header = new InternalPacketHeader();
135
136 byte[] headerbytes = new byte[TcpClient.internalPacketHeaderSize];
137 state.ms_ptr.Position = current_pos;
138 state.ms_ptr.Read(headerbytes, 0, TcpClient.internalPacketHeaderSize);
139 state.ms_ptr.Seek(0, SeekOrigin.End);
140 state.header.FromBytes(headerbytes);
141 }
142
143 if ((state.header != null) && (rest_size >= state.header.numbytes + TcpClient.internalPacketHeaderSize))
144 {
145 //MainLog.Instance.Verbose("TCPSERVER", "Processing body");
146
147 // reading body
148 byte[] packet = new byte[state.header.numbytes];
149 state.ms_ptr.Position = current_pos + TcpClient.internalPacketHeaderSize;
150 state.ms_ptr.Read(packet, 0, state.header.numbytes);
151
152/*
153 for (int i=0; i<state.header.numbytes; i++)
154 {
155 System.Console.Write(packet[i] + " ");
156 }
157 System.Console.WriteLine();
158*/
159
160 state.ms_ptr.Seek(0, SeekOrigin.End);
161 // call loadbarancer function
162 if (PacketHandler == null)
163 {
164 //MainLog.Instance.Verbose("TCPSERVER", "PacketHandler not found");
165 }
166 else
167 {
168 //MainLog.Instance.Verbose("TCPSERVER", "calling PacketHandler");
169 PacketHandler(state.header, packet);
170 }
171
172 int read_size = state.header.numbytes + TcpClient.internalPacketHeaderSize;
173 state.header = null;
174
175 rest_size -= read_size;
176 current_pos += read_size;
177
178 if (rest_size < TcpClient.internalPacketHeaderSize)
179 {
180 byte[] rest_bytes = new byte[rest_size];
181 state.ms_ptr.Position = read_size;
182 state.ms_ptr.Read(rest_bytes, 0, (int) rest_size);
183 state.ms_ptr.Close();
184 state.ms_ptr = new MemoryStream();
185 state.ms_ptr.Write(rest_bytes, 0, (int) rest_size);
186 break;
187 }
188 }
189 } // while (true)
190 }
191 catch (Exception)
192 {
193 //MainLog.Instance.Verbose("TCPSERVER", e.ToString());
194 //MainLog.Instance.Verbose("TCPSERVER", e.StackTrace);
195 }
196
197 handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
198 }
199 }
200
201 public class TcpServer
202 {
203 private int mPort = 11000;
204
205 public TcpServer()
206 {
207 }
208
209 public TcpServer(int port)
210 {
211 mPort = port;
212 }
213
214 public void start()
215 {
216 AsynchronousSocketListener.StartListening(mPort);
217 }
218 }
219} \ No newline at end of file
diff --git a/ThirdParty/3Di/README.txt b/ThirdParty/3Di/README.txt
deleted file mode 100644
index fd7980b..0000000
--- a/ThirdParty/3Di/README.txt
+++ /dev/null
@@ -1,82 +0,0 @@
1INTRODUCTION
2
3This folder contains code that implement:
4
51. Dynamic load balancing
6
7OpenSim is allowing many regions to share a region server, but the optimal
8number of regions on each server depends on the load of each region, something
9which may change as time goes on. 3Di is working on a load balancer that
10allows the current load to be monitored and regions to be reassigned without
11requiring the servers to be restarted. To move a region, its state is
12serialized, and a new clone is created on the target server using this
13stream. The old region is then destroyed and the client viewer updated to use
14the new region address.
15
162. Region splitting
17
18Currently each region can hold only a small number of avatars. To allow more
19avatars in each region, 3Di has implemented region splitting, in which several
20copies of a given region can be distributed across the region servers. Each
21sub-region updates a fraction of the avatars, and sends state updates to the
22other sub-regions.
23
24IMPLEMENTATION
25
26The code is organised as follows:
27
28* LoadBalancer: communicates with other region servers and creates/destroys
29regions on command
30* RegionMonitor/MonitorGUI: provides a browser GUI, showing the state of the
31grid, and provides buttons for controlling region movement, splitting, and
32merging.
33* RegionMonitor/ServerPlugin: this is a region server plugin which
34communicates with the load balancer GUI to provide information
35on the identity and status of the regions on the grid
36* RegionProxy: maps messages from a clients to the true location of a region.
37
38USAGE
39
40In order to use these additions the following lines have to be added to
41OpenSim.ini:
42
43proxy_offset = -1000
44proxy_url = http://10.8.1.50:9001
45serialize_dir = /mnt/temp/
46
47If defined, proxy_offset defines how to calculate the true region port, e.g.
48if the XML defines the port as 9000 the actual port is 8000 if proxy_offset
49is -1000. The RegionProxy module will open a port at 9000 which the clients
50can connect to, and route all traffic from there to port 8000. This allows
51the region proxy to run on region server together with regions without
52blocking them by using the same port number.
53
54The proxy location is defined in proxy_url. When splitting, the region state
55is stored on a file in the folder specified in serialize_dir. This has to be
56a shared folder which both region servers involved in the split have access to.
57
583. Monitor GUI
59
60RegionMonitor/MonitorGUI is used to view status of all the managed Region
61servers, and send "Move", "Split", "Merge" commands to a specified Regions
62server.
63
64MonitorGUI is a web-based application. You can access it through a web browser.
65Its back-end is written in perl. (CGI script)
66
67Pre-requierments (CentOS, Fedora)
68
69RPM package "perl-XML-RPC" and relevant packages.
70
71Installation
72
731. Install Apache
742. copy all the files undef "ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs" to
75"$APACHE_ROOT/htdocs"
763. Configuration in "monitor.cgi"
77 * 10th line, set the value to your "monitor.cgi"'s location.
78 * 11th line, set the value to your Grid server.
79 * 12th line, set your region proxy port number here.
80 (ref. OpenSim.ini::NetWork::http_listener_port)
81* The code also works fine with mod_perl.
82
diff --git a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MonitorGUI/View.pm b/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MonitorGUI/View.pm
deleted file mode 100644
index bab462f..0000000
--- a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MonitorGUI/View.pm
+++ /dev/null
@@ -1,214 +0,0 @@
1package MonitorGUI::View;
2
3use strict;
4
5my @server_list;
6my $max_port;
7my $regions;
8
9sub screen_header {
10 return << "HEADER";
11<HTML>
12<HEAD>
13<STYLE TYPE="text/css">
14<!--
15a:link {font-size: 12pt; text-decoration:none; color:#0000ff ;}
16a:visited {font-size: 12pt; text-decoration:none; color:#ff0000 ;}
17a:active {font-size: 12pt; text-decoration:none; color:#00ff00 ;}
18a:hover {font-size: 12pt; text-decoration:underline; color:#ff00ff ;}
19td {font-size: 12pt;border:0;}
20th {background-color:#000000; font-size: 12pt;border:0; color:#FFFFFF; }
21tr {background-color:#FFFFFF; }
22b {font-size: 12pt;}
23//table {background-color:#000000; }
24-->
25</STYLE>
26<META http-equiv="content-type" content="text/html;charset=UTF-8" />
27<META name="refresh" content="300" />
28<TITLE>Region Monitor GUI, 3Di</TITLE>
29</HEAD>
30<BODY>
31HEADER
32}
33
34sub screen_footer {
35 return << "FOOTER";
36</BODY>
37</HTML>
38FOOTER
39}
40
41sub html {
42 my $grid_info = shift;
43 my $regions_list = $grid_info->{"sim-profiles"};
44 $regions = undef;
45 foreach(@$regions_list) {
46 my $ip = $_->{sim_ip} || "UNKNOWN";
47 my $port = $_->{sim_port} || "UNKNOWN";
48 $regions->{$ip}->{$port} = $_;
49 if (!$regions->{max_port} || $regions->{max_port} < $port) {
50 $regions->{max_port} = $port;
51 }
52 }
53 @server_list = keys %$regions;
54 $max_port = $regions->{max_port};
55 my $html = "";
56 foreach my $machine (@server_list) {
57 next if ($machine eq "max_port");
58 $html .= &_machine_view($machine, $regions->{$machine});
59 }
60 return $html;
61}
62
63sub _machine_view {
64 my ($ip, $info) = @_;
65 my $region_html = "";
66 foreach my $region (keys %$info) {
67 $region_html .= &_region_html($info->{$region});
68 }
69 my $html =<< "MACHINE_HTML";
70<h3>$ip</h3>
71$region_html
72<hr size=0 noshade />
73MACHINE_HTML
74}
75
76sub _region_html {
77 my $region_info = shift;
78 my $name = $region_info->{name} || "UNKNOWN";
79 my $x = $region_info->{x} || -1;
80 my $y = $region_info->{y} || -1;
81 my $ip = $region_info->{sim_ip} || "UNKNOWN";
82 my $port = $region_info->{sim_port} || "UNKNOWN";
83 my $get_scene_presence_filter = $region_info->{get_scene_presence_filter};
84 my $get_scene_presence = $region_info->{get_scene_presence};
85 my $get_avatar_filter = $region_info->{get_avatar_filter};
86 my $get_avatar = $region_info->{get_avatar};
87 my $avatar_names = $region_info->{avatar_names};
88 my $action_forms = &_action_forms($region_info);
89 my $html = <<"REGION_HTML";
90<strong>$name</strong><br/>
91$ip:$port | X: $x Y: $y<br/>
92<table border="0">
93<tr>
94<td>get_avatar</td>
95<td>$get_avatar</td>
96<td></td>
97</tr>
98<tr>
99<td>get_avatar_filter</td>
100<td>$get_avatar_filter</td>
101<td>$avatar_names</td>
102</tr>
103<tr>
104<td>get_scene_presence</td>
105<td>$get_scene_presence</td>
106<td></td>
107</tr>
108<tr>
109<td>get_scene_presence_filter</td>
110<td>$get_scene_presence_filter</td>
111<td></td>
112</tr>
113</table>
114$action_forms
115REGION_HTML
116 return $html;
117}
118
119sub _action_forms {
120 my $region_info = shift;
121 my $ip = $region_info->{sim_ip};
122 my $port = $region_info->{sim_port};
123 my $default_input_port = $max_port + 1;
124 my $move_to_options = "";
125 my $split_to_options = "";
126 my $merge_ip_options = "";
127 foreach(@server_list) {
128 next if ($_ eq "max_port");
129 $merge_ip_options .= "<option value=\"$_\">$_\n";
130 $split_to_options .= "<option value=\"$_\">$_\n";
131 #next if ($_ eq $ip);
132 $move_to_options .= "<option value=\"$_\">$_\n";
133 }
134 my $merge_port_options = "";
135 my $merge_disabled = "disabled";
136
137 foreach(keys %{$regions->{$ip}}) {
138 next if ($_ eq $port);
139 $merge_disabled = "";
140 }
141# for(9000..$max_port) { # TODO :
142# next if ($_ eq $port);
143# $merge_port_options .= "<option value=\"$_\">$_\n";
144# }
145 my %port = ();
146 foreach my $ip (keys %$regions) {
147 next if ($ip eq "max_port");
148 print STDERR "--" . $ip . "\n";
149 foreach my $region_port (keys %{$regions->{$ip}}) {
150 print STDERR "---" . $region_port . "\n";
151 $port{$region_port} = 1;
152 }
153 }
154 foreach (keys %port) {
155 $merge_port_options .= "<option value=\"$_\">$_\n";
156 $merge_disabled = "";
157 }
158 return << "ACTION_FORMS";
159<table>
160<tr>
161<form method="POST">
162<td>
163<input type="hidden" name="A" value="move" />
164<input type="hidden" name="from_ip" value="$ip" />
165<input type="hidden" name="from_port" value="$port" />
166<input type="submit" value="Move to" />
167<select name="to_ip">
168$move_to_options
169</select>:
170<input type="text" name="to_port" size="5" value="$default_input_port"/>
171</td>
172</form>
173
174<td>
175&nbsp;&nbsp;|&nbsp;&nbsp;
176</td>
177
178<form method="POST">
179<td>
180<input type="hidden" name="A" value="split" />
181<input type="hidden" name="from_ip" value="$ip" />
182<input type="hidden" name="from_port" value="$port" />
183<input type="submit" value="Split to" />
184<select name="to_ip">
185$split_to_options
186</select>:
187<input type="text" name="to_port" size="5" value="$default_input_port"/>
188</td>
189</form>
190
191<td>
192&nbsp;&nbsp;|&nbsp;&nbsp;
193</td>
194
195<form method="POST">
196<td>
197<input type="hidden" name="A" value="merge" />
198<input type="hidden" name="from_ip" value="$ip" />
199<input type="hidden" name="master_port" value="$port" />
200<input type="submit" value="Merge" $merge_disabled />
201<select name="slave_ip" $merge_disabled>
202$merge_ip_options
203</select>
204<select name="slave_port" $merge_disabled>
205$merge_port_options
206</select>
207</td>
208</form>
209</tr>
210</table>
211ACTION_FORMS
212}
213
2141;
diff --git a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MyCGI.pm b/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MyCGI.pm
deleted file mode 100644
index 1f232aa..0000000
--- a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/MyCGI.pm
+++ /dev/null
@@ -1,91 +0,0 @@
1package MyCGI;
2
3use strict;
4use CGI;
5
6sub getParam {
7 my $cgi;
8 if ($ARGV[0]) {
9 $cgi = new CGI($ARGV[0]);
10 } else {
11 $cgi = new CGI;
12 }
13 my @param_names = $cgi->param();
14 my %param = ();
15 foreach (@param_names) {
16 $param{$_} = $cgi->param($_);
17 }
18 return \%param;
19}
20
21sub getCookie {
22 my $name = shift;
23 my $cookie_value = &CGI::cookie($name);
24 return &_parse($cookie_value);
25}
26
27sub outputHtml {
28 my ($charset, $html) = @_;
29 print &CGI::header(-charset => $charset);
30 print $html;
31}
32
33sub outputXml {
34 my ($charset, $xml) = @_;
35 print &CGI::header( -type => 'text/xml', -charset => $charset );
36 print $xml;
37}
38
39sub makeCookieValue {
40 my $param = shift;
41 my @data = ();
42 foreach(keys %$param) {
43 push(@data, $_ . "=" . $param->{$_});
44 }
45 return join("&", @data);
46}
47
48sub setCookie {
49 my $param = shift;
50 my $cookie = &CGI::cookie(
51 -name => $param->{name} || return,
52 -value => $param->{value},
53 -domain => $param->{domain},
54 -path => $param->{path},
55 -expires => $param->{expires},
56 );
57 return &CGI::header(-cookie => $cookie);
58}
59
60sub redirect {
61 my $dest = shift;
62 &CGI::redirect($dest);
63}
64
65sub urlEncode {
66 my $str = shift;
67 $str =~ s/([^\w ])/'%'.unpack('H2', $1)/eg;
68 $str =~ tr/ /+/;
69 return $str;
70}
71
72sub urlDecode {
73 my $str = shift;
74 $str =~ tr/+/ /;
75 $str =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('H2', $1)/eg;
76 return $str;
77}
78
79sub _parse {
80 my $value = shift;
81 my @pair = split(/&/, $value);
82 my %data = ();
83 foreach(@pair) {
84 my ($name, $value) = split(/=/, $_);
85 $data{$name} = $value;
86 }
87 return \%data;
88}
89
901;
91
diff --git a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/XML/RPC.pm b/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/XML/RPC.pm
deleted file mode 100644
index 5d9b388..0000000
--- a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/XML/RPC.pm
+++ /dev/null
@@ -1,100 +0,0 @@
1package XML::RPC;
2
3use strict;
4use Carp;
5use RPC::XML;
6use RPC::XML::Parser;
7use RPC::XML::Client;
8
9sub new {
10 my ($this, $url) = @_;
11 my %fields = (
12 parser => new RPC::XML::Parser(),
13 url => $url,
14 );
15 return bless \%fields, $this;
16}
17
18sub receive {
19 my ($this, $xmldata, $handler) = @_;
20 my $response = undef;
21 eval {
22 my $request = $this->{parser}->parse($xmldata);
23 my @args = map {$_->value} @{$request->args};
24 $response = $handler->($request->{name}, @args);
25 };
26 if ($@) {
27 my %error = (
28 "error" => "ERROR",
29 "message" => $@,
30 );
31 $response = \%error;
32 }
33 if ( ref($response) eq "RPC::XML::response" ) {
34 return $response->as_string;
35 }
36 else {
37 return RPC::XML::response->new($response)->as_string;
38 }
39}
40
41sub call {
42 my ($this, $method_name, $param) = @_;
43 if (!$this->{url}) {
44 Carp::croak("XMLRPC: url not set for calling $method_name");
45 }
46 my $client = RPC::XML::Client->new($this->{url});
47 my $request_param = undef;
48 my $req = undef;
49 if (ref $param eq "ARRAY") {
50 $request_param = &_make_array_param($param);
51 $req = RPC::XML::request->new(
52 $method_name,
53 @$request_param,
54 );
55 } elsif (ref $param eq "HASH"){
56 $request_param = &_make_hash_param($param);
57 $req = RPC::XML::request->new(
58 $method_name,
59 $request_param,
60 );
61 } else {
62 Carp::croak("unexpected param type");
63 }
64 my $rpc_res = undef;
65 eval {
66 $rpc_res = $client->send_request($req);
67 };
68 if ($@) {
69 Carp::croak("request " . $this->{url} . "/" . $method_name . " failed. $@" );
70 }
71 if (ref($rpc_res) eq "RPC::XML::struct") {
72 my %res = map { $_ => $rpc_res->{$_}->value } keys %$rpc_res; # remember good perl !!
73 return \%res;
74 } elsif (ref($rpc_res) eq "RPC::XML::string") {
75 return $rpc_res->value;
76 } else {
77 return undef;
78 }
79}
80
81sub _make_array_param {
82 my $param = shift;
83 my @array_param = ();
84 foreach (@$param) {
85 push @array_param, RPC::XML::string->new($_); # @@@ only string type
86 }
87 return \@array_param;
88}
89
90sub _make_hash_param {
91 my $param = shift;
92 my %hash_param = ();
93 foreach (keys %$param) {
94 $hash_param{$_} = RPC::XML::string->new($param->{$_}); # @@@ only string type
95 }
96 return RPC::XML::struct->new(\%hash_param);
97}
98
991;
100
diff --git a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/monitor.cgi b/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/monitor.cgi
deleted file mode 100644
index a5f6445..0000000
--- a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/monitor.cgi
+++ /dev/null
@@ -1,202 +0,0 @@
1#!/usr/bin/perl -w
2
3use strict;
4use Carp;
5use MyCGI;
6use XML::RPC;
7use MonitorGUI::View;
8
9use vars qw ($THIS_URL $GRID_SERVER_URL $DEFAULT_PROXY_PORT);
10$THIS_URL = "http://10.8.1.165/monitorgui/monitor.cgi";
11$GRID_SERVER_URL = "http://10.8.1.165/opensim/grid.cgi";
12$DEFAULT_PROXY_PORT = 9000;
13
14my %ACTIONS = (
15 # Region commands
16 move => \&move_command,
17 split => \&split_command,
18 merge => \&merge_command,
19 # display commands
20 default => \&main_screen,
21 refresh => \&refresh,
22);
23
24# ##################
25# main
26my $param = &MyCGI::getParam;
27my $act = $param->{A} || "default";
28my $contents = "";
29if (!$ACTIONS{$act}) {
30 &gui_error("404 NOT FOUND");
31} else {
32 eval {
33 $ACTIONS{$act}->($param);
34 };
35 if ($@) {
36 &gui_error($@);
37 }
38}
39
40# #################
41# Region Commands
42sub move_command {
43 my $param = shift;
44 # from
45 my $from_ip = $param->{from_ip} || Carp::croak("not enough params (from_ip)");
46 my $from_port = $param->{from_port} || Carp::croak("not enough params (from_port)");
47 my $from_url = "http://" . $param->{from_ip} . ":" . $DEFAULT_PROXY_PORT;
48 # to
49 my $to_ip = $param->{to_ip} || Carp::croak("not enough params (to_ip)");
50 my $to_port = $param->{to_port} || Carp::croak("not enough params (to_port)");
51 my $to_url = "http://" . $param->{to_ip} . ":" . $DEFAULT_PROXY_PORT;
52 # commands
53 eval {
54 &OpenSim::Utility::XMLRPCCall_array($from_url, "SerializeRegion", [$from_ip, $from_port]);
55 &OpenSim::Utility::XMLRPCCall_array($to_url, "DeserializeRegion_Move", [$from_ip, $from_port, $to_ip, $to_port]);
56 &OpenSim::Utility::XMLRPCCall_array($from_url, "TerminateRegion", [$from_port]);
57 };
58 if ($@) {
59 print STDERR "Get Status Error: $@\n";
60 }
61
62 # client refresh
63 &redirect_refresh({wait=>5, force=>"$from_url|$to_url", msg=>"Move region $from_ip:$from_port from $from_url to $to_url"});
64}
65
66sub split_command {
67 my $param = shift;
68 # from
69 my $from_ip = $param->{from_ip} || Carp::croak("not enough params (from_ip)");
70 my $from_port = $param->{from_port} || Carp::croak("not enough params (from_port)");
71 my $from_url = "http://" . $param->{from_ip} . ":" . $DEFAULT_PROXY_PORT;
72 # to
73 my $to_ip = $param->{to_ip} || Carp::croak("not enough params (to_ip)");
74 my $to_port = $param->{to_port} || Carp::croak("not enough params (to_port)");
75 my $to_url = "http://" . $param->{to_ip} . ":" . $DEFAULT_PROXY_PORT;
76 # commands
77 eval {
78 &OpenSim::Utility::XMLRPCCall_array($from_url, "SerializeRegion", [$from_ip, $from_port]);
79 &OpenSim::Utility::XMLRPCCall_array($to_url, "DeserializeRegion_Clone", [$from_ip, $from_port, $to_ip, $to_port]);
80 };
81 if ($@) {
82 print STDERR "Get Status Error: $@\n";
83 }
84
85 &redirect_refresh({wait=>5, force=>"$from_url", msg=>"Split region $from_ip:$from_port"});
86}
87
88sub merge_command {
89 my $param = shift;
90 # from
91 my $from_ip = $param->{from_ip} || Carp::croak("not enough params (from_ip)");
92 my $url = "http://" . $param->{from_ip} . ":" . $DEFAULT_PROXY_PORT;
93 # ports
94 my $master_port = $param->{master_port} || Carp::croak("not enough params (master_port)");
95 my $slave_ip = $param->{slave_ip} || Carp::croak("not enough params (slave_ip)");
96 my $slave_port = $param->{slave_port} || Carp::croak("not enough params (slave_port)");
97 my $slave_url = "http://" . $param->{slave_ip} . ":" . $DEFAULT_PROXY_PORT;
98 # commands
99 eval {
100 &XMLRPCCall_array($url, "MergeRegions", [$from_ip, $master_port]);
101 &XMLRPCCall_array($slave_url, "TerminateRegion", [$slave_port]);
102 };
103 if ($@) {
104 print STDERR "Get Status Error: $@\n";
105 }
106 &redirect_refresh({wait=>5, force=>"$url", msg=>"Merge region $from_ip:$master_port, $slave_port"});
107}
108
109# #################
110# Display
111sub main_screen {
112 my %xml_rpc_param = (
113 # TODO: should be 0 - 65535 ?
114 xmin => 999, ymin => 999, xmax => 1010, ymax => 1010,
115 );
116 my $res_obj = undef;
117 eval {
118 $res_obj = &XMLRPCCall($GRID_SERVER_URL, "map_block", \%xml_rpc_param);
119 };
120 if ($@) {
121 &gui_error("map_block Error: " . $@);
122 }
123 my %copy_obj = %$res_obj;
124 my $getstatus_failed = "<font color=\"red\">GetStatus Failed</font>";
125 my $regions_list = $res_obj->{"sim-profiles"};
126 foreach(@$regions_list) {
127 if ($_->{sim_ip} && $_->{sim_port}) {
128 my $url = "http://" . $_->{sim_ip} . ":" . $DEFAULT_PROXY_PORT;
129 my $port = $_->{sim_port};
130 my $res = undef;
131 eval {
132 $res = &XMLRPCCall_array($url, "GetStatus", [$port]);
133 };
134 if ($@) {
135 print STDERR "Get Status Error: $@\n";
136 }
137 $_->{get_scene_presence_filter} = $res ? $res->{get_scene_presence_filter} : $getstatus_failed;
138 $_->{get_scene_presence} = $res ? $res->{get_scene_presence} : $getstatus_failed;
139 $_->{get_avatar_filter} = $res ? $res->{get_avatar_filter} : $getstatus_failed;
140 $_->{get_avatar} = $res ? $res->{get_avatar} : $getstatus_failed;
141 $_->{avatar_names} = $res ? $res->{avatar_names} : "NO USER";
142 }
143 }
144 my $html = &MonitorGUI::View::html(\%copy_obj);
145 &MyCGI::outputHtml("UTF-8", &MonitorGUI::View::screen_header . $html . &MonitorGUI::View::screen_footer);
146}
147
148sub gui_error {
149 my $msg = shift;
150 &MyCGI::outputHtml("UTF-8", "<h1>ERROR</h1><hr />$msg");
151}
152
153sub redirect_refresh {
154 my $args = shift;
155 my $wait = $args->{wait};
156 my $force = $args->{force} || "";
157 my $msg = $args->{msg} || "";
158 my $param = "A=refresh&wait=$wait&ip=$force&msg=$msg";
159 my $dist_url = $THIS_URL . "?" . $param;
160 &MyCGI::redirect($dist_url);
161}
162
163sub refresh {
164 my $param = shift;
165 my $msg = $param->{msg} || "";
166 my $wait = $param->{wait} || 0;
167 my $force = $param->{ip} || "";
168 #my $jump_url = $force ? "$THIS_URL?A=force&ip=$force" : $THIS_URL;
169 my $jump_url = $THIS_URL;
170 my $html =<< "HTML";
171<html>
172<head>
173<meta http-equiv="Refresh" content="$wait;URL=$jump_url" />
174<title>Region Monitor GUI REFRESH</title>
175</head>
176<body>
177<h3>$msg</h3>
178<br>
179wait <font color="red"><b>$wait</b></font> sec for server to take effect ... <br>
180(* The page will jump to "Monitor Screen" automatically)
181</body>
182</html>
183HTML
184 &MyCGI::outputHtml("UTF-8", $html);
185}
186
187# ##################
188# Utility
189sub XMLRPCCall {
190 my ($url, $methodname, $param) = @_;
191 my $xmlrpc = new XML::RPC($url);
192 my $result = $xmlrpc->call($methodname, $param);
193 return $result;
194}
195
196sub XMLRPCCall_array {
197 my ($url, $methodname, $param) = @_;
198 my $xmlrpc = new XML::RPC($url);
199 my $result = $xmlrpc->call($methodname, @$param);
200 return $result;
201}
202
diff --git a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/readme.txt b/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/readme.txt
deleted file mode 100644
index 396ba56..0000000
--- a/ThirdParty/3Di/RegionMonitor/MonitorGUI/htdocs/readme.txt
+++ /dev/null
@@ -1,21 +0,0 @@
1How to get this working on Linux/Apache:
2
3Create a new directory /var/www/monitor and copy all files htdocs/* files there.
4
5Include these lines in /etc/apache2/httpdocs
6---
7<Directory /var/www/monitor>
8 Options +ExecCGI
9</Directory>
10AddHandler cgi-script .cgi
11---
12
13Restart Apache: sudo /etc/init.d/apache2 restart
14
15Check that the perl XML-RPC modules is available ("sudo apt-get install librcp-xml-perl" on Ubuntu)
16
17Edit /var/www/monitor/monitor.cgi to update the IP addresses for the Grid server (TODO: improve this)
18
19Start OpenSim in grid mode, use a browser to open http://localhost/monitor/monitor.cgi
20
21
diff --git a/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs b/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs
deleted file mode 100644
index a1476fa..0000000
--- a/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs
+++ /dev/null
@@ -1,554 +0,0 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using log4net;
35using Mono.Addins;
36using Nwc.XmlRpc;
37using OpenSim.Framework;
38using OpenSim.Framework.Servers;
39
40namespace OpenSim.ApplicationPlugins.RegionProxy
41{
42 /* This module has an interface to OpenSim clients that is constant, and is responsible for relaying
43 * messages to and from clients to the region objects. Since the region objects can be duplicated and
44 * moved dynamically, the proxy provides methods for changing and adding regions. If more than one region
45 * is associated with a client port, then the message will be broadcasted to all those regions.
46 *
47 * The client interface port may be blocked. While being blocked, all messages from the clients will be
48 * stored in the proxy. Once the interface port is unblocked again, all stored messages will be resent
49 * to the regions. This functionality is used when moving or cloning an region to make sure that no messages
50 * are sent to the region while it is being reconfigured.
51 *
52 * The proxy opens a XmlRpc interface with these public methods:
53 * - AddPort
54 * - AddRegion
55 * - ChangeRegion
56 * - BlockClientMessages
57 * - UnblockClientMessages
58 */
59
60 public class RegionProxyPlugin : IApplicationPlugin
61 {
62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
63 private BaseHttpServer command_server;
64 private ProxyServer proxy;
65
66 #region IApplicationPlugin Members
67 // TODO: required by IPlugin, but likely not at all right
68 string m_name = "RegionProxy";
69 string m_version = "0.1";
70
71 public string Version { get { return m_version; } }
72 public string Name { get { return m_name; } }
73
74 public void Initialise()
75 {
76 m_log.Info("[PROXY]: " + Name + " cannot be default-initialized!");
77 throw new PluginNotInitialisedException (Name);
78 }
79
80 public void Initialise(OpenSimBase openSim)
81 {
82 m_log.Info("[PROXY] Starting proxy");
83 string proxyURL = openSim.ConfigSource.Source.Configs["Network"].GetString("proxy_url", "");
84 if (proxyURL.Length == 0) return;
85
86 uint port = (uint) Int32.Parse(proxyURL.Split(new char[] {':'})[2]);
87 command_server = new BaseHttpServer(port);
88 command_server.Start();
89 command_server.AddXmlRPCHandler("AddPort", AddPort);
90 command_server.AddXmlRPCHandler("AddRegion", AddRegion);
91 command_server.AddXmlRPCHandler("DeleteRegion", DeleteRegion);
92 command_server.AddXmlRPCHandler("ChangeRegion", ChangeRegion);
93 command_server.AddXmlRPCHandler("BlockClientMessages", BlockClientMessages);
94 command_server.AddXmlRPCHandler("UnblockClientMessages", UnblockClientMessages);
95 command_server.AddXmlRPCHandler("Stop", Stop);
96
97 proxy = new ProxyServer(m_log);
98 }
99
100 public void Dispose()
101 {
102 }
103
104 #endregion
105
106 private XmlRpcResponse Stop(XmlRpcRequest request)
107 {
108 try
109 {
110 proxy.Stop();
111 }
112 catch (Exception e)
113 {
114 m_log.Error("[PROXY]" + e.Message);
115 m_log.Error("[PROXY]" + e.StackTrace);
116 }
117 return new XmlRpcResponse();
118 }
119
120 private XmlRpcResponse AddPort(XmlRpcRequest request)
121 {
122 try
123 {
124 int clientPort = (int) request.Params[0];
125 int regionPort = (int) request.Params[1];
126 string regionUrl = (string) request.Params[2];
127 proxy.AddPort(clientPort, regionPort, regionUrl);
128 }
129 catch (Exception e)
130 {
131 m_log.Error("[PROXY]" + e.Message);
132 m_log.Error("[PROXY]" + e.StackTrace);
133 }
134 return new XmlRpcResponse();
135 }
136
137 private XmlRpcResponse AddRegion(XmlRpcRequest request)
138 {
139 try
140 {
141 int currentRegionPort = (int) request.Params[0];
142 string currentRegionUrl = (string) request.Params[1];
143 int newRegionPort = (int) request.Params[2];
144 string newRegionUrl = (string) request.Params[3];
145 proxy.AddRegion(currentRegionPort, currentRegionUrl, newRegionPort, newRegionUrl);
146 }
147 catch (Exception e)
148 {
149 m_log.Error("[PROXY]" + e.Message);
150 m_log.Error("[PROXY]" + e.StackTrace);
151 }
152 return new XmlRpcResponse();
153 }
154
155 private XmlRpcResponse ChangeRegion(XmlRpcRequest request)
156 {
157 try
158 {
159 int currentRegionPort = (int) request.Params[0];
160 string currentRegionUrl = (string) request.Params[1];
161 int newRegionPort = (int) request.Params[2];
162 string newRegionUrl = (string) request.Params[3];
163 proxy.ChangeRegion(currentRegionPort, currentRegionUrl, newRegionPort, newRegionUrl);
164 }
165 catch (Exception e)
166 {
167 m_log.Error("[PROXY]" + e.Message);
168 m_log.Error("[PROXY]" + e.StackTrace);
169 }
170 return new XmlRpcResponse();
171 }
172
173 private XmlRpcResponse DeleteRegion(XmlRpcRequest request)
174 {
175 try
176 {
177 int currentRegionPort = (int) request.Params[0];
178 string currentRegionUrl = (string) request.Params[1];
179 proxy.DeleteRegion(currentRegionPort, currentRegionUrl);
180 }
181 catch (Exception e)
182 {
183 m_log.Error("[PROXY]" + e.Message);
184 m_log.Error("[PROXY]" + e.StackTrace);
185 }
186 return new XmlRpcResponse();
187 }
188
189 private XmlRpcResponse BlockClientMessages(XmlRpcRequest request)
190 {
191 try
192 {
193 string regionUrl = (string) request.Params[0];
194 int regionPort = (int) request.Params[1];
195 proxy.BlockClientMessages(regionUrl, regionPort);
196 }
197 catch (Exception e)
198 {
199 m_log.Error("[PROXY]" + e.Message);
200 m_log.Error("[PROXY]" + e.StackTrace);
201 }
202 return new XmlRpcResponse();
203 }
204
205 private XmlRpcResponse UnblockClientMessages(XmlRpcRequest request)
206 {
207 try
208 {
209 string regionUrl = (string) request.Params[0];
210 int regionPort = (int) request.Params[1];
211 proxy.UnblockClientMessages(regionUrl, regionPort);
212 }
213 catch (Exception e)
214 {
215 m_log.Error("[PROXY]" + e.Message);
216 m_log.Error("[PROXY]" + e.StackTrace);
217 }
218 return new XmlRpcResponse();
219 }
220 }
221
222
223 public class ProxyServer
224 {
225 protected readonly ILog m_log;
226 protected ProxyMap proxy_map = new ProxyMap();
227 protected AsyncCallback receivedData;
228 protected bool running;
229
230 public ProxyServer(ILog log)
231 {
232 m_log = log;
233 running = false;
234 receivedData = new AsyncCallback(OnReceivedData);
235 }
236
237 public void BlockClientMessages(string regionUrl, int regionPort)
238 {
239 EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(regionUrl), regionPort));
240 ProxyMap.RegionData rd = proxy_map.GetRegionData(client);
241 rd.isBlocked = true;
242 }
243
244 public void UnblockClientMessages(string regionUrl, int regionPort)
245 {
246 EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(regionUrl), regionPort));
247 ProxyMap.RegionData rd = proxy_map.GetRegionData(client);
248
249 rd.isBlocked = false;
250 while (rd.storedMessages.Count > 0)
251 {
252 StoredMessage msg = (StoredMessage) rd.storedMessages.Dequeue();
253 //m_log.Verbose("[PROXY]"+"Resending blocked message from {0}", msg.senderEP);
254 SendMessage(msg.buffer, msg.length, msg.senderEP, msg.sd);
255 }
256 }
257
258 public void AddRegion(int oldRegionPort, string oldRegionUrl, int newRegionPort, string newRegionUrl)
259 {
260 //m_log.Verbose("[PROXY]"+"AddRegion {0} {1}", oldRegionPort, newRegionPort);
261 EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(oldRegionUrl), oldRegionPort));
262 ProxyMap.RegionData data = proxy_map.GetRegionData(client);
263 data.regions.Add(new IPEndPoint(IPAddress.Parse(newRegionUrl), newRegionPort));
264 }
265
266 public void ChangeRegion(int oldRegionPort, string oldRegionUrl, int newRegionPort, string newRegionUrl)
267 {
268 //m_log.Verbose("[PROXY]"+"ChangeRegion {0} {1}", oldRegionPort, newRegionPort);
269 EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(oldRegionUrl), oldRegionPort));
270 ProxyMap.RegionData data = proxy_map.GetRegionData(client);
271 data.regions.Clear();
272 data.regions.Add(new IPEndPoint(IPAddress.Parse(newRegionUrl), newRegionPort));
273 }
274
275 public void DeleteRegion(int oldRegionPort, string oldRegionUrl)
276 {
277 m_log.InfoFormat("[PROXY]" + "DeleteRegion {0} {1}", oldRegionPort, oldRegionUrl);
278 EndPoint regionEP = new IPEndPoint(IPAddress.Parse(oldRegionUrl), oldRegionPort);
279 EndPoint client = proxy_map.GetClient(regionEP);
280 ProxyMap.RegionData data = proxy_map.GetRegionData(client);
281 data.regions.Remove(regionEP);
282 }
283
284 public void AddPort(int clientPort, int regionPort, string regionUrl)
285 {
286 running = true;
287
288 //m_log.Verbose("[PROXY]"+"AddPort {0} {1}", clientPort, regionPort);
289 IPEndPoint clientEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), clientPort);
290 proxy_map.Add(clientEP, new IPEndPoint(IPAddress.Parse(regionUrl), regionPort));
291
292 ServerData sd = new ServerData();
293 sd.clientEP = new IPEndPoint(clientEP.Address, clientEP.Port);
294
295 OpenPort(sd);
296 }
297
298 protected void OpenPort(ServerData sd)
299 {
300 // sd.clientEP must be set before calling this function
301
302 ClosePort(sd);
303
304 try
305 {
306 m_log.InfoFormat("[PROXY] Opening special UDP socket on {0}", sd.clientEP);
307 sd.serverIP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), ((IPEndPoint) sd.clientEP).Port);
308 sd.server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
309 sd.server.Bind(sd.serverIP);
310
311 sd.senderEP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
312 //receivedData = new AsyncCallback(OnReceivedData);
313 sd.server.BeginReceiveFrom(sd.recvBuffer, 0, sd.recvBuffer.Length, SocketFlags.None, ref sd.senderEP, receivedData, sd);
314 }
315 catch (Exception e)
316 {
317 m_log.ErrorFormat("[PROXY] Failed to (re)open socket {0}", sd.clientEP);
318 m_log.Error("[PROXY]" + e.Message);
319 m_log.Error("[PROXY]" + e.StackTrace);
320 }
321 }
322
323 protected static void ClosePort(ServerData sd)
324 {
325 // Close the port if it exists and is open
326 if (sd.server == null) return;
327
328 try
329 {
330 sd.server.Shutdown(SocketShutdown.Both);
331 sd.server.Close();
332 }
333 catch (Exception)
334 {
335 }
336 }
337
338 public void Stop()
339 {
340 running = false;
341 m_log.InfoFormat("[PROXY] Stopping the proxy server");
342 }
343
344
345 protected virtual void OnReceivedData(IAsyncResult result)
346 {
347 if (!running) return;
348
349 ServerData sd = (ServerData) result.AsyncState;
350 sd.senderEP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
351
352 try
353 {
354 int numBytes = sd.server.EndReceiveFrom(result, ref sd.senderEP);
355 if (numBytes > 0)
356 {
357 SendMessage(sd.recvBuffer, numBytes, sd.senderEP, sd);
358 }
359 }
360 catch (Exception e)
361 {
362// OpenPort(sd); // reopen the port just in case
363 m_log.ErrorFormat("[PROXY] EndReceiveFrom failed in {0}", sd.clientEP);
364 m_log.Error("[PROXY]" + e.Message);
365 m_log.Error("[PROXY]" + e.StackTrace);
366 }
367
368 WaitForNextMessage(sd);
369 }
370
371 protected void WaitForNextMessage(ServerData sd)
372 {
373 bool error = true;
374 while (error)
375 {
376 error = false;
377 try
378 {
379 sd.server.BeginReceiveFrom(sd.recvBuffer, 0, sd.recvBuffer.Length, SocketFlags.None, ref sd.senderEP, receivedData, sd);
380 }
381 catch (Exception e)
382 {
383 error = true;
384 m_log.ErrorFormat("[PROXY] BeginReceiveFrom failed, retrying... {0}", sd.clientEP);
385 m_log.Error("[PROXY]" + e.Message);
386 m_log.Error("[PROXY]" + e.StackTrace);
387 OpenPort(sd);
388 }
389 }
390 }
391
392 protected void SendMessage(byte[] buffer, int length, EndPoint senderEP, ServerData sd)
393 {
394 int numBytes = length;
395
396 //m_log.ErrorFormat("[PROXY] Got message from {0} in thread {1}, size {2}", senderEP, sd.clientEP, numBytes);
397 EndPoint client = proxy_map.GetClient(senderEP);
398
399 if (client == null)
400 {
401 // This message comes from a client object, forward it to the the region(s)
402 ProxyCodec.EncodeProxyMessage(buffer, ref numBytes, senderEP);
403 ProxyMap.RegionData rd = proxy_map.GetRegionData(sd.clientEP);
404 foreach (EndPoint region in rd.regions)
405 {
406 if (rd.isBlocked)
407 {
408 rd.storedMessages.Enqueue(new StoredMessage(buffer, length, numBytes, senderEP, sd));
409 }
410 else
411 {
412 try
413 {
414 sd.server.SendTo(buffer, numBytes, SocketFlags.None, region);
415 //m_log.InfoFormat("[PROXY] Sending client message from {0} to {1}", senderEP, region);
416 }
417 catch (Exception e)
418 {
419 OpenPort(sd); // reopen the port just in case
420 m_log.ErrorFormat("[PROXY] Failed sending client message from {0} to {1}", senderEP, region);
421 m_log.Error("[PROXY]" + e.Message);
422 m_log.Error("[PROXY]" + e.StackTrace);
423 return;
424 }
425 }
426 }
427 }
428 else
429 {
430 try
431 {
432 client = ProxyCodec.DecodeProxyMessage(buffer, ref numBytes);
433 try
434 {
435 // This message comes from a region object, forward it to the its client
436 sd.server.SendTo(buffer, numBytes, SocketFlags.None, client);
437 //m_log.InfoFormat("[PROXY] Sending region message from {0} to {1}, size {2}", senderEP, client, numBytes);
438 }
439 catch (Exception e)
440 {
441 OpenPort(sd); // reopen the port just in case
442 m_log.ErrorFormat("[PROXY] Failed sending region message from {0} to {1}", senderEP, client);
443 m_log.Error("[PROXY]" + e.Message);
444 m_log.Error("[PROXY]" + e.StackTrace);
445 return;
446 }
447 }
448 catch (Exception e)
449 {
450 OpenPort(sd); // reopen the port just in case
451 m_log.ErrorFormat("[PROXY] Failed decoding region message from {0}", senderEP);
452 m_log.Error("[PROXY]" + e.Message);
453 m_log.Error("[PROXY]" + e.StackTrace);
454 return;
455 }
456 }
457 }
458
459 #region Nested type: ProxyMap
460
461 protected class ProxyMap
462 {
463 private Dictionary<EndPoint, RegionData> map;
464
465 public ProxyMap()
466 {
467 map = new Dictionary<EndPoint, RegionData>();
468 }
469
470 public void Add(EndPoint client, EndPoint region)
471 {
472 if (map.ContainsKey(client))
473 {
474 map[client].regions.Add(region);
475 }
476 else
477 {
478 RegionData regions = new RegionData();
479 map.Add(client, regions);
480 regions.regions.Add(region);
481 }
482 }
483
484 public RegionData GetRegionData(EndPoint client)
485 {
486 return map[client];
487 }
488
489 public EndPoint GetClient(EndPoint region)
490 {
491 foreach (KeyValuePair<EndPoint, RegionData> pair in map)
492 {
493 if (pair.Value.regions.Contains(region))
494 {
495 return pair.Key;
496 }
497 }
498 return null;
499 }
500
501 #region Nested type: RegionData
502
503 public class RegionData
504 {
505 public bool isBlocked = false;
506 public List<EndPoint> regions = new List<EndPoint>();
507 public Queue storedMessages = new Queue();
508 }
509
510 #endregion
511 }
512
513 #endregion
514
515 #region Nested type: ServerData
516
517 protected class ServerData
518 {
519 public EndPoint clientEP;
520 public byte[] recvBuffer = new byte[4096];
521 public EndPoint senderEP;
522 public Socket server;
523 public IPEndPoint serverIP;
524
525 public ServerData()
526 {
527 server = null;
528 }
529 }
530
531 #endregion
532
533 #region Nested type: StoredMessage
534
535 protected class StoredMessage
536 {
537 public byte[] buffer;
538 public int length;
539 public ServerData sd;
540 public EndPoint senderEP;
541
542 public StoredMessage(byte[] buffer, int length, int maxLength, EndPoint senderEP, ServerData sd)
543 {
544 this.buffer = new byte[maxLength];
545 this.length = length;
546 for (int i = 0; i < length; i++) this.buffer[i] = buffer[i];
547 this.senderEP = senderEP;
548 this.sd = sd;
549 }
550 }
551
552 #endregion
553 }
554}
diff --git a/ThirdParty/3Di/RegionProxy/Resources/RegionProxy.addin.xml b/ThirdParty/3Di/RegionProxy/Resources/RegionProxy.addin.xml
deleted file mode 100644
index 9fa6716..0000000
--- a/ThirdParty/3Di/RegionProxy/Resources/RegionProxy.addin.xml
+++ /dev/null
@@ -1,11 +0,0 @@
1<Addin id="RegionProxy" version="0.1">
2 <Runtime>
3 <Import assembly="OpenSim.ApplicationPlugins.RegionProxy.dll" />
4 </Runtime>
5 <Dependencies>
6 <Addin id="OpenSim" version="0.5" />
7 </Dependencies>
8 <Extension path="/OpenSim/Startup">
9 <Plugin id="RegionProxy" type="OpenSim.ApplicationPlugins.RegionProxy.RegionProxyPlugin" />
10 </Extension>
11</Addin>