aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim.RegionServer/ClientViewBase.cs
diff options
context:
space:
mode:
authorMW2007-05-21 16:06:58 +0000
committerMW2007-05-21 16:06:58 +0000
commitfe46b045f75dec5ecdd0a29273c70df3e6ea540e (patch)
tree554c0fb47e513fc6a89f496d99b7b67de24edde7 /OpenSim.RegionServer/ClientViewBase.cs
parentIncreased version number to 0.2! ZOMG! (diff)
downloadopensim-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/ClientViewBase.cs299
1 files changed, 299 insertions, 0 deletions
diff --git a/OpenSim.RegionServer/ClientViewBase.cs b/OpenSim.RegionServer/ClientViewBase.cs
new file mode 100644
index 0000000..814b025
--- /dev/null
+++ b/OpenSim.RegionServer/ClientViewBase.cs
@@ -0,0 +1,299 @@
1using System;
2using System.Collections;
3using System.Collections.Generic;
4using libsecondlife;
5using libsecondlife.Packets;
6using System.Net;
7using System.Net.Sockets;
8using System.IO;
9using System.Threading;
10using System.Timers;
11using OpenSim.Framework.Utilities;
12
13
14namespace OpenSim
15{
16 public class ClientViewBase
17 {
18 protected BlockingQueue<QueItem> PacketQueue;
19 protected Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
20 protected Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
21
22 protected System.Timers.Timer AckTimer;
23 protected uint Sequence = 0;
24 protected object SequenceLock = new object();
25 protected const int MAX_APPENDED_ACKS = 10;
26 protected const int RESEND_TIMEOUT = 4000;
27 protected const int MAX_SEQUENCE = 0xFFFFFF;
28
29 public uint CircuitCode;
30 public EndPoint userEP;
31
32 protected OpenSimNetworkHandler m_networkServer;
33
34 public ClientViewBase()
35 {
36
37 }
38
39 protected virtual void ProcessInPacket(Packet Pack)
40 {
41
42 }
43
44 protected virtual void ProcessOutPacket(Packet Pack)
45 {
46 // Keep track of when this packet was sent out
47 Pack.TickCount = Environment.TickCount;
48
49 if (!Pack.Header.Resent)
50 {
51 // Set the sequence number
52 lock (SequenceLock)
53 {
54 if (Sequence >= MAX_SEQUENCE)
55 Sequence = 1;
56 else
57 Sequence++;
58 Pack.Header.Sequence = Sequence;
59 }
60
61 if (Pack.Header.Reliable) //DIRTY HACK
62 {
63 lock (NeedAck)
64 {
65 if (!NeedAck.ContainsKey(Pack.Header.Sequence))
66 {
67 try
68 {
69 NeedAck.Add(Pack.Header.Sequence, Pack);
70 }
71 catch (Exception e) // HACKY
72 {
73 e.ToString();
74 // Ignore
75 // Seems to throw a exception here occasionally
76 // of 'duplicate key' despite being locked.
77 // !?!?!?
78 }
79 }
80 else
81 {
82 // Client.Log("Attempted to add a duplicate sequence number (" +
83 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
84 // packet.Type.ToString(), Helpers.LogLevel.Warning);
85 }
86 }
87
88 // Don't append ACKs to resent packets, in case that's what was causing the
89 // delivery to fail
90 if (!Pack.Header.Resent)
91 {
92 // Append any ACKs that need to be sent out to this packet
93 lock (PendingAcks)
94 {
95 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
96 Pack.Type != PacketType.PacketAck &&
97 Pack.Type != PacketType.LogoutRequest)
98 {
99 Pack.Header.AckList = new uint[PendingAcks.Count];
100 int i = 0;
101
102 foreach (uint ack in PendingAcks.Values)
103 {
104 Pack.Header.AckList[i] = ack;
105 i++;
106 }
107
108 PendingAcks.Clear();
109 Pack.Header.AppendedAcks = true;
110 }
111 }
112 }
113 }
114 }
115
116 byte[] ZeroOutBuffer = new byte[4096];
117 byte[] sendbuffer;
118 sendbuffer = Pack.ToBytes();
119
120 try
121 {
122 if (Pack.Header.Zerocoded)
123 {
124 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
125 m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
126 }
127 else
128 {
129 m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
130 }
131 }
132 catch (Exception)
133 {
134 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
135 this.KillThread();
136 }
137
138 }
139
140 public virtual void InPacket(Packet NewPack)
141 {
142 // Handle appended ACKs
143 if (NewPack.Header.AppendedAcks)
144 {
145 lock (NeedAck)
146 {
147 foreach (uint ack in NewPack.Header.AckList)
148 {
149 NeedAck.Remove(ack);
150 }
151 }
152 }
153
154 // Handle PacketAck packets
155 if (NewPack.Type == PacketType.PacketAck)
156 {
157 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
158
159 lock (NeedAck)
160 {
161 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
162 {
163 NeedAck.Remove(block.ID);
164 }
165 }
166 }
167 else if ((NewPack.Type == PacketType.StartPingCheck))
168 {
169 //reply to pingcheck
170 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
171 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
172 endPing.PingID.PingID = startPing.PingID.PingID;
173 OutPacket(endPing);
174 }
175 else
176 {
177 QueItem item = new QueItem();
178 item.Packet = NewPack;
179 item.Incoming = true;
180 this.PacketQueue.Enqueue(item);
181 }
182
183 }
184
185 public virtual void OutPacket(Packet NewPack)
186 {
187 QueItem item = new QueItem();
188 item.Packet = NewPack;
189 item.Incoming = false;
190 this.PacketQueue.Enqueue(item);
191 }
192
193 # region Low Level Packet Methods
194
195 protected void ack_pack(Packet Pack)
196 {
197 if (Pack.Header.Reliable)
198 {
199 libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
200 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
201 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
202 ack_it.Packets[0].ID = Pack.Header.Sequence;
203 ack_it.Header.Reliable = false;
204
205 OutPacket(ack_it);
206
207 }
208 /*
209 if (Pack.Header.Reliable)
210 {
211 lock (PendingAcks)
212 {
213 uint sequence = (uint)Pack.Header.Sequence;
214 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
215 }
216 }*/
217 }
218
219 protected void ResendUnacked()
220 {
221 int now = Environment.TickCount;
222
223 lock (NeedAck)
224 {
225 foreach (Packet packet in NeedAck.Values)
226 {
227 if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
228 {
229 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.VERBOSE, "Resending " + packet.Type.ToString() + " packet, " +
230 (now - packet.TickCount) + "ms have passed");
231
232 packet.Header.Resent = true;
233 OutPacket(packet);
234 }
235 }
236 }
237 }
238
239 protected void SendAcks()
240 {
241 lock (PendingAcks)
242 {
243 if (PendingAcks.Count > 0)
244 {
245 if (PendingAcks.Count > 250)
246 {
247 // FIXME: Handle the odd case where we have too many pending ACKs queued up
248 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.VERBOSE, "Too many ACKs queued up!");
249 return;
250 }
251
252 //OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck");
253
254
255 int i = 0;
256 PacketAckPacket acks = new PacketAckPacket();
257 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
258
259 foreach (uint ack in PendingAcks.Values)
260 {
261 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
262 acks.Packets[i].ID = ack;
263 i++;
264 }
265
266 acks.Header.Reliable = false;
267 OutPacket(acks);
268
269 PendingAcks.Clear();
270 }
271 }
272 }
273
274 protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
275 {
276 SendAcks();
277 ResendUnacked();
278 }
279 #endregion
280
281 protected virtual void KillThread()
282 {
283
284 }
285
286 #region Nested Classes
287
288 public class QueItem
289 {
290 public QueItem()
291 {
292 }
293
294 public Packet Packet;
295 public bool Incoming;
296 }
297 #endregion
298 }
299}