aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim.RegionServer/SimComms.cs
diff options
context:
space:
mode:
authorgareth2007-04-17 10:53:50 +0000
committergareth2007-04-17 10:53:50 +0000
commit3e86870f7f1eb3d90089d41f8669fbd22d2e50d4 (patch)
tree5e04e36b7725227e95618933a2850898504a12fc /OpenSim.RegionServer/SimComms.cs
parentSim crossing now works (except for broken co-ordinates, resets to 0,0 - to be... (diff)
downloadopensim-SC_OLD-3e86870f7f1eb3d90089d41f8669fbd22d2e50d4.zip
opensim-SC_OLD-3e86870f7f1eb3d90089d41f8669fbd22d2e50d4.tar.gz
opensim-SC_OLD-3e86870f7f1eb3d90089d41f8669fbd22d2e50d4.tar.bz2
opensim-SC_OLD-3e86870f7f1eb3d90089d41f8669fbd22d2e50d4.tar.xz
Created skeleton SimComms.cs for sim<->sim UDP circuits
Fixed bug with <0,0> co-ordinates on sim crossing
Diffstat (limited to '')
-rw-r--r--OpenSim.RegionServer/SimComms.cs437
1 files changed, 437 insertions, 0 deletions
diff --git a/OpenSim.RegionServer/SimComms.cs b/OpenSim.RegionServer/SimComms.cs
new file mode 100644
index 0000000..a2b936b
--- /dev/null
+++ b/OpenSim.RegionServer/SimComms.cs
@@ -0,0 +1,437 @@
1/*
2Copyright (c) OpenSim project, http://osgrid.org/
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above copyright
9* notice, this list of conditions and the following disclaimer in the
10* documentation and/or other materials provided with the distribution.
11* * Neither the name of the <organization> nor the
12* names of its contributors may be used to endorse or promote products
13* derived from this software without specific prior written permission.
14*
15* THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
19* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*/
26
27using System;
28using System.Collections;
29using System.Collections.Generic;
30using libsecondlife;
31using libsecondlife.Packets;
32using Nwc.XmlRpc;
33using System.Net;
34using System.Net.Sockets;
35using System.IO;
36using System.Threading;
37using System.Timers;
38using OpenSim.Framework.Interfaces;
39using OpenSim.Framework.Assets;
40using OpenSim.Framework.Inventory;
41using OpenSim.Framework.Utilities;
42using OpenSim.world;
43using OpenSim.Assets;
44
45namespace OpenSim
46{
47 public delegate bool PacketMethod(SimComms remoteSim, Packet packet);
48
49 /// <summary>
50 /// Handles sim<->sim communications
51 /// Constructor takes a single Packet and authenticates everything
52 /// </summary>
53 public class SimComms
54 {
55 public LLUUID SimUUID;
56 public bool m_child;
57 public uint CircuitCode;
58 private UseCircuitCodePacket cirpack;
59 public Thread ClientThread;
60 public EndPoint simEP;
61 private BlockingQueue<QueItem> PacketQueue;
62 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
63 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
64 private System.Timers.Timer AckTimer;
65 private uint Sequence = 0;
66 private object SequenceLock = new object();
67 private const int MAX_APPENDED_ACKS = 10;
68 private const int RESEND_TIMEOUT = 4000;
69 private const int MAX_SEQUENCE = 0xFFFFFF;
70 private bool debug = false;
71 private World m_world;
72 private Dictionary<uint, SimComms> m_simThreads;
73 private IGridServer m_gridServer;
74 private IUserServer m_userServer = null;
75 private OpenSimNetworkHandler m_application;
76 //private bool m_sandboxMode; // I can think of no reason why we'd ever have this set in sandbox mode
77
78 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all sims
79
80 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); //local handlers for this instance
81
82 public IUserServer UserServer
83 {
84 set
85 {
86 this.m_userServer = value;
87 }
88 }
89
90 public SimComms(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, SimComms> simThreads, IGridServer gridServer, OpenSimNetworkHandler application)
91 {
92 m_world = world;
93 m_clientThreads = clientThreads;
94 m_gridServer = gridServer;
95 m_application = application;
96
97 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("SimComms.cs - Started up new thread to handle incoming request");
98 cirpack = initialcirpack;
99 simEP = remoteEP;
100
101 PacketQueue = new BlockingQueue<QueItem>();
102
103 AckTimer = new System.Timers.Timer(500);
104 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
105 AckTimer.Start();
106
107 this.RegisterLocalPacketHandlers();
108
109 ClientThread = new Thread(new ThreadStart(AuthUser));
110 ClientThread.IsBackground = true;
111 ClientThread.Start();
112 }
113
114 protected virtual void RegisterLocalPacketHandlers()
115 {
116/* this.AddLocalPacketHandler(PacketType.LogoutRequest, this.Logout);
117 this.AddLocalPacketHandler(PacketType.AgentCachedTexture, this.AgentTextureCached);
118 this.AddLocalPacketHandler(PacketType.MultipleObjectUpdate, this.MultipleObjUpdate);*/
119 }
120
121 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
122 {
123 bool result = false;
124 lock (PacketHandlers)
125 {
126 if (!PacketHandlers.ContainsKey(packetType))
127 {
128 PacketHandlers.Add(packetType, handler);
129 result = true;
130 }
131 }
132 return result;
133 }
134
135 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
136 {
137 bool result = false;
138 lock (m_packetHandlers)
139 {
140 if (!m_packetHandlers.ContainsKey(packetType))
141 {
142 m_packetHandlers.Add(packetType, handler);
143 result = true;
144 }
145 }
146 return result;
147 }
148
149 protected virtual bool ProcessPacketMethod(Packet packet)
150 {
151 bool result = false;
152 bool found = false;
153 PacketMethod method;
154 if (m_packetHandlers.TryGetValue(packet.Type, out method))
155 {
156 //there is a local handler for this packet type
157 result = method(this, packet);
158 }
159 else
160 {
161 //there is not a local handler so see if there is a Global handler
162 lock (PacketHandlers)
163 {
164 found = PacketHandlers.TryGetValue(packet.Type, out method);
165 }
166 if (found)
167 {
168 result = method(this, packet);
169 }
170 }
171 return result;
172 }
173
174 private void ack_pack(Packet Pack)
175 {
176 if (Pack.Header.Reliable)
177 {
178 libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
179 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
180 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
181 ack_it.Packets[0].ID = Pack.Header.Sequence;
182 ack_it.Header.Reliable = false;
183
184 OutPacket(ack_it);
185
186 }
187 /*
188 if (Pack.Header.Reliable)
189 {
190 lock (PendingAcks)
191 {
192 uint sequence = (uint)Pack.Header.Sequence;
193 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
194 }
195 }*/
196 }
197
198 protected virtual void ProcessInPacket(Packet Pack)
199 {
200 ack_pack(Pack);
201
202 if (this.ProcessPacketMethod(Pack))
203 {
204 //there is a handler registered that handled this packet type
205 return;
206 }
207 else
208 {
209 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
210
211 switch (Pack.Type)
212 {
213 }
214 }
215 }
216
217 private void ResendUnacked()
218 {
219 int now = Environment.TickCount;
220
221 lock (NeedAck)
222 {
223 foreach (Packet packet in NeedAck.Values)
224 {
225 if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
226 {
227 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Resending " + packet.Type.ToString() + " packet, " +
228 (now - packet.TickCount) + "ms have passed");
229
230 packet.Header.Resent = true;
231 OutPacket(packet);
232 }
233 }
234 }
235 }
236
237 private void SendAcks()
238 {
239 lock (PendingAcks)
240 {
241 if (PendingAcks.Count > 0)
242 {
243 if (PendingAcks.Count > 250)
244 {
245 // FIXME: Handle the odd case where we have too many pending ACKs queued up
246 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Too many ACKs queued up!");
247 return;
248 }
249
250 //OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck");
251
252
253 int i = 0;
254 PacketAckPacket acks = new PacketAckPacket();
255 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
256
257 foreach (uint ack in PendingAcks.Values)
258 {
259 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
260 acks.Packets[i].ID = ack;
261 i++;
262 }
263
264 acks.Header.Reliable = false;
265 OutPacket(acks);
266
267 PendingAcks.Clear();
268 }
269 }
270 }
271
272 private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
273 {
274 SendAcks();
275 ResendUnacked();
276 }
277
278 protected virtual void ProcessOutPacket(Packet Pack)
279 {
280
281 // Keep track of when this packet was sent out
282 Pack.TickCount = Environment.TickCount;
283
284 if (!Pack.Header.Resent)
285 {
286 // Set the sequence number
287 lock (SequenceLock)
288 {
289 if (Sequence >= MAX_SEQUENCE)
290 Sequence = 1;
291 else
292 Sequence++;
293 Pack.Header.Sequence = Sequence;
294 }
295
296 if (Pack.Header.Reliable) //DIRTY HACK
297 {
298 lock (NeedAck)
299 {
300 if (!NeedAck.ContainsKey(Pack.Header.Sequence))
301 {
302 NeedAck.Add(Pack.Header.Sequence, Pack);
303 }
304 else
305 {
306 // Client.Log("Attempted to add a duplicate sequence number (" +
307 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
308 // packet.Type.ToString(), Helpers.LogLevel.Warning);
309 }
310 }
311
312 // Don't append ACKs to resent packets, in case that's what was causing the
313 // delivery to fail
314 if (!Pack.Header.Resent)
315 {
316 // Append any ACKs that need to be sent out to this packet
317 lock (PendingAcks)
318 {
319 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
320 Pack.Type != PacketType.PacketAck &&
321 Pack.Type != PacketType.LogoutRequest)
322 {
323 Pack.Header.AckList = new uint[PendingAcks.Count];
324 int i = 0;
325
326 foreach (uint ack in PendingAcks.Values)
327 {
328 Pack.Header.AckList[i] = ack;
329 i++;
330 }
331
332 PendingAcks.Clear();
333 Pack.Header.AppendedAcks = true;
334 }
335 }
336 }
337 }
338 }
339
340 byte[] ZeroOutBuffer = new byte[4096];
341 byte[] sendbuffer;
342 sendbuffer = Pack.ToBytes();
343
344 try
345 {
346 if (Pack.Header.Zerocoded)
347 {
348 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
349 m_application.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
350 }
351 else
352 {
353 m_application.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
354 }
355 }
356 catch (Exception)
357 {
358 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("SimComms.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + simEP.ToString() + " - killing thread");
359 ClientThread.Abort();
360 }
361
362 }
363
364 public virtual void InPacket(Packet NewPack)
365 {
366 // Handle appended ACKs
367 if (NewPack.Header.AppendedAcks)
368 {
369 lock (NeedAck)
370 {
371 foreach (uint ack in NewPack.Header.AckList)
372 {
373 NeedAck.Remove(ack);
374 }
375 }
376 }
377
378 // Handle PacketAck packets
379 if (NewPack.Type == PacketType.PacketAck)
380 {
381 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
382
383 lock (NeedAck)
384 {
385 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
386 {
387 NeedAck.Remove(block.ID);
388 }
389 }
390 }
391 else if ((NewPack.Type == PacketType.StartPingCheck))
392 {
393 //reply to pingcheck
394 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
395 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
396 endPing.PingID.PingID = startPing.PingID.PingID;
397 OutPacket(endPing);
398 }
399 else
400 {
401 QueItem item = new QueItem();
402 item.Packet = NewPack;
403 item.Incoming = true;
404 this.PacketQueue.Enqueue(item);
405 }
406
407 }
408
409 public virtual void OutPacket(Packet NewPack)
410 {
411 QueItem item = new QueItem();
412 item.Packet = NewPack;
413 item.Incoming = false;
414 this.PacketQueue.Enqueue(item);
415 }
416
417 protected virtual void ClientLoop()
418 {
419 OpenSim.Framework.Console.MainConsole.Instance.WriteLine("SimComms.cs:ClientLoop() - Entered loop");
420 while (true)
421 {
422 QueItem nextPacket = PacketQueue.Dequeue();
423 if (nextPacket.Incoming)
424 {
425 //is a incoming packet
426 ProcessInPacket(nextPacket.Packet);
427 }
428 else
429 {
430 //is a out going packet
431 ProcessOutPacket(nextPacket.Packet);
432 }
433 }
434 }
435
436 }
437}