aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/ClientViewBase.cs
diff options
context:
space:
mode:
authorMW2007-06-27 15:28:52 +0000
committerMW2007-06-27 15:28:52 +0000
commit646bbbc84b8010e0dacbeed5342cdb045f46cc49 (patch)
tree770b34d19855363c3c113ab9a0af9a56d821d887 /OpenSim/Region/ClientStack/ClientViewBase.cs
downloadopensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.zip
opensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.gz
opensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.bz2
opensim-SC_OLD-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.xz
Some work on restructuring the namespaces / project names. Note this doesn't compile yet as not all the code has been changed to use the new namespaces. Am committing it now for feedback on the namespaces.
Diffstat (limited to 'OpenSim/Region/ClientStack/ClientViewBase.cs')
-rw-r--r--OpenSim/Region/ClientStack/ClientViewBase.cs327
1 files changed, 327 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/ClientViewBase.cs b/OpenSim/Region/ClientStack/ClientViewBase.cs
new file mode 100644
index 0000000..8b503f0
--- /dev/null
+++ b/OpenSim/Region/ClientStack/ClientViewBase.cs
@@ -0,0 +1,327 @@
1
2/*
3* Copyright (c) Contributors, http://www.openmetaverse.org/
4* See CONTRIBUTORS.TXT for a full list of copyright holders.
5*
6* Redistribution and use in source and binary forms, with or without
7* modification, are permitted provided that the following conditions are met:
8* * Redistributions of source code must retain the above copyright
9* notice, this list of conditions and the following disclaimer.
10* * Redistributions in binary form must reproduce the above copyright
11* notice, this list of conditions and the following disclaimer in the
12* documentation and/or other materials provided with the distribution.
13* * Neither the name of the OpenSim Project nor the
14* names of its contributors may be used to endorse or promote products
15* derived from this software without specific prior written permission.
16*
17* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
18* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
21* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*
28*/
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using libsecondlife;
33using libsecondlife.Packets;
34using System.Net;
35using System.Net.Sockets;
36using System.IO;
37using System.Threading;
38using System.Timers;
39using OpenSim.Framework.Utilities;
40using OpenSim.Framework.Interfaces;
41
42namespace OpenSim
43{
44 public class ClientViewBase
45 {
46 protected BlockingQueue<QueItem> PacketQueue;
47 protected Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
48 protected Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
49
50 protected System.Timers.Timer AckTimer;
51 protected uint Sequence = 0;
52 protected object SequenceLock = new object();
53 protected const int MAX_APPENDED_ACKS = 10;
54 protected const int RESEND_TIMEOUT = 4000;
55 protected const int MAX_SEQUENCE = 0xFFFFFF;
56
57 public uint CircuitCode;
58 public EndPoint userEP;
59
60 protected PacketServer m_networkServer;
61
62 public ClientViewBase()
63 {
64
65 }
66
67 protected virtual void ProcessInPacket(Packet Pack)
68 {
69
70 }
71
72 protected virtual void ProcessOutPacket(Packet Pack)
73 {
74 // Keep track of when this packet was sent out
75 Pack.TickCount = Environment.TickCount;
76
77 if (!Pack.Header.Resent)
78 {
79 // Set the sequence number
80 lock (SequenceLock)
81 {
82 if (Sequence >= MAX_SEQUENCE)
83 Sequence = 1;
84 else
85 Sequence++;
86 Pack.Header.Sequence = Sequence;
87 }
88
89 if (Pack.Header.Reliable) //DIRTY HACK
90 {
91 lock (NeedAck)
92 {
93 if (!NeedAck.ContainsKey(Pack.Header.Sequence))
94 {
95 try
96 {
97 NeedAck.Add(Pack.Header.Sequence, Pack);
98 }
99 catch (Exception e) // HACKY
100 {
101 e.ToString();
102 // Ignore
103 // Seems to throw a exception here occasionally
104 // of 'duplicate key' despite being locked.
105 // !?!?!?
106 }
107 }
108 else
109 {
110 // Client.Log("Attempted to add a duplicate sequence number (" +
111 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
112 // packet.Type.ToString(), Helpers.LogLevel.Warning);
113 }
114 }
115
116 // Don't append ACKs to resent packets, in case that's what was causing the
117 // delivery to fail
118 if (!Pack.Header.Resent)
119 {
120 // Append any ACKs that need to be sent out to this packet
121 lock (PendingAcks)
122 {
123 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
124 Pack.Type != PacketType.PacketAck &&
125 Pack.Type != PacketType.LogoutRequest)
126 {
127 Pack.Header.AckList = new uint[PendingAcks.Count];
128 int i = 0;
129
130 foreach (uint ack in PendingAcks.Values)
131 {
132 Pack.Header.AckList[i] = ack;
133 i++;
134 }
135
136 PendingAcks.Clear();
137 Pack.Header.AppendedAcks = true;
138 }
139 }
140 }
141 }
142 }
143
144 byte[] ZeroOutBuffer = new byte[4096];
145 byte[] sendbuffer;
146 sendbuffer = Pack.ToBytes();
147
148 try
149 {
150 if (Pack.Header.Zerocoded)
151 {
152 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
153 m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
154 }
155 else
156 {
157 m_networkServer.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
158 }
159 }
160 catch (Exception)
161 {
162 OpenSim.Framework.Console.MainLog.Instance.Warn("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
163 this.KillThread();
164 }
165
166 }
167
168 public virtual void InPacket(Packet NewPack)
169 {
170 // Handle appended ACKs
171 if (NewPack.Header.AppendedAcks)
172 {
173 lock (NeedAck)
174 {
175 foreach (uint ack in NewPack.Header.AckList)
176 {
177 NeedAck.Remove(ack);
178 }
179 }
180 }
181
182 // Handle PacketAck packets
183 if (NewPack.Type == PacketType.PacketAck)
184 {
185 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
186
187 lock (NeedAck)
188 {
189 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
190 {
191 NeedAck.Remove(block.ID);
192 }
193 }
194 }
195 else if ((NewPack.Type == PacketType.StartPingCheck))
196 {
197 //reply to pingcheck
198 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
199 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
200 endPing.PingID.PingID = startPing.PingID.PingID;
201 OutPacket(endPing);
202 }
203 else
204 {
205 QueItem item = new QueItem();
206 item.Packet = NewPack;
207 item.Incoming = true;
208 this.PacketQueue.Enqueue(item);
209 }
210
211 }
212
213 public virtual void OutPacket(Packet NewPack)
214 {
215 QueItem item = new QueItem();
216 item.Packet = NewPack;
217 item.Incoming = false;
218 this.PacketQueue.Enqueue(item);
219 }
220
221 # region Low Level Packet Methods
222
223 protected void ack_pack(Packet Pack)
224 {
225 if (Pack.Header.Reliable)
226 {
227 libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
228 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
229 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
230 ack_it.Packets[0].ID = Pack.Header.Sequence;
231 ack_it.Header.Reliable = false;
232
233 OutPacket(ack_it);
234
235 }
236 /*
237 if (Pack.Header.Reliable)
238 {
239 lock (PendingAcks)
240 {
241 uint sequence = (uint)Pack.Header.Sequence;
242 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
243 }
244 }*/
245 }
246
247 protected void ResendUnacked()
248 {
249 int now = Environment.TickCount;
250
251 lock (NeedAck)
252 {
253 foreach (Packet packet in NeedAck.Values)
254 {
255 if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
256 {
257 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Resending " + packet.Type.ToString() + " packet, " +
258 (now - packet.TickCount) + "ms have passed");
259
260 packet.Header.Resent = true;
261 OutPacket(packet);
262 }
263 }
264 }
265 }
266
267 protected void SendAcks()
268 {
269 lock (PendingAcks)
270 {
271 if (PendingAcks.Count > 0)
272 {
273 if (PendingAcks.Count > 250)
274 {
275 // FIXME: Handle the odd case where we have too many pending ACKs queued up
276 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Too many ACKs queued up!");
277 return;
278 }
279
280 //OpenSim.Framework.Console.MainLog.Instance.WriteLine("Sending PacketAck");
281
282
283 int i = 0;
284 PacketAckPacket acks = new PacketAckPacket();
285 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
286
287 foreach (uint ack in PendingAcks.Values)
288 {
289 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
290 acks.Packets[i].ID = ack;
291 i++;
292 }
293
294 acks.Header.Reliable = false;
295 OutPacket(acks);
296
297 PendingAcks.Clear();
298 }
299 }
300 }
301
302 protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
303 {
304 SendAcks();
305 ResendUnacked();
306 }
307 #endregion
308
309 protected virtual void KillThread()
310 {
311
312 }
313
314 #region Nested Classes
315
316 public class QueItem
317 {
318 public QueItem()
319 {
320 }
321
322 public Packet Packet;
323 public bool Incoming;
324 }
325 #endregion
326 }
327}