SimClient.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. /*
  2. Copyright (c) OpenSim project, http://osgrid.org/
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the <organization> nor the
  12. * names of its contributors may be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
  16. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. using System;
  27. using System.Collections;
  28. using System.Collections.Generic;
  29. using libsecondlife;
  30. using libsecondlife.Packets;
  31. using System.Net;
  32. using System.Net.Sockets;
  33. using System.IO;
  34. using System.Threading;
  35. using System.Timers;
  36. using OpenSim.Framework.Interfaces;
  37. using OpenSim.Framework.Assets;
  38. using OpenSim.Framework.Inventory;
  39. using OpenSim.Framework.Utilities;
  40. using OpenSim.world;
  41. using OpenSim.Assets;
  42. namespace OpenSim
  43. {
  44. /// <summary>
  45. /// Handles new client connections
  46. /// Constructor takes a single Packet and authenticates everything
  47. /// </summary>
  48. public class SimClient
  49. {
  50. public LLUUID AgentID;
  51. public LLUUID SessionID;
  52. public LLUUID SecureSessionID = LLUUID.Zero;
  53. public uint CircuitCode;
  54. public world.Avatar ClientAvatar;
  55. private UseCircuitCodePacket cirpack;
  56. private Thread ClientThread;
  57. public EndPoint userEP;
  58. private BlockingQueue<QueItem> PacketQueue;
  59. private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
  60. private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
  61. //private Dictionary<LLUUID, AssetBase> UploadedAssets = new Dictionary<LLUUID, AssetBase>();
  62. private System.Timers.Timer AckTimer;
  63. private uint Sequence = 0;
  64. private object SequenceLock = new object();
  65. private const int MAX_APPENDED_ACKS = 10;
  66. private const int RESEND_TIMEOUT = 4000;
  67. private const int MAX_SEQUENCE = 0xFFFFFF;
  68. private AgentAssetUpload UploadAssets;
  69. private LLUUID newAssetFolder = LLUUID.Zero;
  70. private bool debug = false;
  71. private World m_world;
  72. private Dictionary<uint, SimClient> m_clientThreads;
  73. private AssetCache m_assetCache;
  74. private IGridServer m_gridServer;
  75. private IUserServer m_userServer = null;
  76. private OpenSimNetworkHandler m_application;
  77. private InventoryCache m_inventoryCache;
  78. private bool m_sandboxMode;
  79. public IUserServer UserServer
  80. {
  81. set
  82. {
  83. this.m_userServer = value;
  84. }
  85. }
  86. private void ack_pack(Packet Pack)
  87. {
  88. //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
  89. //ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
  90. //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
  91. //ack_it.Packets[0].ID = Pack.Header.ID;
  92. //ack_it.Header.Reliable = false;
  93. //OutPacket(ack_it);
  94. if (Pack.Header.Reliable)
  95. {
  96. lock (PendingAcks)
  97. {
  98. uint sequence = (uint)Pack.Header.Sequence;
  99. if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
  100. }
  101. }
  102. }
  103. protected virtual void ProcessInPacket(Packet Pack)
  104. {
  105. ack_pack(Pack);
  106. if (debug)
  107. {
  108. if (Pack.Type != PacketType.AgentUpdate)
  109. {
  110. Console.WriteLine(Pack.Type.ToString());
  111. }
  112. }
  113. switch (Pack.Type)
  114. {
  115. case PacketType.CompleteAgentMovement:
  116. ClientAvatar.CompleteMovement(m_world);
  117. ClientAvatar.SendInitialPosition();
  118. break;
  119. case PacketType.RegionHandshakeReply:
  120. m_world.SendLayerData(this);
  121. break;
  122. case PacketType.AgentWearablesRequest:
  123. ClientAvatar.SendInitialAppearance();
  124. foreach (SimClient client in m_clientThreads.Values)
  125. {
  126. if (client.AgentID != this.AgentID)
  127. {
  128. ObjectUpdatePacket objupdate = client.ClientAvatar.CreateUpdatePacket();
  129. this.OutPacket(objupdate);
  130. client.ClientAvatar.SendAppearanceToOtherAgent(this);
  131. }
  132. }
  133. m_world.GetInitialPrims(this);
  134. break;
  135. case PacketType.AgentIsNowWearing:
  136. AgentIsNowWearingPacket wear = (AgentIsNowWearingPacket)Pack;
  137. //Console.WriteLine(Pack.ToString());
  138. break;
  139. case PacketType.AgentSetAppearance:
  140. AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
  141. // Console.WriteLine(appear.ToString());
  142. this.ClientAvatar.SetAppearance(appear);
  143. break;
  144. case PacketType.ObjectAdd:
  145. m_world.AddNewPrim((ObjectAddPacket)Pack, this);
  146. break;
  147. case PacketType.ObjectLink:
  148. OpenSim.Framework.Console.MainConsole.Instance.WriteLine(Pack.ToString());
  149. break;
  150. case PacketType.ObjectScale:
  151. OpenSim.Framework.Console.MainConsole.Instance.WriteLine(Pack.ToString());
  152. break;
  153. case PacketType.ObjectShape:
  154. ObjectShapePacket shape = (ObjectShapePacket)Pack;
  155. for (int i = 0; i < shape.ObjectData.Length; i++)
  156. {
  157. foreach (Entity ent in m_world.Entities.Values)
  158. {
  159. if (ent.localid == shape.ObjectData[i].ObjectLocalID)
  160. {
  161. ((OpenSim.world.Primitive)ent).UpdateShape(shape.ObjectData[i]);
  162. }
  163. }
  164. }
  165. break;
  166. case PacketType.MultipleObjectUpdate:
  167. MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)Pack;
  168. for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
  169. {
  170. if (multipleupdate.ObjectData[i].Type == 9) //change position
  171. {
  172. libsecondlife.LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0);
  173. foreach (Entity ent in m_world.Entities.Values)
  174. {
  175. if (ent.localid == multipleupdate.ObjectData[i].ObjectLocalID)
  176. {
  177. ((OpenSim.world.Primitive)ent).UpdatePosition(pos);
  178. }
  179. }
  180. //should update stored position of the prim
  181. }
  182. else if (multipleupdate.ObjectData[i].Type == 10)//rotation
  183. {
  184. libsecondlife.LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 0, true);
  185. foreach (Entity ent in m_world.Entities.Values)
  186. {
  187. if (ent.localid == multipleupdate.ObjectData[i].ObjectLocalID)
  188. {
  189. ent.rotation = new Axiom.MathLib.Quaternion(rot.W, rot.X, rot.Y, rot.Z);
  190. ((OpenSim.world.Primitive)ent).UpdateFlag = true;
  191. }
  192. }
  193. }
  194. else if (multipleupdate.ObjectData[i].Type == 13)//scale
  195. {
  196. libsecondlife.LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12);
  197. foreach (Entity ent in m_world.Entities.Values)
  198. {
  199. if (ent.localid == multipleupdate.ObjectData[i].ObjectLocalID)
  200. {
  201. ((OpenSim.world.Primitive)ent).Scale = scale;
  202. }
  203. }
  204. }
  205. }
  206. break;
  207. case PacketType.RequestImage:
  208. RequestImagePacket imageRequest = (RequestImagePacket)Pack;
  209. for (int i = 0; i < imageRequest.RequestImage.Length; i++)
  210. {
  211. m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image);
  212. }
  213. break;
  214. case PacketType.TransferRequest:
  215. //Console.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request");
  216. TransferRequestPacket transfer = (TransferRequestPacket)Pack;
  217. m_assetCache.AddAssetRequest(this, transfer);
  218. break;
  219. case PacketType.AgentUpdate:
  220. ClientAvatar.HandleUpdate((AgentUpdatePacket)Pack);
  221. break;
  222. case PacketType.LogoutRequest:
  223. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request");
  224. //send reply to let the client logout
  225. LogoutReplyPacket logReply = new LogoutReplyPacket();
  226. logReply.AgentData.AgentID = this.AgentID;
  227. logReply.AgentData.SessionID = this.SessionID;
  228. logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
  229. logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
  230. logReply.InventoryData[0].ItemID = LLUUID.Zero;
  231. OutPacket(logReply);
  232. //tell all clients to kill our object
  233. KillObjectPacket kill = new KillObjectPacket();
  234. kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
  235. kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
  236. kill.ObjectData[0].ID = this.ClientAvatar.localid;
  237. foreach (SimClient client in m_clientThreads.Values)
  238. {
  239. client.OutPacket(kill);
  240. }
  241. if (this.m_userServer != null)
  242. {
  243. this.m_inventoryCache.ClientLeaving(this.AgentID, this.m_userServer);
  244. }
  245. else
  246. {
  247. this.m_inventoryCache.ClientLeaving(this.AgentID, null);
  248. }
  249. m_gridServer.LogoutSession(this.SessionID, this.AgentID, this.CircuitCode);
  250. lock (m_world.Entities)
  251. {
  252. m_world.Entities.Remove(this.AgentID);
  253. }
  254. //need to do other cleaning up here too
  255. m_clientThreads.Remove(this.CircuitCode); //this.userEP);
  256. m_application.RemoveClientCircuit(this.CircuitCode);
  257. this.ClientThread.Abort();
  258. break;
  259. case PacketType.ChatFromViewer:
  260. ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
  261. if (Helpers.FieldToString(inchatpack.ChatData.Message) == "") break;
  262. System.Text.Encoding _enc = System.Text.Encoding.ASCII;
  263. libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket();
  264. reply.ChatData.Audible = 1;
  265. reply.ChatData.Message = inchatpack.ChatData.Message;
  266. reply.ChatData.ChatType = 1;
  267. reply.ChatData.SourceType = 1;
  268. reply.ChatData.Position = this.ClientAvatar.position;
  269. reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0");
  270. reply.ChatData.OwnerID = this.AgentID;
  271. reply.ChatData.SourceID = this.AgentID;
  272. foreach (SimClient client in m_clientThreads.Values)
  273. {
  274. client.OutPacket(reply);
  275. }
  276. break;
  277. case PacketType.ObjectImage:
  278. ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
  279. for (int i = 0; i < imagePack.ObjectData.Length; i++)
  280. {
  281. foreach (Entity ent in m_world.Entities.Values)
  282. {
  283. if (ent.localid == imagePack.ObjectData[i].ObjectLocalID)
  284. {
  285. ((OpenSim.world.Primitive)ent).UpdateTexture(imagePack.ObjectData[i].TextureEntry);
  286. }
  287. }
  288. }
  289. break;
  290. case PacketType.ObjectFlagUpdate:
  291. ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
  292. foreach (Entity ent in m_world.Entities.Values)
  293. {
  294. if (ent.localid == flags.AgentData.ObjectLocalID)
  295. {
  296. ((OpenSim.world.Primitive)ent).UpdateObjectFlags(flags);
  297. }
  298. }
  299. break;
  300. case PacketType.AssetUploadRequest:
  301. //this.debug = true;
  302. AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
  303. // Console.WriteLine(Pack.ToString());
  304. // if (request.AssetBlock.Type == 0)
  305. // {
  306. //this.UploadAssets.HandleUploadPacket(request, LLUUID.Random());
  307. //}
  308. //else
  309. //{
  310. this.UploadAssets.HandleUploadPacket(request, request.AssetBlock.TransactionID.Combine(this.SecureSessionID));
  311. //}
  312. break;
  313. case PacketType.SendXferPacket:
  314. Console.WriteLine(Pack.ToString());
  315. this.UploadAssets.HandleXferPacket((SendXferPacketPacket)Pack);
  316. break;
  317. case PacketType.CreateInventoryFolder:
  318. CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
  319. m_inventoryCache.CreateNewInventoryFolder(this, invFolder.FolderData.FolderID, (ushort)invFolder.FolderData.Type);
  320. Console.WriteLine(Pack.ToString());
  321. break;
  322. case PacketType.CreateInventoryItem:
  323. Console.WriteLine(Pack.ToString());
  324. CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
  325. if (createItem.InventoryBlock.TransactionID != LLUUID.Zero)
  326. {
  327. this.UploadAssets.CreateInventoryItem(createItem);
  328. }
  329. break;
  330. case PacketType.FetchInventory:
  331. //Console.WriteLine("fetch item packet");
  332. FetchInventoryPacket FetchInventory = (FetchInventoryPacket)Pack;
  333. m_inventoryCache.FetchInventory(this, FetchInventory);
  334. break;
  335. case PacketType.FetchInventoryDescendents:
  336. FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
  337. m_inventoryCache.FetchInventoryDescendents(this, Fetch);
  338. break;
  339. case PacketType.UpdateInventoryItem:
  340. UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack;
  341. for (int i = 0; i < update.InventoryData.Length; i++)
  342. {
  343. if (update.InventoryData[i].TransactionID != LLUUID.Zero)
  344. {
  345. AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionID));
  346. if (asset != null)
  347. {
  348. m_inventoryCache.UpdateInventoryItem(this, update.InventoryData[i].ItemID, asset);
  349. }
  350. else
  351. {
  352. asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID);
  353. if (asset != null)
  354. {
  355. m_inventoryCache.UpdateInventoryItem(this, update.InventoryData[i].ItemID, asset);
  356. }
  357. }
  358. }
  359. }
  360. break;
  361. case PacketType.ViewerEffect:
  362. ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
  363. foreach (SimClient client in m_clientThreads.Values)
  364. {
  365. if (client.AgentID != this.AgentID)
  366. {
  367. viewer.AgentData.AgentID = client.AgentID;
  368. viewer.AgentData.SessionID = client.SessionID;
  369. client.OutPacket(viewer);
  370. }
  371. }
  372. break;
  373. case PacketType.DeRezObject:
  374. //OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Received DeRezObject packet");
  375. m_world.DeRezObject((DeRezObjectPacket)Pack, this);
  376. break;
  377. }
  378. }
  379. private void ResendUnacked()
  380. {
  381. int now = Environment.TickCount;
  382. lock (NeedAck)
  383. {
  384. foreach (Packet packet in NeedAck.Values)
  385. {
  386. if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
  387. {
  388. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Resending " + packet.Type.ToString() + " packet, " +
  389. (now - packet.TickCount) + "ms have passed");
  390. packet.Header.Resent = true;
  391. OutPacket(packet);
  392. }
  393. }
  394. }
  395. }
  396. private void SendAcks()
  397. {
  398. lock (PendingAcks)
  399. {
  400. if (PendingAcks.Count > 0)
  401. {
  402. if (PendingAcks.Count > 250)
  403. {
  404. // FIXME: Handle the odd case where we have too many pending ACKs queued up
  405. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Too many ACKs queued up!");
  406. return;
  407. }
  408. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck");
  409. int i = 0;
  410. PacketAckPacket acks = new PacketAckPacket();
  411. acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
  412. foreach (uint ack in PendingAcks.Values)
  413. {
  414. acks.Packets[i] = new PacketAckPacket.PacketsBlock();
  415. acks.Packets[i].ID = ack;
  416. i++;
  417. }
  418. acks.Header.Reliable = false;
  419. OutPacket(acks);
  420. PendingAcks.Clear();
  421. }
  422. }
  423. }
  424. private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
  425. {
  426. SendAcks();
  427. ResendUnacked();
  428. }
  429. protected virtual void ProcessOutPacket(Packet Pack)
  430. {
  431. // Keep track of when this packet was sent out
  432. Pack.TickCount = Environment.TickCount;
  433. if (!Pack.Header.Resent)
  434. {
  435. // Set the sequence number
  436. lock (SequenceLock)
  437. {
  438. if (Sequence >= MAX_SEQUENCE)
  439. Sequence = 1;
  440. else
  441. Sequence++;
  442. Pack.Header.Sequence = Sequence;
  443. }
  444. if (Pack.Header.Reliable) //DIRTY HACK
  445. {
  446. lock (NeedAck)
  447. {
  448. if (!NeedAck.ContainsKey(Pack.Header.Sequence))
  449. {
  450. NeedAck.Add(Pack.Header.Sequence, Pack);
  451. }
  452. else
  453. {
  454. // Client.Log("Attempted to add a duplicate sequence number (" +
  455. // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
  456. // packet.Type.ToString(), Helpers.LogLevel.Warning);
  457. }
  458. }
  459. // Don't append ACKs to resent packets, in case that's what was causing the
  460. // delivery to fail
  461. if (!Pack.Header.Resent)
  462. {
  463. // Append any ACKs that need to be sent out to this packet
  464. lock (PendingAcks)
  465. {
  466. if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
  467. Pack.Type != PacketType.PacketAck &&
  468. Pack.Type != PacketType.LogoutRequest)
  469. {
  470. Pack.Header.AckList = new uint[PendingAcks.Count];
  471. int i = 0;
  472. foreach (uint ack in PendingAcks.Values)
  473. {
  474. Pack.Header.AckList[i] = ack;
  475. i++;
  476. }
  477. PendingAcks.Clear();
  478. Pack.Header.AppendedAcks = true;
  479. }
  480. }
  481. }
  482. }
  483. }
  484. //MainConsole.Instance.WriteLine("OUT: \n" + Pack.ToString());
  485. byte[] ZeroOutBuffer = new byte[4096];
  486. byte[] sendbuffer;
  487. sendbuffer = Pack.ToBytes();
  488. try
  489. {
  490. if (Pack.Header.Zerocoded)
  491. {
  492. int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
  493. m_application.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
  494. }
  495. else
  496. {
  497. m_application.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
  498. }
  499. }
  500. catch (Exception)
  501. {
  502. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
  503. ClientThread.Abort();
  504. }
  505. }
  506. public virtual void InPacket(Packet NewPack)
  507. {
  508. // Handle appended ACKs
  509. if (NewPack.Header.AppendedAcks)
  510. {
  511. lock (NeedAck)
  512. {
  513. foreach (uint ack in NewPack.Header.AckList)
  514. {
  515. NeedAck.Remove(ack);
  516. }
  517. }
  518. }
  519. // Handle PacketAck packets
  520. if (NewPack.Type == PacketType.PacketAck)
  521. {
  522. PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
  523. lock (NeedAck)
  524. {
  525. foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
  526. {
  527. NeedAck.Remove(block.ID);
  528. }
  529. }
  530. }
  531. else if ((NewPack.Type == PacketType.StartPingCheck))
  532. {
  533. //reply to pingcheck
  534. libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
  535. libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
  536. endPing.PingID.PingID = startPing.PingID.PingID;
  537. OutPacket(endPing);
  538. }
  539. else
  540. {
  541. QueItem item = new QueItem();
  542. item.Packet = NewPack;
  543. item.Incoming = true;
  544. this.PacketQueue.Enqueue(item);
  545. }
  546. }
  547. public virtual void OutPacket(Packet NewPack)
  548. {
  549. QueItem item = new QueItem();
  550. item.Packet = NewPack;
  551. item.Incoming = false;
  552. this.PacketQueue.Enqueue(item);
  553. }
  554. public SimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, SimClient> clientThreads, AssetCache assetCache, IGridServer gridServer, OpenSimNetworkHandler application, InventoryCache inventoryCache, bool sandboxMode)
  555. {
  556. m_world = world;
  557. m_clientThreads = clientThreads;
  558. m_assetCache = assetCache;
  559. m_gridServer = gridServer;
  560. m_application = application;
  561. m_inventoryCache = inventoryCache;
  562. m_sandboxMode = sandboxMode;
  563. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request");
  564. cirpack = initialcirpack;
  565. userEP = remoteEP;
  566. PacketQueue = new BlockingQueue<QueItem>();
  567. this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache );
  568. AckTimer = new System.Timers.Timer(500);
  569. AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
  570. AckTimer.Start();
  571. ClientThread = new Thread(new ThreadStart(AuthUser));
  572. ClientThread.IsBackground = true;
  573. ClientThread.Start();
  574. }
  575. protected virtual void ClientLoop()
  576. {
  577. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop");
  578. while (true)
  579. {
  580. QueItem nextPacket = PacketQueue.Dequeue();
  581. if (nextPacket.Incoming)
  582. {
  583. //is a incoming packet
  584. ProcessInPacket(nextPacket.Packet);
  585. }
  586. else
  587. {
  588. //is a out going packet
  589. ProcessOutPacket(nextPacket.Packet);
  590. }
  591. }
  592. }
  593. protected virtual void InitNewClient()
  594. {
  595. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world");
  596. m_world.AddViewerAgent(this);
  597. world.Entity tempent = m_world.Entities[this.AgentID];
  598. this.ClientAvatar = (world.Avatar)tempent;
  599. }
  600. protected virtual void AuthUser()
  601. {
  602. AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
  603. if (!sessionInfo.Authorised)
  604. {
  605. //session/circuit not authorised
  606. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString());
  607. ClientThread.Abort();
  608. }
  609. else
  610. {
  611. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString());
  612. //session is authorised
  613. this.AgentID = cirpack.CircuitCode.ID;
  614. this.SessionID = cirpack.CircuitCode.SessionID;
  615. this.CircuitCode = cirpack.CircuitCode.Code;
  616. InitNewClient(); //shouldn't be called here as we might be a child agent and not want a full avatar
  617. this.ClientAvatar.firstname = sessionInfo.LoginInfo.First;
  618. this.ClientAvatar.lastname = sessionInfo.LoginInfo.Last;
  619. if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero)
  620. {
  621. this.SecureSessionID = sessionInfo.LoginInfo.SecureSession;
  622. }
  623. // Create Inventory, currently only works for sandbox mode
  624. if (m_sandboxMode)
  625. {
  626. AgentInventory inventory = null;
  627. if (sessionInfo.LoginInfo.InventoryFolder != null)
  628. {
  629. inventory = this.CreateInventory(sessionInfo.LoginInfo.InventoryFolder);
  630. if (sessionInfo.LoginInfo.BaseFolder != null)
  631. {
  632. if (!inventory.HasFolder(sessionInfo.LoginInfo.BaseFolder))
  633. {
  634. m_inventoryCache.CreateNewInventoryFolder(this, sessionInfo.LoginInfo.BaseFolder);
  635. }
  636. this.newAssetFolder = sessionInfo.LoginInfo.BaseFolder;
  637. AssetBase[] inventorySet = m_assetCache.CreateNewInventorySet(this.AgentID);
  638. if (inventorySet != null)
  639. {
  640. for (int i = 0; i < inventorySet.Length; i++)
  641. {
  642. if (inventorySet[i] != null)
  643. {
  644. m_inventoryCache.AddNewInventoryItem(this, sessionInfo.LoginInfo.BaseFolder, inventorySet[i]);
  645. }
  646. }
  647. }
  648. }
  649. }
  650. }
  651. ClientLoop();
  652. }
  653. }
  654. private AgentInventory CreateInventory(LLUUID baseFolder)
  655. {
  656. AgentInventory inventory = null;
  657. if (this.m_userServer != null)
  658. {
  659. // a user server is set so request the inventory from it
  660. inventory = m_inventoryCache.FetchAgentsInventory(this.AgentID, m_userServer);
  661. }
  662. else
  663. {
  664. inventory = new AgentInventory();
  665. inventory.AgentID = this.AgentID;
  666. inventory.CreateRootFolder(this.AgentID, false);
  667. m_inventoryCache.AddNewAgentsInventory(inventory);
  668. m_inventoryCache.CreateNewInventoryFolder(this, baseFolder);
  669. }
  670. return inventory;
  671. }
  672. }
  673. }