aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/OpenSimClient.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/OpenSimClient.cs889
1 files changed, 469 insertions, 420 deletions
diff --git a/src/OpenSimClient.cs b/src/OpenSimClient.cs
index 655ebfe..497df00 100644
--- a/src/OpenSimClient.cs
+++ b/src/OpenSimClient.cs
@@ -37,425 +37,474 @@ using System.Timers;
37 37
38namespace OpenSim 38namespace OpenSim
39{ 39{
40 /// <summary> 40 /// <summary>
41 /// Handles new client connections 41 /// Handles new client connections
42 /// Constructor takes a single Packet and authenticates everything 42 /// Constructor takes a single Packet and authenticates everything
43 /// </summary> 43 /// </summary>
44 public class OpenSimClient { 44 public class OpenSimClient
45 45 {
46 public LLUUID AgentID; 46
47 public LLUUID SessionID; 47 public LLUUID AgentID;
48 public uint CircuitCode; 48 public LLUUID SessionID;
49 public world.Avatar ClientAvatar; 49 public uint CircuitCode;
50 private UseCircuitCodePacket cirpack; 50 public world.Avatar ClientAvatar;
51 private Thread ClientThread; 51 private UseCircuitCodePacket cirpack;
52 public EndPoint userEP; 52 private Thread ClientThread;
53 private BlockingQueue<QueItem> PacketQueue; 53 public EndPoint userEP;
54 private BlockingQueue<TransferRequestPacket> AssetRequests; 54 private BlockingQueue<QueItem> PacketQueue;
55 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); 55 private BlockingQueue<TransferRequestPacket> AssetRequests;
56 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); 56 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
57 private System.Timers.Timer AckTimer; 57 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
58 private uint Sequence = 0; 58 private System.Timers.Timer AckTimer;
59 private object SequenceLock = new object(); 59 private uint Sequence = 0;
60 private const int MAX_APPENDED_ACKS = 10; 60 private object SequenceLock = new object();
61 private const int RESEND_TIMEOUT = 4000; 61 private const int MAX_APPENDED_ACKS = 10;
62 private const int MAX_SEQUENCE = 0xFFFFFF; 62 private const int RESEND_TIMEOUT = 4000;
63 private Queue<uint> Inbox; 63 private const int MAX_SEQUENCE = 0xFFFFFF;
64 64 //private Queue<uint> Inbox;
65 public void ack_pack(Packet Pack) { 65
66 //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); 66 public void ack_pack(Packet Pack)
67 //ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; 67 {
68 //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); 68 //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
69 //ack_it.Packets[0].ID = Pack.Header.ID; 69 //ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
70 //ack_it.Header.Reliable = false; 70 //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
71 71 //ack_it.Packets[0].ID = Pack.Header.ID;
72 //OutPacket(ack_it); 72 //ack_it.Header.Reliable = false;
73 73
74 if (Pack.Header.Reliable) { 74 //OutPacket(ack_it);
75 lock (PendingAcks) { 75
76 uint sequence = (uint)Pack.Header.Sequence; 76 if (Pack.Header.Reliable)
77 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } 77 {
78 } 78 lock (PendingAcks)
79 } 79 {
80 } 80 uint sequence = (uint)Pack.Header.Sequence;
81 81 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
82 public void AssetLoader() { 82 }
83 if(OpenSim_Main.cfg.sandbox==false) { 83 }
84 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread"); 84 }
85 TransferRequestPacket reqPacket = AssetRequests.Dequeue(); 85
86 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it"); 86 public void AssetLoader()
87 LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0); 87 {
88 WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data"); 88 if (OpenSim_Main.cfg.sandbox == false)
89 WebResponse AssetResponse = AssetLoad.GetResponse(); 89 {
90 byte[] idata = new byte[(int)AssetResponse.ContentLength]; 90 WebResponse AssetResponse;
91 BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream()); 91 byte[] idata;
92 idata = br.ReadBytes((int)AssetResponse.ContentLength); 92
93 br.Close(); 93 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread");
94 94 TransferRequestPacket reqPacket = AssetRequests.Dequeue();
95 TransferInfoPacket Transfer = new TransferInfoPacket(); 95 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it");
96 Transfer.TransferInfo.ChannelType = 2; 96 LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0);
97 Transfer.TransferInfo.Status = 0; 97
98 Transfer.TransferInfo.TargetType = 0; 98 try
99 Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params; 99 {
100 Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength; 100 WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data");
101 Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID; 101 AssetResponse = AssetLoad.GetResponse();
102 102 idata = new byte[(int)AssetResponse.ContentLength];
103 OutPacket(Transfer); 103 BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream());
104 104 idata = br.ReadBytes((int)AssetResponse.ContentLength);
105 TransferPacketPacket TransferPacket = new TransferPacketPacket(); 105 br.Close();
106 TransferPacket.TransferData.Packet = 0; 106 }
107 TransferPacket.TransferData.ChannelType = 2; 107 catch (Exception e)
108 TransferPacket.TransferData.TransferID=reqPacket.TransferInfo.TransferID; 108 {
109 109 Console.WriteLine(e.ToString());
110 if(AssetResponse.ContentLength>1000) { 110 return;
111 byte[] chunk = new byte[1000]; 111 }
112 Array.Copy(idata,chunk,1000); 112
113 TransferPacket.TransferData.Data = chunk; 113 TransferInfoPacket Transfer = new TransferInfoPacket();
114 TransferPacket.TransferData.Status = 0; 114 Transfer.TransferInfo.ChannelType = 2;
115 OutPacket(TransferPacket); 115 Transfer.TransferInfo.Status = 0;
116 116 Transfer.TransferInfo.TargetType = 0;
117 TransferPacket = new TransferPacketPacket(); 117 Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params;
118 TransferPacket.TransferData.Packet = 1; 118 Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength;
119 TransferPacket.TransferData.ChannelType = 2; 119 Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID;
120 TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; 120
121 byte[] chunk1 = new byte[(idata.Length-1000)]; 121 OutPacket(Transfer);
122 Array.Copy(idata, 1000, chunk1, 0, chunk1.Length); 122
123 TransferPacket.TransferData.Data = chunk1; 123 TransferPacketPacket TransferPacket = new TransferPacketPacket();
124 TransferPacket.TransferData.Status = 1; 124 TransferPacket.TransferData.Packet = 0;
125 OutPacket(TransferPacket); 125 TransferPacket.TransferData.ChannelType = 2;
126 } else { 126 TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID;
127 TransferPacket.TransferData.Status = 1; 127
128 TransferPacket.TransferData.Data = idata; 128 if (AssetResponse.ContentLength > 1000)
129 OutPacket(TransferPacket); 129 {
130 } 130 byte[] chunk = new byte[1000];
131 AssetResponse.Close(); 131 Array.Copy(idata, chunk, 1000);
132 } 132 TransferPacket.TransferData.Data = chunk;
133 } 133 TransferPacket.TransferData.Status = 0;
134 134 OutPacket(TransferPacket);
135 public void Logout() { 135
136 // TODO - kill any AssetLoaders 136 TransferPacket = new TransferPacketPacket();
137 ClientThread.Abort(); 137 TransferPacket.TransferData.Packet = 1;
138 } 138 TransferPacket.TransferData.ChannelType = 2;
139 139 TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID;
140 public void ProcessInPacket(Packet Pack) { 140 byte[] chunk1 = new byte[(idata.Length - 1000)];
141 ack_pack(Pack); 141 Array.Copy(idata, 1000, chunk1, 0, chunk1.Length);
142 switch(Pack.Type) { 142 TransferPacket.TransferData.Data = chunk1;
143 case PacketType.CompleteAgentMovement: 143 TransferPacket.TransferData.Status = 1;
144 ClientAvatar.CompleteMovement(OpenSim_Main.local_world); 144 OutPacket(TransferPacket);
145 ClientAvatar.SendInitialPosition(); 145 }
146 break; 146 else
147 case PacketType.RegionHandshakeReply: 147 {
148 OpenSim_Main.local_world.SendLayerData(this); 148 TransferPacket.TransferData.Status = 1;
149 break; 149 TransferPacket.TransferData.Data = idata;
150 case PacketType.AgentWearablesRequest: 150 OutPacket(TransferPacket);
151 ClientAvatar.SendInitialAppearance(); 151 }
152 break; 152 AssetResponse.Close();
153 case PacketType.TransferRequest: 153 }
154 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request"); 154 }
155 // We put transfer requests into a big queue and then spawn a thread for each new one 155
156 TransferRequestPacket transfer = (TransferRequestPacket)Pack; 156 public void Logout()
157 AssetRequests.Enqueue(transfer); 157 {
158 Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader)); 158 // TODO - kill any AssetLoaders
159 AssetLoaderThread.Start(); 159 ClientThread.Abort();
160 break; 160 }
161 case PacketType.LogoutRequest: 161
162 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request"); 162 public void ProcessInPacket(Packet Pack)
163 lock(OpenSim_Main.local_world.Entities) { 163 {
164 OpenSim_Main.local_world.Entities.Remove(this.AgentID); 164 ack_pack(Pack);
165 } 165 switch (Pack.Type)
166 166 {
167 if(OpenSim_Main.cfg.sandbox==false) { 167 case PacketType.CompleteAgentMovement:
168 WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete"); 168 ClientAvatar.CompleteMovement(OpenSim_Main.local_world);
169 WebResponse GridResponse = DeleteSession.GetResponse(); 169 ClientAvatar.SendInitialPosition();
170 StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); 170 break;
171 String grTest = sr.ReadLine(); 171 case PacketType.RegionHandshakeReply:
172 sr.Close(); 172 OpenSim_Main.local_world.SendLayerData(this);
173 GridResponse.Close(); 173 break;
174 OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest); 174 case PacketType.AgentWearablesRequest:
175 } 175 ClientAvatar.SendInitialAppearance();
176 this.ClientThread.Abort(); 176 break;
177 break; 177 case PacketType.TransferRequest:
178 case PacketType.AgentUpdate: 178 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request");
179 ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack); 179 // We put transfer requests into a big queue and then spawn a thread for each new one
180 break; 180 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
181 case PacketType.ChatFromViewer: 181 AssetRequests.Enqueue(transfer);
182 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; 182 Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader));
183 if(Helpers.FieldToString(inchatpack.ChatData.Message)=="") break; 183 AssetLoaderThread.Start();
184 184 break;
185 System.Text.Encoding _enc = System.Text.Encoding.ASCII; 185 case PacketType.LogoutRequest:
186 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); 186 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request");
187 reply.ChatData.Audible = 1; 187 lock (OpenSim_Main.local_world.Entities)
188 reply.ChatData.Message = inchatpack.ChatData.Message; 188 {
189 reply.ChatData.ChatType = 1; 189 OpenSim_Main.local_world.Entities.Remove(this.AgentID);
190 reply.ChatData.SourceType = 1; 190 }
191 reply.ChatData.Position = this.ClientAvatar.position; 191
192 reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0"); 192 if (OpenSim_Main.cfg.sandbox == false)
193 reply.ChatData.OwnerID = this.AgentID; 193 {
194 reply.ChatData.SourceID = this.AgentID; 194 WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete");
195 195 WebResponse GridResponse = DeleteSession.GetResponse();
196 196 StreamReader sr = new StreamReader(GridResponse.GetResponseStream());
197 197 String grTest = sr.ReadLine();
198 foreach(OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) { 198 sr.Close();
199 client.OutPacket(reply); 199 GridResponse.Close();
200 } 200 OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest);
201 break; 201 }
202 } 202 this.ClientThread.Abort();
203 } 203 break;
204 204 case PacketType.AgentUpdate:
205 private void ResendUnacked() 205 ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack);
206 { 206 break;
207 int now = Environment.TickCount; 207 case PacketType.ChatFromViewer:
208 208 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
209 lock (NeedAck) 209 if (Helpers.FieldToString(inchatpack.ChatData.Message) == "") break;
210 { 210
211 foreach (Packet packet in NeedAck.Values) 211 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
212 { 212 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket();
213 if (now - packet.TickCount > RESEND_TIMEOUT) 213 reply.ChatData.Audible = 1;
214 { 214 reply.ChatData.Message = inchatpack.ChatData.Message;
215 215 reply.ChatData.ChatType = 1;
216 packet.Header.Resent = true; 216 reply.ChatData.SourceType = 1;
217 OutPacket(packet); 217 reply.ChatData.Position = this.ClientAvatar.position;
218 } 218 reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0");
219 } 219 reply.ChatData.OwnerID = this.AgentID;
220 } 220 reply.ChatData.SourceID = this.AgentID;
221 } 221
222 222
223 private void SendAcks() 223
224 { 224 foreach (OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values)
225 lock (PendingAcks) 225 {
226 { 226 client.OutPacket(reply);
227 if (PendingAcks.Count > 0) 227 }
228 { 228 break;
229 if (PendingAcks.Count > 250) 229 }
230 { 230 }
231 return; 231
232 } 232 private void ResendUnacked()
233 233 {
234 234 int now = Environment.TickCount;
235 235
236 int i = 0; 236 lock (NeedAck)
237 PacketAckPacket acks = new PacketAckPacket(); 237 {
238 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; 238 foreach (Packet packet in NeedAck.Values)
239 239 {
240 foreach (uint ack in PendingAcks.Values) 240 if (now - packet.TickCount > RESEND_TIMEOUT)
241 { 241 {
242 acks.Packets[i] = new PacketAckPacket.PacketsBlock(); 242
243 acks.Packets[i].ID = ack; 243 packet.Header.Resent = true;
244 i++; 244 OutPacket(packet);
245 } 245 }
246 246 }
247 acks.Header.Reliable = false; 247 }
248 OutPacket(acks); 248 }
249 249
250 PendingAcks.Clear(); 250 private void SendAcks()
251 } 251 {
252 } 252 lock (PendingAcks)
253 } 253 {
254 254 if (PendingAcks.Count > 0)
255 private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) 255 {
256 { 256 if (PendingAcks.Count > 250)
257 SendAcks(); 257 {
258 ResendUnacked(); 258 return;
259 } 259 }
260 260
261 public void ProcessOutPacket(Packet Pack) { 261
262 262
263 // Keep track of when this packet was sent out 263 int i = 0;
264 Pack.TickCount = Environment.TickCount; 264 PacketAckPacket acks = new PacketAckPacket();
265 265 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
266 if (!Pack.Header.Resent) 266
267 { 267 foreach (uint ack in PendingAcks.Values)
268 // Set the sequence number 268 {
269 lock (SequenceLock) 269 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
270 { 270 acks.Packets[i].ID = ack;
271 if (Sequence >= MAX_SEQUENCE) 271 i++;
272 Sequence = 1; 272 }
273 else 273
274 Sequence++; 274 acks.Header.Reliable = false;
275 Pack.Header.Sequence = Sequence; 275 OutPacket(acks);
276 } 276
277 277 PendingAcks.Clear();
278 if (Pack.Header.Reliable) //DIRTY HACK 278 }
279 { 279 }
280 lock (NeedAck) 280 }
281 { 281
282 if (!NeedAck.ContainsKey(Pack.Header.Sequence)) 282 private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
283 { 283 {
284 NeedAck.Add(Pack.Header.Sequence, Pack); 284 SendAcks();
285 } 285 ResendUnacked();
286 else 286 }
287 { 287
288 // Client.Log("Attempted to add a duplicate sequence number (" + 288 public void ProcessOutPacket(Packet Pack)
289 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + 289 {
290 // packet.Type.ToString(), Helpers.LogLevel.Warning); 290
291 } 291 // Keep track of when this packet was sent out
292 } 292 Pack.TickCount = Environment.TickCount;
293 293
294 // Don't append ACKs to resent packets, in case that's what was causing the 294 if (!Pack.Header.Resent)
295 // delivery to fail 295 {
296 if (!Pack.Header.Resent) 296 // Set the sequence number
297 { 297 lock (SequenceLock)
298 // Append any ACKs that need to be sent out to this packet 298 {
299 lock (PendingAcks) 299 if (Sequence >= MAX_SEQUENCE)
300 { 300 Sequence = 1;
301 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && 301 else
302 Pack.Type != PacketType.PacketAck && 302 Sequence++;
303 Pack.Type != PacketType.LogoutRequest) 303 Pack.Header.Sequence = Sequence;
304 { 304 }
305 Pack.Header.AckList = new uint[PendingAcks.Count]; 305
306 int i = 0; 306 if (Pack.Header.Reliable) //DIRTY HACK
307 307 {
308 foreach (uint ack in PendingAcks.Values) 308 lock (NeedAck)
309 { 309 {
310 Pack.Header.AckList[i] = ack; 310 if (!NeedAck.ContainsKey(Pack.Header.Sequence))
311 i++; 311 {
312 } 312 NeedAck.Add(Pack.Header.Sequence, Pack);
313 313 }
314 PendingAcks.Clear(); 314 else
315 Pack.Header.AppendedAcks = true; 315 {
316 } 316 // Client.Log("Attempted to add a duplicate sequence number (" +
317 } 317 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
318 } 318 // packet.Type.ToString(), Helpers.LogLevel.Warning);
319 } 319 }
320 } 320 }
321 321
322 322 // Don't append ACKs to resent packets, in case that's what was causing the
323 byte[] ZeroOutBuffer = new byte[4096]; 323 // delivery to fail
324 byte[] sendbuffer; 324 if (!Pack.Header.Resent)
325 sendbuffer = Pack.ToBytes(); 325 {
326 326 // Append any ACKs that need to be sent out to this packet
327 try { 327 lock (PendingAcks)
328 if (Pack.Header.Zerocoded) { 328 {
329 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); 329 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
330 OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None,userEP); 330 Pack.Type != PacketType.PacketAck &&
331 } else { 331 Pack.Type != PacketType.LogoutRequest)
332 OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None,userEP); 332 {
333 } 333 Pack.Header.AckList = new uint[PendingAcks.Count];
334 } catch (Exception) { 334 int i = 0;
335 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); 335
336 ClientThread.Abort(); 336 foreach (uint ack in PendingAcks.Values)
337 } 337 {
338 338 Pack.Header.AckList[i] = ack;
339 } 339 i++;
340 340 }
341 public void InPacket(Packet NewPack) { 341
342 // Handle appended ACKs 342 PendingAcks.Clear();
343 if (NewPack.Header.AppendedAcks) 343 Pack.Header.AppendedAcks = true;
344 { 344 }
345 lock (NeedAck) 345 }
346 { 346 }
347 foreach (uint ack in NewPack.Header.AckList) 347 }
348 { 348 }
349 OpenSim_Main.localcons.WriteLine("Got appended ack: "+ack); 349
350 NeedAck.Remove(ack); 350
351 } 351 byte[] ZeroOutBuffer = new byte[4096];
352 } 352 byte[] sendbuffer;
353 } 353 sendbuffer = Pack.ToBytes();
354 354
355 // Handle PacketAck packets 355 try
356 if (NewPack.Type == PacketType.PacketAck) 356 {
357 { 357 if (Pack.Header.Zerocoded)
358 PacketAckPacket ackPacket = (PacketAckPacket)NewPack; 358 {
359 359 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
360 lock (NeedAck) 360 OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None, userEP);
361 { 361 }
362 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) 362 else
363 { 363 {
364 NeedAck.Remove(block.ID); 364 OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None, userEP);
365 } 365 }
366 } 366 }
367 } else if( ( NewPack.Type == PacketType.StartPingCheck ) ) { 367 catch (Exception)
368 //reply to pingcheck 368 {
369 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; 369 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
370 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); 370 ClientThread.Abort();
371 endPing.PingID.PingID = startPing.PingID.PingID; 371 }
372 OutPacket(endPing); 372
373 } 373 }
374 else 374
375 { 375 public void InPacket(Packet NewPack)
376 QueItem item = new QueItem(); 376 {
377 item.Packet = NewPack; 377 // Handle appended ACKs
378 item.Incoming = true; 378 if (NewPack.Header.AppendedAcks)
379 this.PacketQueue.Enqueue(item); 379 {
380 } 380 lock (NeedAck)
381 381 {
382 } 382 foreach (uint ack in NewPack.Header.AckList)
383 383 {
384 public void OutPacket(Packet NewPack) { 384 OpenSim_Main.localcons.WriteLine("Got appended ack: " + ack);
385 QueItem item = new QueItem(); 385 NeedAck.Remove(ack);
386 item.Packet = NewPack; 386 }
387 item.Incoming = false; 387 }
388 this.PacketQueue.Enqueue(item); 388 }
389 } 389
390 390 // Handle PacketAck packets
391 public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack) { 391 if (NewPack.Type == PacketType.PacketAck)
392 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); 392 {
393 cirpack = initialcirpack; 393 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
394 userEP = remoteEP; 394
395 PacketQueue = new BlockingQueue<QueItem>(); 395 lock (NeedAck)
396 AssetRequests = new BlockingQueue<TransferRequestPacket>(); 396 {
397 AckTimer = new System.Timers.Timer(500); 397 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
398 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); 398 {
399 AckTimer.Start(); 399 NeedAck.Remove(block.ID);
400 400 }
401 ClientThread = new Thread(new ThreadStart(AuthUser)); 401 }
402 ClientThread.IsBackground = true; 402 }
403 ClientThread.Start(); 403 else if ((NewPack.Type == PacketType.StartPingCheck))
404 } 404 {
405 405 //reply to pingcheck
406 private void ClientLoop() { 406 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
407 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop"); 407 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
408 while(true) { 408 endPing.PingID.PingID = startPing.PingID.PingID;
409 QueItem nextPacket = PacketQueue.Dequeue(); 409 OutPacket(endPing);
410 if(nextPacket.Incoming) 410 }
411 { 411 else
412 //is a incoming packet 412 {
413 ProcessInPacket(nextPacket.Packet); 413 QueItem item = new QueItem();
414 } 414 item.Packet = NewPack;
415 else 415 item.Incoming = true;
416 { 416 this.PacketQueue.Enqueue(item);
417 //is a out going packet 417 }
418 ProcessOutPacket(nextPacket.Packet); 418
419 } 419 }
420 } 420
421 } 421 public void OutPacket(Packet NewPack)
422 422 {
423 private void InitNewClient() { 423 QueItem item = new QueItem();
424 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world"); 424 item.Packet = NewPack;
425 OpenSim_Main.local_world.AddViewerAgent(this); 425 item.Incoming = false;
426 world.Entity tempent=OpenSim_Main.local_world.Entities[this.AgentID]; 426 this.PacketQueue.Enqueue(item);
427 this.ClientAvatar=(world.Avatar)tempent; 427 }
428 } 428
429 429 public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack)
430 private void AuthUser() { 430 {
431 if(OpenSim_Main.cfg.sandbox==false) { 431 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request");
432 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid"); 432 cirpack = initialcirpack;
433 WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists"); 433 userEP = remoteEP;
434 OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL); 434 PacketQueue = new BlockingQueue<QueItem>();
435 WebResponse GridResponse = CheckSession.GetResponse(); 435 AssetRequests = new BlockingQueue<TransferRequestPacket>();
436 StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); 436 AckTimer = new System.Timers.Timer(500);
437 String grTest = sr.ReadLine(); 437 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
438 sr.Close(); 438 AckTimer.Start();
439 GridResponse.Close(); 439
440 if(String.IsNullOrEmpty(grTest) || grTest.Equals("1")) { // YAY! Valid login 440 ClientThread = new Thread(new ThreadStart(AuthUser));
441 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString()); 441 ClientThread.IsBackground = true;
442 this.AgentID=cirpack.CircuitCode.ID; 442 ClientThread.Start();
443 this.SessionID=cirpack.CircuitCode.SessionID; 443 }
444 this.CircuitCode=cirpack.CircuitCode.Code; 444
445 InitNewClient(); 445 private void ClientLoop()
446 ClientLoop(); 446 {
447 } else { // Invalid 447 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop");
448 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); 448 while (true)
449 ClientThread.Abort(); 449 {
450 } 450 QueItem nextPacket = PacketQueue.Dequeue();
451 } else { 451 if (nextPacket.Incoming)
452 this.AgentID=cirpack.CircuitCode.ID; 452 {
453 this.SessionID=cirpack.CircuitCode.SessionID; 453 //is a incoming packet
454 this.CircuitCode=cirpack.CircuitCode.Code; 454 ProcessInPacket(nextPacket.Packet);
455 InitNewClient(); 455 }
456 ClientLoop(); 456 else
457 } 457 {
458 } 458 //is a out going packet
459 } 459 ProcessOutPacket(nextPacket.Packet);
460 }
461 }
462 }
463
464 private void InitNewClient()
465 {
466 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world");
467 OpenSim_Main.local_world.AddViewerAgent(this);
468 world.Entity tempent = OpenSim_Main.local_world.Entities[this.AgentID];
469 this.ClientAvatar = (world.Avatar)tempent;
470 }
471
472 private void AuthUser()
473 {
474 if (OpenSim_Main.cfg.sandbox == false)
475 {
476 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid");
477 WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists");
478 OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL);
479 WebResponse GridResponse = CheckSession.GetResponse();
480 StreamReader sr = new StreamReader(GridResponse.GetResponseStream());
481 String grTest = sr.ReadLine();
482 sr.Close();
483 GridResponse.Close();
484 if (String.IsNullOrEmpty(grTest) || grTest.Equals("1"))
485 { // YAY! Valid login
486 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString());
487 this.AgentID = cirpack.CircuitCode.ID;
488 this.SessionID = cirpack.CircuitCode.SessionID;
489 this.CircuitCode = cirpack.CircuitCode.Code;
490 InitNewClient();
491 ClientLoop();
492 }
493 else
494 { // Invalid
495 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString());
496 ClientThread.Abort();
497 }
498 }
499 else
500 {
501 this.AgentID = cirpack.CircuitCode.ID;
502 this.SessionID = cirpack.CircuitCode.SessionID;
503 this.CircuitCode = cirpack.CircuitCode.Code;
504 InitNewClient();
505 ClientLoop();
506 }
507 }
508 }
460 509
461} 510}