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