aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs
diff options
context:
space:
mode:
authorMW2008-07-21 15:13:34 +0000
committerMW2008-07-21 15:13:34 +0000
commitfb096dfbd54cfbcfa60be872cee1680eb521dd14 (patch)
treefdc6c3b4d5d15dfd03dc24138ada668e62af7562 /OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs
parentMantis#1801. Thank you kindly, Junta_Kohime for a patch that: (diff)
downloadopensim-SC_OLD-fb096dfbd54cfbcfa60be872cee1680eb521dd14.zip
opensim-SC_OLD-fb096dfbd54cfbcfa60be872cee1680eb521dd14.tar.gz
opensim-SC_OLD-fb096dfbd54cfbcfa60be872cee1680eb521dd14.tar.bz2
opensim-SC_OLD-fb096dfbd54cfbcfa60be872cee1680eb521dd14.tar.xz
added experimental packet tracker (LLPacketTracker.cs), which can be told to track a packet and if it hasn't been acked within a set time, trigger a IClientAPI event, that the application/scene can handle. Currently only terrain packet tracking is finished, Tracking for initial Prim packets (first full update for a prim) is being worked on. Future improvements would be to make it a more generic packet tracker with callback delegates instead of events.
Add a test event handler (which would fire after a minute if a terrain packet hadn't been acked) to scene to handle the OnUnackedTerrain event, which currently just resends the terrain patch. The idea of this packet tracking is for the region level application to be able to know if the client stack gave up on sending a packet.
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs234
1 files changed, 234 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs
new file mode 100644
index 0000000..e775a67
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketTracker.cs
@@ -0,0 +1,234 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using System.Threading;
5using libsecondlife;
6
7namespace OpenSim.Region.ClientStack.LindenUDP
8{
9
10 public class LLPacketTracker
11 {
12 public delegate void PacketAcked(uint sequenceNumber);
13 public event PacketAcked OnPacketAcked;
14
15 protected List<uint> m_beenAcked = new List<uint>();
16
17 protected TerrainPacketTracker[,] m_sentTerrainPackets = new TerrainPacketTracker[16, 16];
18 protected Dictionary<LLUUID, PrimPacketTracker> m_sendPrimPackets = new Dictionary<LLUUID, PrimPacketTracker>();
19
20 protected LLClientView m_parentClient;
21
22 public LLPacketTracker(LLClientView parent)
23 {
24 m_parentClient = parent;
25 OnPacketAcked += TerrainPacketAcked;
26 //OnPacketAcked += PrimPacketAcked;
27 }
28
29 public void PacketAck(uint sequenceNumber)
30 {
31 lock (m_beenAcked)
32 {
33 m_beenAcked.Add(sequenceNumber);
34 }
35 }
36
37 public void TrackTerrainPacket(uint sequenceNumber, int patchX, int patchY)
38 {
39 TerrainPacketTracker tracker = new TerrainPacketTracker();
40 tracker.X = patchX;
41 tracker.Y = patchY;
42 tracker.SeqNumber = sequenceNumber;
43 tracker.TimeSent = DateTime.Now;
44 lock (m_sentTerrainPackets)
45 {
46 m_sentTerrainPackets[patchX, patchY] = tracker;
47 }
48 }
49
50 public void TrackPrimPacket(uint sequenceNumber, LLUUID primID)
51 {
52 PrimPacketTracker tracker = new PrimPacketTracker();
53 tracker.PrimID = primID;
54 tracker.TimeSent = DateTime.Now;
55 tracker.SeqNumber = sequenceNumber;
56 lock (m_sendPrimPackets)
57 {
58 m_sendPrimPackets[primID] = tracker;
59 }
60 }
61
62 public void TerrainPacketCheck()
63 {
64 DateTime now = DateTime.Now;
65 List<TerrainPacketTracker> resendList = new List<TerrainPacketTracker>();
66 lock (m_sentTerrainPackets)
67 {
68 for (int y = 0; y < 16; y++)
69 {
70 for (int x = 0; x < 16; x++)
71 {
72 if (m_sentTerrainPackets[x, y] != null)
73 {
74 TerrainPacketTracker tracker = m_sentTerrainPackets[x, y];
75 if ((now - tracker.TimeSent) > TimeSpan.FromMinutes(1))
76 {
77 tracker.TimeSent = now;
78 m_sentTerrainPackets[x, y] = null;
79 resendList.Add(tracker);
80 }
81 }
82 }
83 }
84 }
85
86 foreach (TerrainPacketTracker tracker in resendList)
87 {
88 m_parentClient.TriggerTerrainUnackedEvent(tracker.X, tracker.Y);
89 }
90 }
91
92 public void PrimPacketCheck()
93 {
94 DateTime now = DateTime.Now;
95 List<PrimPacketTracker> resendList = new List<PrimPacketTracker>();
96 List<PrimPacketTracker> ackedList = new List<PrimPacketTracker>();
97
98 lock (m_sendPrimPackets)
99 {
100 foreach (PrimPacketTracker tracker in m_sendPrimPackets.Values)
101 {
102 if (tracker.Acked)
103 {
104 ackedList.Add(tracker);
105 }
106 else if (((now - tracker.TimeSent) > TimeSpan.FromMinutes(1)) && (!tracker.Acked))
107 {
108 resendList.Add(tracker);
109 }
110 }
111 }
112
113 foreach (PrimPacketTracker tracker in resendList)
114 {
115 lock (m_sendPrimPackets)
116 {
117 m_sendPrimPackets.Remove(tracker.PrimID);
118 }
119 //call event
120 Console.WriteLine("Prim packet not acked, " + tracker.PrimID.ToString());
121 }
122
123
124 RemovePrimTrackers(ackedList);
125 }
126
127 public void PrimTrackerCleanup()
128 {
129 List<PrimPacketTracker> ackedList = new List<PrimPacketTracker>();
130
131 lock (m_sendPrimPackets)
132 {
133 foreach (PrimPacketTracker tracker in m_sendPrimPackets.Values)
134 {
135 if (tracker.Acked)
136 {
137 ackedList.Add(tracker);
138 }
139 }
140 }
141 Thread.Sleep(15); //give a little bit of time for other code to access list before we lock it again
142
143 RemovePrimTrackers(ackedList);
144 }
145
146 protected void RemovePrimTrackers(List<PrimPacketTracker> ackedList)
147 {
148 lock (m_sendPrimPackets)
149 {
150 foreach (PrimPacketTracker tracker in ackedList)
151 {
152 m_sendPrimPackets.Remove(tracker.PrimID);
153 }
154 }
155 }
156
157 protected void TerrainPacketAcked(uint sequence)
158 {
159 lock (m_sentTerrainPackets)
160 {
161 for (int y = 0; y < 16; y++)
162 {
163 for (int x = 0; x < 16; x++)
164 {
165 if (m_sentTerrainPackets[x, y] != null)
166 {
167 if (m_sentTerrainPackets[x, y].SeqNumber == sequence)
168 {
169 m_sentTerrainPackets[x, y] = null;
170 return;
171 }
172 }
173 }
174 }
175 }
176 }
177
178 protected void PrimPacketAcked(uint sequence)
179 {
180 lock (m_sendPrimPackets)
181 {
182 foreach (PrimPacketTracker tracker in m_sendPrimPackets.Values)
183 {
184 if (tracker.SeqNumber == sequence)
185 {
186 tracker.Acked = true;
187 break;
188 }
189 }
190 }
191 }
192
193 public void Process()
194 {
195 List<uint> ackedPackets = null;
196 lock (m_beenAcked)
197 {
198 ackedPackets = new List<uint>(m_beenAcked);
199 m_beenAcked.Clear();
200 }
201
202 if (ackedPackets != null)
203 {
204 foreach (uint packetId in ackedPackets)
205 {
206 if (OnPacketAcked != null)
207 {
208 OnPacketAcked(packetId);
209 }
210 }
211 }
212
213 // ackedPackets.Clear();
214 ackedPackets = null;
215 }
216
217 public class TerrainPacketTracker
218 {
219 public uint SeqNumber = 0;
220 public int X;
221 public int Y;
222 public DateTime TimeSent;
223
224 }
225
226 public class PrimPacketTracker
227 {
228 public uint SeqNumber = 0;
229 public DateTime TimeSent;
230 public LLUUID PrimID;
231 public bool Acked = false;
232 }
233 }
234}