diff options
author | MW | 2007-05-21 16:06:58 +0000 |
---|---|---|
committer | MW | 2007-05-21 16:06:58 +0000 |
commit | fe46b045f75dec5ecdd0a29273c70df3e6ea540e (patch) | |
tree | 554c0fb47e513fc6a89f496d99b7b67de24edde7 /OpenSim.RegionServer/SimClient.cs | |
parent | Increased version number to 0.2! ZOMG! (diff) | |
download | opensim-SC-fe46b045f75dec5ecdd0a29273c70df3e6ea540e.zip opensim-SC-fe46b045f75dec5ecdd0a29273c70df3e6ea540e.tar.gz opensim-SC-fe46b045f75dec5ecdd0a29273c70df3e6ea540e.tar.bz2 opensim-SC-fe46b045f75dec5ecdd0a29273c70df3e6ea540e.tar.xz |
Start of a redesign of SimClient (now renamed ClientView)/World/Avatar/Prim , switching to a event based system (World/Avatar register as event handlers). It is possible that I've broke something with this commit but it doesn't matter as I'll just hide and no one will find me.
Diffstat (limited to '')
-rw-r--r-- | OpenSim.RegionServer/ClientView.cs (renamed from OpenSim.RegionServer/SimClient.cs) | 303 |
1 files changed, 31 insertions, 272 deletions
diff --git a/OpenSim.RegionServer/SimClient.cs b/OpenSim.RegionServer/ClientView.cs index 3b243cf..a97049d 100644 --- a/OpenSim.RegionServer/SimClient.cs +++ b/OpenSim.RegionServer/ClientView.cs | |||
@@ -44,43 +44,31 @@ using OpenSim.Assets; | |||
44 | 44 | ||
45 | namespace OpenSim | 45 | namespace OpenSim |
46 | { | 46 | { |
47 | public delegate bool PacketMethod(SimClient simClient, Packet packet); | 47 | public delegate bool PacketMethod(ClientView simClient, Packet packet); |
48 | 48 | ||
49 | /// <summary> | 49 | /// <summary> |
50 | /// Handles new client connections | 50 | /// Handles new client connections |
51 | /// Constructor takes a single Packet and authenticates everything | 51 | /// Constructor takes a single Packet and authenticates everything |
52 | /// </summary> | 52 | /// </summary> |
53 | public partial class SimClient | 53 | public partial class ClientView : ClientViewBase |
54 | { | 54 | { |
55 | public LLUUID AgentID; | 55 | public LLUUID AgentID; |
56 | public LLUUID SessionID; | 56 | public LLUUID SessionID; |
57 | public LLUUID SecureSessionID = LLUUID.Zero; | 57 | public LLUUID SecureSessionID = LLUUID.Zero; |
58 | public bool m_child; | 58 | public bool m_child; |
59 | public uint CircuitCode; | ||
60 | public world.Avatar ClientAvatar; | 59 | public world.Avatar ClientAvatar; |
61 | private UseCircuitCodePacket cirpack; | 60 | private UseCircuitCodePacket cirpack; |
62 | public Thread ClientThread; | 61 | public Thread ClientThread; |
63 | public EndPoint userEP; | ||
64 | public LLVector3 startpos; | 62 | public LLVector3 startpos; |
65 | private BlockingQueue<QueItem> PacketQueue; | 63 | |
66 | private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); | ||
67 | private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); | ||
68 | //private Dictionary<LLUUID, AssetBase> UploadedAssets = new Dictionary<LLUUID, AssetBase>(); | ||
69 | private System.Timers.Timer AckTimer; | ||
70 | private uint Sequence = 0; | ||
71 | private object SequenceLock = new object(); | ||
72 | private const int MAX_APPENDED_ACKS = 10; | ||
73 | private const int RESEND_TIMEOUT = 4000; | ||
74 | private const int MAX_SEQUENCE = 0xFFFFFF; | ||
75 | private AgentAssetUpload UploadAssets; | 64 | private AgentAssetUpload UploadAssets; |
76 | private LLUUID newAssetFolder = LLUUID.Zero; | 65 | private LLUUID newAssetFolder = LLUUID.Zero; |
77 | private bool debug = false; | 66 | private bool debug = false; |
78 | private World m_world; | 67 | private World m_world; |
79 | private Dictionary<uint, SimClient> m_clientThreads; | 68 | private Dictionary<uint, ClientView> m_clientThreads; |
80 | private AssetCache m_assetCache; | 69 | private AssetCache m_assetCache; |
81 | private IGridServer m_gridServer; | 70 | private IGridServer m_gridServer; |
82 | private IUserServer m_userServer = null; | 71 | private IUserServer m_userServer = null; |
83 | private OpenSimNetworkHandler m_networkServer; | ||
84 | private InventoryCache m_inventoryCache; | 72 | private InventoryCache m_inventoryCache; |
85 | public bool m_sandboxMode; | 73 | public bool m_sandboxMode; |
86 | private int cachedtextureserial = 0; | 74 | private int cachedtextureserial = 0; |
@@ -99,7 +87,7 @@ namespace OpenSim | |||
99 | } | 87 | } |
100 | } | 88 | } |
101 | 89 | ||
102 | public SimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, SimClient> clientThreads, AssetCache assetCache, IGridServer gridServer, OpenSimNetworkHandler application, InventoryCache inventoryCache, bool sandboxMode, bool child, RegionInfo regionDat, AuthenticateSessionsBase authenSessions) | 90 | public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, ClientView> clientThreads, AssetCache assetCache, IGridServer gridServer, OpenSimNetworkHandler application, InventoryCache inventoryCache, bool sandboxMode, bool child, RegionInfo regionDat, AuthenticateSessionsBase authenSessions) |
103 | { | 91 | { |
104 | m_world = world; | 92 | m_world = world; |
105 | m_clientThreads = clientThreads; | 93 | m_clientThreads = clientThreads; |
@@ -170,7 +158,7 @@ namespace OpenSim | |||
170 | kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; | 158 | kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; |
171 | kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); | 159 | kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); |
172 | kill.ObjectData[0].ID = this.ClientAvatar.localid; | 160 | kill.ObjectData[0].ID = this.ClientAvatar.localid; |
173 | foreach (SimClient client in m_clientThreads.Values) | 161 | foreach (ClientView client in m_clientThreads.Values) |
174 | { | 162 | { |
175 | client.OutPacket(kill); | 163 | client.OutPacket(kill); |
176 | } | 164 | } |
@@ -247,246 +235,6 @@ namespace OpenSim | |||
247 | 235 | ||
248 | # endregion | 236 | # endregion |
249 | 237 | ||
250 | # region Low Level Packet Methods | ||
251 | |||
252 | private void ack_pack(Packet Pack) | ||
253 | { | ||
254 | if (Pack.Header.Reliable) | ||
255 | { | ||
256 | libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); | ||
257 | ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; | ||
258 | ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); | ||
259 | ack_it.Packets[0].ID = Pack.Header.Sequence; | ||
260 | ack_it.Header.Reliable = false; | ||
261 | |||
262 | OutPacket(ack_it); | ||
263 | |||
264 | } | ||
265 | /* | ||
266 | if (Pack.Header.Reliable) | ||
267 | { | ||
268 | lock (PendingAcks) | ||
269 | { | ||
270 | uint sequence = (uint)Pack.Header.Sequence; | ||
271 | if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } | ||
272 | } | ||
273 | }*/ | ||
274 | } | ||
275 | |||
276 | private void ResendUnacked() | ||
277 | { | ||
278 | int now = Environment.TickCount; | ||
279 | |||
280 | lock (NeedAck) | ||
281 | { | ||
282 | foreach (Packet packet in NeedAck.Values) | ||
283 | { | ||
284 | if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent)) | ||
285 | { | ||
286 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.VERBOSE, "Resending " + packet.Type.ToString() + " packet, " + | ||
287 | (now - packet.TickCount) + "ms have passed"); | ||
288 | |||
289 | packet.Header.Resent = true; | ||
290 | OutPacket(packet); | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | private void SendAcks() | ||
297 | { | ||
298 | lock (PendingAcks) | ||
299 | { | ||
300 | if (PendingAcks.Count > 0) | ||
301 | { | ||
302 | if (PendingAcks.Count > 250) | ||
303 | { | ||
304 | // FIXME: Handle the odd case where we have too many pending ACKs queued up | ||
305 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.VERBOSE, "Too many ACKs queued up!"); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | //OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck"); | ||
310 | |||
311 | |||
312 | int i = 0; | ||
313 | PacketAckPacket acks = new PacketAckPacket(); | ||
314 | acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; | ||
315 | |||
316 | foreach (uint ack in PendingAcks.Values) | ||
317 | { | ||
318 | acks.Packets[i] = new PacketAckPacket.PacketsBlock(); | ||
319 | acks.Packets[i].ID = ack; | ||
320 | i++; | ||
321 | } | ||
322 | |||
323 | acks.Header.Reliable = false; | ||
324 | OutPacket(acks); | ||
325 | |||
326 | PendingAcks.Clear(); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) | ||
332 | { | ||
333 | SendAcks(); | ||
334 | ResendUnacked(); | ||
335 | } | ||
336 | |||
337 | # endregion | ||
338 | |||
339 | #region Packet Queue Processing | ||
340 | |||
341 | protected virtual void ProcessOutPacket(Packet Pack) | ||
342 | { | ||
343 | // Keep track of when this packet was sent out | ||
344 | Pack.TickCount = Environment.TickCount; | ||
345 | |||
346 | if (!Pack.Header.Resent) | ||
347 | { | ||
348 | // Set the sequence number | ||
349 | lock (SequenceLock) | ||
350 | { | ||
351 | if (Sequence >= MAX_SEQUENCE) | ||
352 | Sequence = 1; | ||
353 | else | ||
354 | Sequence++; | ||
355 | Pack.Header.Sequence = Sequence; | ||
356 | } | ||
357 | |||
358 | if (Pack.Header.Reliable) //DIRTY HACK | ||
359 | { | ||
360 | lock (NeedAck) | ||
361 | { | ||
362 | if (!NeedAck.ContainsKey(Pack.Header.Sequence)) | ||
363 | { | ||
364 | try | ||
365 | { | ||
366 | NeedAck.Add(Pack.Header.Sequence, Pack); | ||
367 | } | ||
368 | catch (Exception e) // HACKY | ||
369 | { | ||
370 | e.ToString(); | ||
371 | // Ignore | ||
372 | // Seems to throw a exception here occasionally | ||
373 | // of 'duplicate key' despite being locked. | ||
374 | // !?!?!? | ||
375 | } | ||
376 | } | ||
377 | else | ||
378 | { | ||
379 | // Client.Log("Attempted to add a duplicate sequence number (" + | ||
380 | // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + | ||
381 | // packet.Type.ToString(), Helpers.LogLevel.Warning); | ||
382 | } | ||
383 | } | ||
384 | |||
385 | // Don't append ACKs to resent packets, in case that's what was causing the | ||
386 | // delivery to fail | ||
387 | if (!Pack.Header.Resent) | ||
388 | { | ||
389 | // Append any ACKs that need to be sent out to this packet | ||
390 | lock (PendingAcks) | ||
391 | { | ||
392 | if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && | ||
393 | Pack.Type != PacketType.PacketAck && | ||
394 | Pack.Type != PacketType.LogoutRequest) | ||
395 | { | ||
396 | Pack.Header.AckList = new uint[PendingAcks.Count]; | ||
397 | int i = 0; | ||
398 | |||
399 | foreach (uint ack in PendingAcks.Values) | ||
400 | { | ||
401 | Pack.Header.AckList[i] = ack; | ||
402 | i++; | ||
403 | } | ||
404 | |||
405 | PendingAcks.Clear(); | ||
406 | Pack.Header.AppendedAcks = true; | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | byte[] ZeroOutBuffer = new byte[4096]; | ||
414 | byte[] sendbuffer; | ||
415 | sendbuffer = Pack.ToBytes(); | ||
416 | |||
417 | try | ||
418 | { | ||
419 | if (Pack.Header.Zerocoded) | ||
420 | { | ||
421 | int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); | ||
422 | m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP); | ||
423 | } | ||
424 | else | ||
425 | { | ||
426 | m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP); | ||
427 | } | ||
428 | } | ||
429 | catch (Exception) | ||
430 | { | ||
431 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); | ||
432 | ClientThread.Abort(); | ||
433 | } | ||
434 | |||
435 | } | ||
436 | |||
437 | public virtual void InPacket(Packet NewPack) | ||
438 | { | ||
439 | // Handle appended ACKs | ||
440 | if (NewPack.Header.AppendedAcks) | ||
441 | { | ||
442 | lock (NeedAck) | ||
443 | { | ||
444 | foreach (uint ack in NewPack.Header.AckList) | ||
445 | { | ||
446 | NeedAck.Remove(ack); | ||
447 | } | ||
448 | } | ||
449 | } | ||
450 | |||
451 | // Handle PacketAck packets | ||
452 | if (NewPack.Type == PacketType.PacketAck) | ||
453 | { | ||
454 | PacketAckPacket ackPacket = (PacketAckPacket)NewPack; | ||
455 | |||
456 | lock (NeedAck) | ||
457 | { | ||
458 | foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) | ||
459 | { | ||
460 | NeedAck.Remove(block.ID); | ||
461 | } | ||
462 | } | ||
463 | } | ||
464 | else if ((NewPack.Type == PacketType.StartPingCheck)) | ||
465 | { | ||
466 | //reply to pingcheck | ||
467 | libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; | ||
468 | libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); | ||
469 | endPing.PingID.PingID = startPing.PingID.PingID; | ||
470 | OutPacket(endPing); | ||
471 | } | ||
472 | else | ||
473 | { | ||
474 | QueItem item = new QueItem(); | ||
475 | item.Packet = NewPack; | ||
476 | item.Incoming = true; | ||
477 | this.PacketQueue.Enqueue(item); | ||
478 | } | ||
479 | |||
480 | } | ||
481 | |||
482 | public virtual void OutPacket(Packet NewPack) | ||
483 | { | ||
484 | QueItem item = new QueItem(); | ||
485 | item.Packet = NewPack; | ||
486 | item.Incoming = false; | ||
487 | this.PacketQueue.Enqueue(item); | ||
488 | } | ||
489 | |||
490 | protected virtual void ClientLoop() | 238 | protected virtual void ClientLoop() |
491 | { | 239 | { |
492 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "OpenSimClient.cs:ClientLoop() - Entered loop"); | 240 | OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "OpenSimClient.cs:ClientLoop() - Entered loop"); |
@@ -506,8 +254,6 @@ namespace OpenSim | |||
506 | } | 254 | } |
507 | } | 255 | } |
508 | 256 | ||
509 | #endregion | ||
510 | |||
511 | # region Setup | 257 | # region Setup |
512 | 258 | ||
513 | protected virtual void InitNewClient() | 259 | protected virtual void InitNewClient() |
@@ -556,6 +302,31 @@ namespace OpenSim | |||
556 | } | 302 | } |
557 | # endregion | 303 | # endregion |
558 | 304 | ||
305 | |||
306 | protected override void KillThread() | ||
307 | { | ||
308 | this.ClientThread.Abort(); | ||
309 | } | ||
310 | |||
311 | #region World/Avatar To Viewer Methods | ||
312 | |||
313 | public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID) | ||
314 | { | ||
315 | System.Text.Encoding enc = System.Text.Encoding.ASCII; | ||
316 | libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); | ||
317 | reply.ChatData.Audible = 1; | ||
318 | reply.ChatData.Message = message; | ||
319 | reply.ChatData.ChatType = type; | ||
320 | reply.ChatData.SourceType = 1; | ||
321 | reply.ChatData.Position = fromPos; | ||
322 | reply.ChatData.FromName = enc.GetBytes(fromName + "\0"); | ||
323 | reply.ChatData.OwnerID = fromAgentID; | ||
324 | reply.ChatData.SourceID = fromAgentID; | ||
325 | |||
326 | this.OutPacket(reply); | ||
327 | } | ||
328 | #endregion | ||
329 | |||
559 | #region Inventory Creation | 330 | #region Inventory Creation |
560 | private void SetupInventory(AuthenticateResponse sessionInfo) | 331 | private void SetupInventory(AuthenticateResponse sessionInfo) |
561 | { | 332 | { |
@@ -646,17 +417,5 @@ namespace OpenSim | |||
646 | } | 417 | } |
647 | #endregion | 418 | #endregion |
648 | 419 | ||
649 | #region Nested Classes | ||
650 | |||
651 | public class QueItem | ||
652 | { | ||
653 | public QueItem() | ||
654 | { | ||
655 | } | ||
656 | |||
657 | public Packet Packet; | ||
658 | public bool Incoming; | ||
659 | } | ||
660 | #endregion | ||
661 | } | 420 | } |
662 | } | 421 | } |