aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs')
-rw-r--r--ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs554
1 files changed, 0 insertions, 554 deletions
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}