diff options
Diffstat (limited to 'ThirdParty/3Di/RegionProxy')
-rw-r--r-- | ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs b/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs new file mode 100644 index 0000000..13aec48 --- /dev/null +++ b/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | */ | ||
28 | |||
29 | using System; | ||
30 | using System.IO; | ||
31 | using System.Net; | ||
32 | using System.Xml; | ||
33 | using System.Text; | ||
34 | using System.Xml.Serialization; | ||
35 | using System.Net.Sockets; | ||
36 | using System.Collections; | ||
37 | using System.Collections.Generic; | ||
38 | using System.Diagnostics; | ||
39 | |||
40 | using OpenSim.Framework; | ||
41 | using OpenSim.Framework.Servers; | ||
42 | using OpenSim.Framework.Console; | ||
43 | using Nwc.XmlRpc; | ||
44 | |||
45 | using Mono.Addins; | ||
46 | |||
47 | [assembly:Addin] | ||
48 | [assembly:AddinDependency ("OpenSim", "0.5")] | ||
49 | |||
50 | namespace OpenSim.ApplicationPlugins.RegionProxy | ||
51 | { | ||
52 | /* This module has an interface to OpenSim clients that is constant, and is responsible for relaying | ||
53 | * messages to and from clients to the region objects. Since the region objects can be duplicated and | ||
54 | * moved dynamically, the proxy provides methods for changing and adding regions. If more than one region | ||
55 | * is associated with a client port, then the message will be broadcasted to all those regions. | ||
56 | * | ||
57 | * The client interface port may be blocked. While being blocked, all messages from the clients will be | ||
58 | * stored in the proxy. Once the interface port is unblocked again, all stored messages will be resent | ||
59 | * to the regions. This functionality is used when moving or cloning an region to make sure that no messages | ||
60 | * are sent to the region while it is being reconfigured. | ||
61 | * | ||
62 | * The proxy opens a XmlRpc interface with these public methods: | ||
63 | * - AddPort | ||
64 | * - AddRegion | ||
65 | * - ChangeRegion | ||
66 | * - BlockClientMessages | ||
67 | * - UnblockClientMessages | ||
68 | */ | ||
69 | |||
70 | [Extension("/OpenSim/Startup")] | ||
71 | public class RegionProxyPlugin : IApplicationPlugin | ||
72 | { | ||
73 | private ProxyServer proxy; | ||
74 | private BaseHttpServer command_server; | ||
75 | private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
76 | |||
77 | public void Initialise(OpenSimMain openSim) | ||
78 | { | ||
79 | Console.WriteLine("Starting proxy"); | ||
80 | string proxyURL = openSim.ConfigSource.Configs["Network"].GetString("proxy_url", ""); | ||
81 | if(proxyURL.Length==0) return; | ||
82 | |||
83 | uint port = (uint) Int32.Parse(proxyURL.Split(new char[] { ':' })[2]); | ||
84 | command_server = new BaseHttpServer(port); | ||
85 | command_server.Start(); | ||
86 | command_server.AddXmlRPCHandler("AddPort", AddPort); | ||
87 | command_server.AddXmlRPCHandler("AddRegion", AddRegion); | ||
88 | command_server.AddXmlRPCHandler("DeleteRegion", DeleteRegion); | ||
89 | command_server.AddXmlRPCHandler("ChangeRegion", ChangeRegion); | ||
90 | command_server.AddXmlRPCHandler("BlockClientMessages", BlockClientMessages); | ||
91 | command_server.AddXmlRPCHandler("UnblockClientMessages", UnblockClientMessages); | ||
92 | command_server.AddXmlRPCHandler("Stop", Stop); | ||
93 | |||
94 | proxy=new ProxyServer(m_log); | ||
95 | } | ||
96 | |||
97 | public void Close() | ||
98 | { | ||
99 | } | ||
100 | |||
101 | private XmlRpcResponse Stop(XmlRpcRequest request) | ||
102 | { | ||
103 | try | ||
104 | { | ||
105 | proxy.Stop(); | ||
106 | } | ||
107 | catch (Exception e) | ||
108 | { | ||
109 | m_log.Error("[PROXY]" + e.Message); | ||
110 | m_log.Error("[PROXY]" + e.StackTrace); | ||
111 | } | ||
112 | return new XmlRpcResponse(); | ||
113 | } | ||
114 | |||
115 | private XmlRpcResponse AddPort(XmlRpcRequest request) | ||
116 | { | ||
117 | try { | ||
118 | int clientPort = (int) request.Params[0]; | ||
119 | int regionPort = (int) request.Params[1]; | ||
120 | string regionUrl = (string) request.Params[2]; | ||
121 | proxy.AddPort(clientPort, regionPort, regionUrl); | ||
122 | } catch(Exception e) { | ||
123 | m_log.Error("[PROXY]"+e.Message); | ||
124 | m_log.Error("[PROXY]"+e.StackTrace); | ||
125 | } | ||
126 | return new XmlRpcResponse(); | ||
127 | } | ||
128 | |||
129 | private XmlRpcResponse AddRegion(XmlRpcRequest request) | ||
130 | { | ||
131 | try { | ||
132 | int currentRegionPort = (int) request.Params[0]; | ||
133 | string currentRegionUrl = (string) request.Params[1]; | ||
134 | int newRegionPort = (int) request.Params[2]; | ||
135 | string newRegionUrl = (string) request.Params[3]; | ||
136 | proxy.AddRegion(currentRegionPort, currentRegionUrl, newRegionPort, newRegionUrl); | ||
137 | } catch(Exception e) { | ||
138 | m_log.Error("[PROXY]"+e.Message); | ||
139 | m_log.Error("[PROXY]"+e.StackTrace); | ||
140 | } | ||
141 | return new XmlRpcResponse(); | ||
142 | } | ||
143 | |||
144 | private XmlRpcResponse ChangeRegion(XmlRpcRequest request) | ||
145 | { | ||
146 | try { | ||
147 | int currentRegionPort = (int) request.Params[0]; | ||
148 | string currentRegionUrl = (string) request.Params[1]; | ||
149 | int newRegionPort = (int) request.Params[2]; | ||
150 | string newRegionUrl = (string) request.Params[3]; | ||
151 | proxy.ChangeRegion(currentRegionPort, currentRegionUrl, newRegionPort, newRegionUrl); | ||
152 | } catch(Exception e) { | ||
153 | m_log.Error("[PROXY]"+e.Message); | ||
154 | m_log.Error("[PROXY]"+e.StackTrace); | ||
155 | } | ||
156 | return new XmlRpcResponse(); | ||
157 | } | ||
158 | |||
159 | private XmlRpcResponse DeleteRegion(XmlRpcRequest request) | ||
160 | { | ||
161 | try { | ||
162 | int currentRegionPort = (int) request.Params[0]; | ||
163 | string currentRegionUrl = (string) request.Params[1]; | ||
164 | proxy.DeleteRegion(currentRegionPort, currentRegionUrl); | ||
165 | } catch(Exception e) { | ||
166 | m_log.Error("[PROXY]"+e.Message); | ||
167 | m_log.Error("[PROXY]"+e.StackTrace); | ||
168 | } | ||
169 | return new XmlRpcResponse(); | ||
170 | } | ||
171 | |||
172 | private XmlRpcResponse BlockClientMessages(XmlRpcRequest request) | ||
173 | { | ||
174 | try { | ||
175 | string regionUrl = (string) request.Params[0]; | ||
176 | int regionPort = (int) request.Params[1]; | ||
177 | proxy.BlockClientMessages(regionUrl, regionPort); | ||
178 | } catch(Exception e) { | ||
179 | m_log.Error("[PROXY]"+e.Message); | ||
180 | m_log.Error("[PROXY]"+e.StackTrace); | ||
181 | } | ||
182 | return new XmlRpcResponse(); | ||
183 | } | ||
184 | |||
185 | private XmlRpcResponse UnblockClientMessages(XmlRpcRequest request) | ||
186 | { | ||
187 | try { | ||
188 | string regionUrl = (string) request.Params[0]; | ||
189 | int regionPort = (int) request.Params[1]; | ||
190 | proxy.UnblockClientMessages(regionUrl, regionPort); | ||
191 | } catch(Exception e) { | ||
192 | m_log.Error("[PROXY]"+e.Message); | ||
193 | m_log.Error("[PROXY]"+e.StackTrace); | ||
194 | } | ||
195 | return new XmlRpcResponse(); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | |||
200 | public class ProxyServer { | ||
201 | protected AsyncCallback receivedData; | ||
202 | protected ProxyMap proxy_map = new ProxyMap(); | ||
203 | protected readonly log4net.ILog m_log; | ||
204 | protected bool running; | ||
205 | |||
206 | protected class ProxyMap | ||
207 | { | ||
208 | public class RegionData | ||
209 | { | ||
210 | public bool isBlocked = false; | ||
211 | public Queue storedMessages = new Queue(); | ||
212 | public List<EndPoint> regions = new List<EndPoint>(); | ||
213 | } | ||
214 | |||
215 | private Dictionary<EndPoint, RegionData> map; | ||
216 | |||
217 | public ProxyMap() { | ||
218 | map = new Dictionary<EndPoint, RegionData>(); | ||
219 | } | ||
220 | |||
221 | public void Add(EndPoint client, EndPoint region) | ||
222 | { | ||
223 | if(map.ContainsKey(client)) | ||
224 | { | ||
225 | map[client].regions.Add(region); | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | RegionData regions = new RegionData(); | ||
230 | map.Add(client, regions); | ||
231 | regions.regions.Add(region); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | public RegionData GetRegionData(EndPoint client) | ||
236 | { | ||
237 | return map[client]; | ||
238 | } | ||
239 | |||
240 | public EndPoint GetClient(EndPoint region) | ||
241 | { | ||
242 | foreach (KeyValuePair<EndPoint, RegionData> pair in map) | ||
243 | { | ||
244 | if(pair.Value.regions.Contains(region)) | ||
245 | { | ||
246 | return pair.Key; | ||
247 | } | ||
248 | } | ||
249 | return null; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | protected class ServerData { | ||
254 | public Socket server; | ||
255 | public EndPoint clientEP; | ||
256 | public EndPoint senderEP; | ||
257 | public IPEndPoint serverIP; | ||
258 | public byte[] recvBuffer = new byte[4096]; | ||
259 | |||
260 | public ServerData() | ||
261 | { | ||
262 | server = null; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | protected class StoredMessage | ||
267 | { | ||
268 | public byte[] buffer; | ||
269 | public int length; | ||
270 | public EndPoint senderEP; | ||
271 | public ServerData sd; | ||
272 | |||
273 | public StoredMessage(byte[] buffer, int length, int maxLength, EndPoint senderEP, ServerData sd) | ||
274 | { | ||
275 | this.buffer = new byte[maxLength]; | ||
276 | this.length = length; | ||
277 | for(int i=0; i<length; i++) this.buffer[i]=buffer[i]; | ||
278 | this.senderEP = senderEP; | ||
279 | this.sd = sd; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | public ProxyServer(log4net.ILog log) | ||
284 | { | ||
285 | m_log = log; | ||
286 | running=false; | ||
287 | receivedData = new AsyncCallback(OnReceivedData); | ||
288 | } | ||
289 | |||
290 | public void BlockClientMessages(string regionUrl, int regionPort) | ||
291 | { | ||
292 | EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(regionUrl), regionPort)); | ||
293 | ProxyMap.RegionData rd = proxy_map.GetRegionData(client); | ||
294 | rd.isBlocked = true; | ||
295 | } | ||
296 | |||
297 | public void UnblockClientMessages(string regionUrl, int regionPort) | ||
298 | { | ||
299 | EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(regionUrl), regionPort)); | ||
300 | ProxyMap.RegionData rd = proxy_map.GetRegionData(client); | ||
301 | |||
302 | rd.isBlocked = false; | ||
303 | while(rd.storedMessages.Count > 0) { | ||
304 | StoredMessage msg = (StoredMessage) rd.storedMessages.Dequeue(); | ||
305 | //m_log.Verbose("[PROXY]"+"Resending blocked message from {0}", msg.senderEP); | ||
306 | SendMessage(msg.buffer, msg.length, msg.senderEP, msg.sd); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | public void AddRegion(int oldRegionPort, string oldRegionUrl, int newRegionPort, string newRegionUrl) | ||
311 | { | ||
312 | //m_log.Verbose("[PROXY]"+"AddRegion {0} {1}", oldRegionPort, newRegionPort); | ||
313 | EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(oldRegionUrl), oldRegionPort)); | ||
314 | ProxyMap.RegionData data = proxy_map.GetRegionData(client); | ||
315 | data.regions.Add(new IPEndPoint(IPAddress.Parse(newRegionUrl), newRegionPort)); | ||
316 | } | ||
317 | |||
318 | public void ChangeRegion(int oldRegionPort, string oldRegionUrl, int newRegionPort, string newRegionUrl) | ||
319 | { | ||
320 | //m_log.Verbose("[PROXY]"+"ChangeRegion {0} {1}", oldRegionPort, newRegionPort); | ||
321 | EndPoint client = proxy_map.GetClient(new IPEndPoint(IPAddress.Parse(oldRegionUrl), oldRegionPort)); | ||
322 | ProxyMap.RegionData data = proxy_map.GetRegionData(client); | ||
323 | data.regions.Clear(); | ||
324 | data.regions.Add(new IPEndPoint(IPAddress.Parse(newRegionUrl), newRegionPort)); | ||
325 | } | ||
326 | |||
327 | public void DeleteRegion(int oldRegionPort, string oldRegionUrl) | ||
328 | { | ||
329 | m_log.InfoFormat("[PROXY]"+"DeleteRegion {0} {1}", oldRegionPort, oldRegionUrl); | ||
330 | EndPoint regionEP = new IPEndPoint(IPAddress.Parse(oldRegionUrl), oldRegionPort); | ||
331 | EndPoint client = proxy_map.GetClient(regionEP); | ||
332 | ProxyMap.RegionData data = proxy_map.GetRegionData(client); | ||
333 | data.regions.Remove(regionEP); | ||
334 | } | ||
335 | |||
336 | public void AddPort(int clientPort, int regionPort, string regionUrl) | ||
337 | { | ||
338 | running = true; | ||
339 | |||
340 | //m_log.Verbose("[PROXY]"+"AddPort {0} {1}", clientPort, regionPort); | ||
341 | IPEndPoint clientEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), clientPort); | ||
342 | proxy_map.Add(clientEP, new IPEndPoint(IPAddress.Parse(regionUrl), regionPort)); | ||
343 | |||
344 | ServerData sd = new ServerData(); | ||
345 | sd.clientEP = new IPEndPoint(clientEP.Address, clientEP.Port); | ||
346 | |||
347 | OpenPort(sd); | ||
348 | } | ||
349 | |||
350 | protected void OpenPort(ServerData sd) | ||
351 | { | ||
352 | // sd.clientEP must be set before calling this function | ||
353 | |||
354 | ClosePort(sd); | ||
355 | |||
356 | try | ||
357 | { | ||
358 | |||
359 | m_log.InfoFormat("[PROXY] Opening UDP socket on {0}", sd.clientEP); | ||
360 | sd.serverIP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), ((IPEndPoint)sd.clientEP).Port); | ||
361 | sd.server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); | ||
362 | sd.server.Bind(sd.serverIP); | ||
363 | |||
364 | sd.senderEP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); | ||
365 | //receivedData = new AsyncCallback(OnReceivedData); | ||
366 | sd.server.BeginReceiveFrom(sd.recvBuffer, 0, sd.recvBuffer.Length, SocketFlags.None, ref sd.senderEP, receivedData, sd); | ||
367 | } | ||
368 | catch (Exception e) | ||
369 | { | ||
370 | m_log.ErrorFormat("[PROXY] Failed to (re)open socket {0}", sd.clientEP); | ||
371 | m_log.Error("[PROXY]" + e.Message); | ||
372 | m_log.Error("[PROXY]" + e.StackTrace); | ||
373 | } | ||
374 | } | ||
375 | |||
376 | protected void ClosePort(ServerData sd) | ||
377 | { | ||
378 | // Close the port if it exists and is open | ||
379 | if (sd.server == null) return; | ||
380 | |||
381 | try | ||
382 | { | ||
383 | sd.server.Shutdown(SocketShutdown.Both); | ||
384 | sd.server.Close(); | ||
385 | } | ||
386 | catch (Exception) | ||
387 | { | ||
388 | } | ||
389 | } | ||
390 | |||
391 | public void Stop() | ||
392 | { | ||
393 | running = false; | ||
394 | m_log.InfoFormat("[PROXY] Stopping the proxy server"); | ||
395 | |||
396 | } | ||
397 | |||
398 | |||
399 | protected virtual void OnReceivedData(IAsyncResult result) | ||
400 | { | ||
401 | if(!running) return; | ||
402 | |||
403 | ServerData sd = (ServerData)result.AsyncState; | ||
404 | sd.senderEP = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0); | ||
405 | |||
406 | try | ||
407 | { | ||
408 | int numBytes = sd.server.EndReceiveFrom(result, ref sd.senderEP); | ||
409 | if (numBytes > 0) | ||
410 | { | ||
411 | SendMessage(sd.recvBuffer, numBytes, sd.senderEP, sd); | ||
412 | } | ||
413 | } | ||
414 | catch (Exception e) | ||
415 | { | ||
416 | // OpenPort(sd); // reopen the port just in case | ||
417 | m_log.ErrorFormat("[PROXY] EndReceiveFrom failed in {0}", sd.clientEP); | ||
418 | m_log.Error("[PROXY]" + e.Message); | ||
419 | m_log.Error("[PROXY]" + e.StackTrace); | ||
420 | } | ||
421 | |||
422 | WaitForNextMessage(sd); | ||
423 | } | ||
424 | |||
425 | protected void WaitForNextMessage(ServerData sd) | ||
426 | { | ||
427 | bool error = true; | ||
428 | while (error) | ||
429 | { | ||
430 | error = false; | ||
431 | try | ||
432 | { | ||
433 | sd.server.BeginReceiveFrom(sd.recvBuffer, 0, sd.recvBuffer.Length, SocketFlags.None, ref sd.senderEP, receivedData, sd); | ||
434 | } | ||
435 | catch (Exception e) | ||
436 | { | ||
437 | error = true; | ||
438 | m_log.ErrorFormat("[PROXY] BeginReceiveFrom failed, retrying... {0}", sd.clientEP); | ||
439 | m_log.Error("[PROXY]" + e.Message); | ||
440 | m_log.Error("[PROXY]" + e.StackTrace); | ||
441 | OpenPort(sd); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | protected void SendMessage(byte[] buffer, int length, EndPoint senderEP, ServerData sd) | ||
447 | { | ||
448 | int numBytes = length; | ||
449 | |||
450 | //m_log.ErrorFormat("[PROXY] Got message from {0} in thread {1}, size {2}", senderEP, sd.clientEP, numBytes); | ||
451 | EndPoint client = proxy_map.GetClient(senderEP); | ||
452 | |||
453 | if (client != null) | ||
454 | { | ||
455 | try | ||
456 | { | ||
457 | client = PacketPool.DecodeProxyMessage(buffer, ref numBytes); | ||
458 | try | ||
459 | { | ||
460 | // This message comes from a region object, forward it to the its client | ||
461 | sd.server.SendTo(buffer, numBytes, SocketFlags.None, client); | ||
462 | //m_log.InfoFormat("[PROXY] Sending region message from {0} to {1}, size {2}", senderEP, client, numBytes); | ||
463 | } | ||
464 | catch (Exception e) | ||
465 | { | ||
466 | OpenPort(sd); // reopen the port just in case | ||
467 | m_log.ErrorFormat("[PROXY] Failed sending region message from {0} to {1}", senderEP, client); | ||
468 | m_log.Error("[PROXY]" + e.Message); | ||
469 | m_log.Error("[PROXY]" + e.StackTrace); | ||
470 | return; | ||
471 | } | ||
472 | } | ||
473 | catch (Exception e) | ||
474 | { | ||
475 | OpenPort(sd); // reopen the port just in case | ||
476 | m_log.ErrorFormat("[PROXY] Failed decoding region message from {0}", senderEP); | ||
477 | m_log.Error("[PROXY]" + e.Message); | ||
478 | m_log.Error("[PROXY]" + e.StackTrace); | ||
479 | return; | ||
480 | } | ||
481 | |||
482 | } | ||
483 | else | ||
484 | { | ||
485 | // This message comes from a client object, forward it to the the region(s) | ||
486 | PacketPool.EncodeProxyMessage(buffer, ref numBytes, senderEP); | ||
487 | ProxyMap.RegionData rd = proxy_map.GetRegionData(sd.clientEP); | ||
488 | foreach (EndPoint region in rd.regions) | ||
489 | { | ||
490 | if(rd.isBlocked) { | ||
491 | rd.storedMessages.Enqueue(new StoredMessage(buffer, length, numBytes, senderEP, sd)); | ||
492 | } | ||
493 | else | ||
494 | { | ||
495 | try | ||
496 | { | ||
497 | sd.server.SendTo(buffer, numBytes, SocketFlags.None, region); | ||
498 | //m_log.InfoFormat("[PROXY] Sending client message from {0} to {1}", senderEP, region); | ||
499 | } | ||
500 | catch (Exception e) | ||
501 | { | ||
502 | OpenPort(sd); // reopen the port just in case | ||
503 | m_log.ErrorFormat("[PROXY] Failed sending client message from {0} to {1}", senderEP, region); | ||
504 | m_log.Error("[PROXY]" + e.Message); | ||
505 | m_log.Error("[PROXY]" + e.StackTrace); | ||
506 | return; | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | } | ||
511 | } | ||
512 | } | ||
513 | } | ||