SimClient.cs 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  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 Nwc.XmlRpc;
  32. using System.Net;
  33. using System.Net.Sockets;
  34. using System.IO;
  35. using System.Threading;
  36. using System.Timers;
  37. using OpenSim.Framework.Interfaces;
  38. using OpenSim.Framework.Types;
  39. using OpenSim.Framework.Inventory;
  40. using OpenSim.Framework.Utilities;
  41. using OpenSim.world;
  42. using OpenSim.Assets;
  43. namespace OpenSim
  44. {
  45. public delegate bool PacketMethod(SimClient simClient, Packet packet);
  46. /// <summary>
  47. /// Handles new client connections
  48. /// Constructor takes a single Packet and authenticates everything
  49. /// </summary>
  50. public class SimClient
  51. {
  52. public LLUUID AgentID;
  53. public LLUUID SessionID;
  54. public LLUUID SecureSessionID = LLUUID.Zero;
  55. public bool m_child;
  56. public uint CircuitCode;
  57. public world.Avatar ClientAvatar;
  58. private UseCircuitCodePacket cirpack;
  59. public Thread ClientThread;
  60. public EndPoint userEP;
  61. public LLVector3 startpos;
  62. private BlockingQueue<QueItem> PacketQueue;
  63. private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
  64. private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
  65. //private Dictionary<LLUUID, AssetBase> UploadedAssets = new Dictionary<LLUUID, AssetBase>();
  66. private System.Timers.Timer AckTimer;
  67. private uint Sequence = 0;
  68. private object SequenceLock = new object();
  69. private const int MAX_APPENDED_ACKS = 10;
  70. private const int RESEND_TIMEOUT = 4000;
  71. private const int MAX_SEQUENCE = 0xFFFFFF;
  72. private AgentAssetUpload UploadAssets;
  73. private LLUUID newAssetFolder = LLUUID.Zero;
  74. private bool debug = false;
  75. private World m_world;
  76. private Dictionary<uint, SimClient> m_clientThreads;
  77. private AssetCache m_assetCache;
  78. private IGridServer m_gridServer;
  79. private IUserServer m_userServer = null;
  80. private OpenSimNetworkHandler m_application;
  81. private InventoryCache m_inventoryCache;
  82. public bool m_sandboxMode;
  83. private int cachedtextureserial = 0;
  84. private RegionInfo m_regionData;
  85. protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
  86. protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); //local handlers for this instance
  87. public IUserServer UserServer
  88. {
  89. set
  90. {
  91. this.m_userServer = value;
  92. }
  93. }
  94. public SimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, SimClient> clientThreads, AssetCache assetCache, IGridServer gridServer, OpenSimNetworkHandler application, InventoryCache inventoryCache, bool sandboxMode, bool child, RegionInfo regionDat)
  95. {
  96. m_world = world;
  97. m_clientThreads = clientThreads;
  98. m_assetCache = assetCache;
  99. m_gridServer = gridServer;
  100. m_application = application;
  101. m_inventoryCache = inventoryCache;
  102. m_sandboxMode = sandboxMode;
  103. m_child = child;
  104. m_regionData = regionDat;
  105. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request");
  106. cirpack = initialcirpack;
  107. userEP = remoteEP;
  108. if (m_gridServer.GetName() == "Remote")
  109. {
  110. this.startpos = ((RemoteGridBase)m_gridServer).agentcircuits[initialcirpack.CircuitCode.Code].startpos;
  111. }
  112. else
  113. {
  114. this.startpos = new LLVector3(128, 128, m_world.Terrain[(int)128, (int)128] + 15.0f); // new LLVector3(128.0f, 128.0f, 60f);
  115. }
  116. PacketQueue = new BlockingQueue<QueItem>();
  117. this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
  118. AckTimer = new System.Timers.Timer(500);
  119. AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
  120. AckTimer.Start();
  121. this.RegisterLocalPacketHandlers();
  122. ClientThread = new Thread(new ThreadStart(AuthUser));
  123. ClientThread.IsBackground = true;
  124. ClientThread.Start();
  125. }
  126. protected virtual void RegisterLocalPacketHandlers()
  127. {
  128. this.AddLocalPacketHandler(PacketType.LogoutRequest, this.Logout);
  129. this.AddLocalPacketHandler(PacketType.AgentCachedTexture, this.AgentTextureCached);
  130. this.AddLocalPacketHandler(PacketType.MultipleObjectUpdate, this.MultipleObjUpdate);
  131. }
  132. public void CrossSimBorder(LLVector3 avatarpos)
  133. { // VERY VERY BASIC
  134. LLVector3 newpos = avatarpos;
  135. uint neighbourx = this.m_regionData.RegionLocX;
  136. uint neighboury = this.m_regionData.RegionLocY;
  137. if (avatarpos.X < 0)
  138. {
  139. neighbourx -= 1;
  140. newpos.X = 254;
  141. }
  142. if (avatarpos.X > 255)
  143. {
  144. neighbourx += 1;
  145. newpos.X = 1;
  146. }
  147. if (avatarpos.Y < 0)
  148. {
  149. neighboury -= 1;
  150. newpos.Y = 254;
  151. }
  152. if (avatarpos.Y > 255)
  153. {
  154. neighbourx += 1;
  155. newpos.Y = 1;
  156. }
  157. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("SimClient.cs:CrossSimBorder() - Crossing border to neighbouring sim at [" + neighbourx.ToString() + "," + neighboury.ToString() + "]");
  158. Hashtable SimParams;
  159. ArrayList SendParams;
  160. XmlRpcRequest GridReq;
  161. XmlRpcResponse GridResp;
  162. foreach (Hashtable borderingSim in ((RemoteGridBase)m_gridServer).neighbours)
  163. {
  164. if (((string)borderingSim["region_locx"]).Equals(neighbourx.ToString()) && ((string)borderingSim["region_locy"]).Equals(neighboury.ToString()))
  165. {
  166. SimParams = new Hashtable();
  167. SimParams["firstname"] = this.ClientAvatar.firstname;
  168. SimParams["lastname"] = this.ClientAvatar.lastname;
  169. SimParams["circuit_code"] = this.CircuitCode.ToString();
  170. SimParams["pos_x"] = newpos.X.ToString();
  171. SimParams["pos_y"] = newpos.Y.ToString();
  172. SimParams["pos_z"] = newpos.Z.ToString();
  173. SendParams = new ArrayList();
  174. SendParams.Add(SimParams);
  175. GridReq = new XmlRpcRequest("agent_crossing", SendParams);
  176. GridResp = GridReq.Send("http://" + borderingSim["sim_ip"] + ":" + borderingSim["sim_port"], 3000);
  177. CrossedRegionPacket NewSimPack = new CrossedRegionPacket();
  178. NewSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
  179. NewSimPack.AgentData.AgentID = this.AgentID;
  180. NewSimPack.AgentData.SessionID = this.SessionID;
  181. NewSimPack.Info = new CrossedRegionPacket.InfoBlock();
  182. NewSimPack.Info.Position = newpos;
  183. NewSimPack.Info.LookAt = new LLVector3(0.99f, 0.042f, 0); // copied from Avatar.cs - SHOULD BE DYNAMIC!!!!!!!!!!
  184. NewSimPack.RegionData = new libsecondlife.Packets.CrossedRegionPacket.RegionDataBlock();
  185. NewSimPack.RegionData.RegionHandle = Helpers.UIntsToLong((uint)(Convert.ToInt32(borderingSim["region_locx"]) * 256), (uint)(Convert.ToInt32(borderingSim["region_locy"]) * 256));
  186. System.Net.IPAddress neighbourIP = System.Net.IPAddress.Parse((string)borderingSim["sim_ip"]);
  187. byte[] byteIP = neighbourIP.GetAddressBytes();
  188. NewSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
  189. NewSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
  190. NewSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
  191. NewSimPack.RegionData.SimIP += (uint)byteIP[0];
  192. NewSimPack.RegionData.SimPort = (ushort)Convert.ToInt32(borderingSim["sim_port"]);
  193. NewSimPack.RegionData.SeedCapability = new byte[0];
  194. lock (PacketQueue)
  195. {
  196. ProcessOutPacket(NewSimPack);
  197. DowngradeClient();
  198. }
  199. }
  200. }
  201. }
  202. public void UpgradeClient()
  203. {
  204. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("SimClient.cs:UpgradeClient() - upgrading child to full agent");
  205. this.m_child = false;
  206. this.m_world.RemoveViewerAgent(this);
  207. if (!this.m_sandboxMode)
  208. {
  209. this.startpos = ((RemoteGridBase)m_gridServer).agentcircuits[CircuitCode].startpos;
  210. ((RemoteGridBase)m_gridServer).agentcircuits[CircuitCode].child = false;
  211. }
  212. this.InitNewClient();
  213. }
  214. public void DowngradeClient()
  215. {
  216. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("SimClient.cs:UpgradeClient() - changing full agent to child");
  217. this.m_child = true;
  218. this.m_world.RemoveViewerAgent(this);
  219. this.m_world.AddViewerAgent(this);
  220. }
  221. public void KillClient()
  222. {
  223. KillObjectPacket kill = new KillObjectPacket();
  224. kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
  225. kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
  226. kill.ObjectData[0].ID = this.ClientAvatar.localid;
  227. foreach (SimClient client in m_clientThreads.Values)
  228. {
  229. client.OutPacket(kill);
  230. }
  231. if (this.m_userServer != null)
  232. {
  233. this.m_inventoryCache.ClientLeaving(this.AgentID, this.m_userServer);
  234. }
  235. else
  236. {
  237. this.m_inventoryCache.ClientLeaving(this.AgentID, null);
  238. }
  239. m_world.RemoveViewerAgent(this);
  240. m_clientThreads.Remove(this.CircuitCode);
  241. m_application.RemoveClientCircuit(this.CircuitCode);
  242. this.ClientThread.Abort();
  243. }
  244. public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
  245. {
  246. bool result = false;
  247. lock (PacketHandlers)
  248. {
  249. if (!PacketHandlers.ContainsKey(packetType))
  250. {
  251. PacketHandlers.Add(packetType, handler);
  252. result = true;
  253. }
  254. }
  255. return result;
  256. }
  257. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
  258. {
  259. bool result = false;
  260. lock (m_packetHandlers)
  261. {
  262. if (!m_packetHandlers.ContainsKey(packetType))
  263. {
  264. m_packetHandlers.Add(packetType, handler);
  265. result = true;
  266. }
  267. }
  268. return result;
  269. }
  270. protected virtual bool ProcessPacketMethod(Packet packet)
  271. {
  272. bool result = false;
  273. bool found = false;
  274. PacketMethod method;
  275. if (m_packetHandlers.TryGetValue(packet.Type, out method))
  276. {
  277. //there is a local handler for this packet type
  278. result = method(this, packet);
  279. }
  280. else
  281. {
  282. //there is not a local handler so see if there is a Global handler
  283. lock (PacketHandlers)
  284. {
  285. found = PacketHandlers.TryGetValue(packet.Type, out method);
  286. }
  287. if (found)
  288. {
  289. result = method(this, packet);
  290. }
  291. }
  292. return result;
  293. }
  294. private void ack_pack(Packet Pack)
  295. {
  296. if (Pack.Header.Reliable)
  297. {
  298. libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
  299. ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
  300. ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
  301. ack_it.Packets[0].ID = Pack.Header.Sequence;
  302. ack_it.Header.Reliable = false;
  303. OutPacket(ack_it);
  304. }
  305. /*
  306. if (Pack.Header.Reliable)
  307. {
  308. lock (PendingAcks)
  309. {
  310. uint sequence = (uint)Pack.Header.Sequence;
  311. if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
  312. }
  313. }*/
  314. }
  315. protected virtual void ProcessInPacket(Packet Pack)
  316. {
  317. ack_pack(Pack);
  318. if (debug)
  319. {
  320. if (Pack.Type != PacketType.AgentUpdate)
  321. {
  322. Console.WriteLine(Pack.Type.ToString());
  323. }
  324. }
  325. if (this.ProcessPacketMethod(Pack))
  326. {
  327. //there is a handler registered that handled this packet type
  328. return;
  329. }
  330. else
  331. {
  332. System.Text.Encoding _enc = System.Text.Encoding.ASCII;
  333. switch (Pack.Type)
  334. {
  335. case PacketType.CompleteAgentMovement:
  336. if (this.m_child) this.UpgradeClient();
  337. ClientAvatar.CompleteMovement(m_world);
  338. ClientAvatar.SendInitialPosition();
  339. break;
  340. case PacketType.RegionHandshakeReply:
  341. m_world.SendLayerData(this);
  342. break;
  343. case PacketType.AgentWearablesRequest:
  344. ClientAvatar.SendInitialAppearance();
  345. foreach (SimClient client in m_clientThreads.Values)
  346. {
  347. if (client.AgentID != this.AgentID)
  348. {
  349. ObjectUpdatePacket objupdate = client.ClientAvatar.CreateUpdatePacket();
  350. this.OutPacket(objupdate);
  351. client.ClientAvatar.SendAppearanceToOtherAgent(this);
  352. }
  353. }
  354. m_world.GetInitialPrims(this);
  355. break;
  356. case PacketType.AgentIsNowWearing:
  357. AgentIsNowWearingPacket wear = (AgentIsNowWearingPacket)Pack;
  358. //Console.WriteLine(Pack.ToString());
  359. break;
  360. case PacketType.AgentSetAppearance:
  361. AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
  362. // Console.WriteLine(appear.ToString());
  363. this.ClientAvatar.SetAppearance(appear);
  364. break;
  365. case PacketType.ObjectAdd:
  366. m_world.AddNewPrim((ObjectAddPacket)Pack, this);
  367. break;
  368. case PacketType.ObjectLink:
  369. OpenSim.Framework.Console.MainConsole.Instance.WriteLine(Pack.ToString());
  370. ObjectLinkPacket link = (ObjectLinkPacket)Pack;
  371. uint parentprimid = 0;
  372. OpenSim.world.Primitive parentprim = null;
  373. if (link.ObjectData.Length > 1)
  374. {
  375. parentprimid = link.ObjectData[0].ObjectLocalID;
  376. foreach (Entity ent in m_world.Entities.Values)
  377. {
  378. if (ent.localid == parentprimid)
  379. {
  380. parentprim = (OpenSim.world.Primitive)ent;
  381. }
  382. }
  383. for (int i = 1; i < link.ObjectData.Length; i++)
  384. {
  385. foreach (Entity ent in m_world.Entities.Values)
  386. {
  387. if (ent.localid == link.ObjectData[i].ObjectLocalID)
  388. {
  389. ((OpenSim.world.Primitive)ent).MakeParent(parentprim);
  390. }
  391. }
  392. }
  393. }
  394. break;
  395. case PacketType.ObjectScale:
  396. OpenSim.Framework.Console.MainConsole.Instance.WriteLine(Pack.ToString());
  397. break;
  398. case PacketType.ObjectShape:
  399. ObjectShapePacket shape = (ObjectShapePacket)Pack;
  400. for (int i = 0; i < shape.ObjectData.Length; i++)
  401. {
  402. foreach (Entity ent in m_world.Entities.Values)
  403. {
  404. if (ent.localid == shape.ObjectData[i].ObjectLocalID)
  405. {
  406. ((OpenSim.world.Primitive)ent).UpdateShape(shape.ObjectData[i]);
  407. }
  408. }
  409. }
  410. break;
  411. case PacketType.RequestImage:
  412. RequestImagePacket imageRequest = (RequestImagePacket)Pack;
  413. for (int i = 0; i < imageRequest.RequestImage.Length; i++)
  414. {
  415. m_assetCache.AddTextureRequest(this, imageRequest.RequestImage[i].Image);
  416. }
  417. break;
  418. case PacketType.TransferRequest:
  419. //Console.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request");
  420. TransferRequestPacket transfer = (TransferRequestPacket)Pack;
  421. m_assetCache.AddAssetRequest(this, transfer);
  422. break;
  423. case PacketType.AgentUpdate:
  424. ClientAvatar.HandleUpdate((AgentUpdatePacket)Pack);
  425. break;
  426. case PacketType.ObjectImage:
  427. ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
  428. for (int i = 0; i < imagePack.ObjectData.Length; i++)
  429. {
  430. foreach (Entity ent in m_world.Entities.Values)
  431. {
  432. if (ent.localid == imagePack.ObjectData[i].ObjectLocalID)
  433. {
  434. ((OpenSim.world.Primitive)ent).UpdateTexture(imagePack.ObjectData[i].TextureEntry);
  435. }
  436. }
  437. }
  438. break;
  439. case PacketType.ObjectFlagUpdate:
  440. ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
  441. foreach (Entity ent in m_world.Entities.Values)
  442. {
  443. if (ent.localid == flags.AgentData.ObjectLocalID)
  444. {
  445. ((OpenSim.world.Primitive)ent).UpdateObjectFlags(flags);
  446. }
  447. }
  448. break;
  449. case PacketType.AssetUploadRequest:
  450. AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
  451. this.UploadAssets.HandleUploadPacket(request, request.AssetBlock.TransactionID.Combine(this.SecureSessionID));
  452. break;
  453. case PacketType.RequestXfer:
  454. //Console.WriteLine(Pack.ToString());
  455. break;
  456. case PacketType.SendXferPacket:
  457. this.UploadAssets.HandleXferPacket((SendXferPacketPacket)Pack);
  458. break;
  459. case PacketType.CreateInventoryFolder:
  460. CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
  461. m_inventoryCache.CreateNewInventoryFolder(this, invFolder.FolderData.FolderID, (ushort)invFolder.FolderData.Type, Util.FieldToString(invFolder.FolderData.Name), invFolder.FolderData.ParentID);
  462. //Console.WriteLine(Pack.ToString());
  463. break;
  464. case PacketType.CreateInventoryItem:
  465. //Console.WriteLine(Pack.ToString());
  466. CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
  467. if (createItem.InventoryBlock.TransactionID != LLUUID.Zero)
  468. {
  469. this.UploadAssets.CreateInventoryItem(createItem);
  470. }
  471. else
  472. {
  473. // Console.Write(Pack.ToString());
  474. this.CreateInventoryItem(createItem);
  475. }
  476. break;
  477. case PacketType.FetchInventory:
  478. //Console.WriteLine("fetch item packet");
  479. FetchInventoryPacket FetchInventory = (FetchInventoryPacket)Pack;
  480. m_inventoryCache.FetchInventory(this, FetchInventory);
  481. break;
  482. case PacketType.FetchInventoryDescendents:
  483. FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
  484. m_inventoryCache.FetchInventoryDescendents(this, Fetch);
  485. break;
  486. case PacketType.UpdateInventoryItem:
  487. UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack;
  488. //Console.WriteLine(Pack.ToString());
  489. for (int i = 0; i < update.InventoryData.Length; i++)
  490. {
  491. if (update.InventoryData[i].TransactionID != LLUUID.Zero)
  492. {
  493. AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionID));
  494. if (asset != null)
  495. {
  496. // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToStringHyphenated() + " already in cache");
  497. m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
  498. }
  499. else
  500. {
  501. asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID);
  502. if (asset != null)
  503. {
  504. //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToStringHyphenated() + " to cache");
  505. m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
  506. }
  507. else
  508. {
  509. //Console.WriteLine("trying to update inventory item, but asset is null");
  510. }
  511. }
  512. }
  513. else
  514. {
  515. m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ;
  516. }
  517. }
  518. break;
  519. case PacketType.ViewerEffect:
  520. ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
  521. foreach (SimClient client in m_clientThreads.Values)
  522. {
  523. if (client.AgentID != this.AgentID)
  524. {
  525. viewer.AgentData.AgentID = client.AgentID;
  526. viewer.AgentData.SessionID = client.SessionID;
  527. client.OutPacket(viewer);
  528. }
  529. }
  530. break;
  531. case PacketType.RequestTaskInventory:
  532. // Console.WriteLine(Pack.ToString());
  533. RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
  534. ReplyTaskInventoryPacket replytask = new ReplyTaskInventoryPacket();
  535. bool foundent = false;
  536. foreach (Entity ent in m_world.Entities.Values)
  537. {
  538. if (ent.localid == requesttask.InventoryData.LocalID)
  539. {
  540. replytask.InventoryData.TaskID = ent.uuid;
  541. replytask.InventoryData.Serial = 0;
  542. replytask.InventoryData.Filename = new byte[0];
  543. foundent = true;
  544. }
  545. }
  546. if (foundent)
  547. {
  548. this.OutPacket(replytask);
  549. }
  550. break;
  551. case PacketType.UpdateTaskInventory:
  552. // Console.WriteLine(Pack.ToString());
  553. UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
  554. AgentInventory myinventory = this.m_inventoryCache.GetAgentsInventory(this.AgentID);
  555. if (myinventory != null)
  556. {
  557. if (updatetask.UpdateData.Key == 0)
  558. {
  559. if (myinventory.InventoryItems[updatetask.InventoryData.ItemID] != null)
  560. {
  561. if (myinventory.InventoryItems[updatetask.InventoryData.ItemID].Type == 7)
  562. {
  563. LLUUID noteaid = myinventory.InventoryItems[updatetask.InventoryData.ItemID].AssetID;
  564. AssetBase assBase = this.m_assetCache.GetAsset(noteaid);
  565. if (assBase != null)
  566. {
  567. foreach (Entity ent in m_world.Entities.Values)
  568. {
  569. if (ent.localid == updatetask.UpdateData.LocalID)
  570. {
  571. if (ent is OpenSim.world.Primitive)
  572. {
  573. this.m_world.AddScript(ent, Util.FieldToString(assBase.Data));
  574. }
  575. }
  576. }
  577. }
  578. }
  579. }
  580. }
  581. }
  582. break;
  583. case PacketType.AgentAnimation:
  584. if (!m_child)
  585. {
  586. AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
  587. for (int i = 0; i < AgentAni.AnimationList.Length; i++)
  588. {
  589. if (AgentAni.AnimationList[i].StartAnim)
  590. {
  591. ClientAvatar.current_anim = AgentAni.AnimationList[i].AnimID;
  592. ClientAvatar.anim_seq = 1;
  593. ClientAvatar.SendAnimPack();
  594. }
  595. }
  596. }
  597. break;
  598. case PacketType.ObjectSelect:
  599. ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
  600. for (int i = 0; i < incomingselect.ObjectData.Length; i++)
  601. {
  602. foreach (Entity ent in m_world.Entities.Values)
  603. {
  604. if (ent.localid == incomingselect.ObjectData[i].ObjectLocalID)
  605. {
  606. ((OpenSim.world.Primitive)ent).GetProperites(this);
  607. break;
  608. }
  609. }
  610. }
  611. break;
  612. }
  613. }
  614. }
  615. private void ResendUnacked()
  616. {
  617. int now = Environment.TickCount;
  618. lock (NeedAck)
  619. {
  620. foreach (Packet packet in NeedAck.Values)
  621. {
  622. if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
  623. {
  624. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Resending " + packet.Type.ToString() + " packet, " +
  625. (now - packet.TickCount) + "ms have passed");
  626. packet.Header.Resent = true;
  627. OutPacket(packet);
  628. }
  629. }
  630. }
  631. }
  632. private void SendAcks()
  633. {
  634. lock (PendingAcks)
  635. {
  636. if (PendingAcks.Count > 0)
  637. {
  638. if (PendingAcks.Count > 250)
  639. {
  640. // FIXME: Handle the odd case where we have too many pending ACKs queued up
  641. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Too many ACKs queued up!");
  642. return;
  643. }
  644. //OpenSim.Framework.Console.MainConsole.Instance.WriteLine("Sending PacketAck");
  645. int i = 0;
  646. PacketAckPacket acks = new PacketAckPacket();
  647. acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
  648. foreach (uint ack in PendingAcks.Values)
  649. {
  650. acks.Packets[i] = new PacketAckPacket.PacketsBlock();
  651. acks.Packets[i].ID = ack;
  652. i++;
  653. }
  654. acks.Header.Reliable = false;
  655. OutPacket(acks);
  656. PendingAcks.Clear();
  657. }
  658. }
  659. }
  660. private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
  661. {
  662. SendAcks();
  663. ResendUnacked();
  664. }
  665. protected virtual void ProcessOutPacket(Packet Pack)
  666. {
  667. // Keep track of when this packet was sent out
  668. Pack.TickCount = Environment.TickCount;
  669. if (!Pack.Header.Resent)
  670. {
  671. // Set the sequence number
  672. lock (SequenceLock)
  673. {
  674. if (Sequence >= MAX_SEQUENCE)
  675. Sequence = 1;
  676. else
  677. Sequence++;
  678. Pack.Header.Sequence = Sequence;
  679. }
  680. if (Pack.Header.Reliable) //DIRTY HACK
  681. {
  682. lock (NeedAck)
  683. {
  684. if (!NeedAck.ContainsKey(Pack.Header.Sequence))
  685. {
  686. try
  687. {
  688. NeedAck.Add(Pack.Header.Sequence, Pack);
  689. }
  690. catch (Exception e) // HACKY
  691. {
  692. e.ToString();
  693. // Ignore
  694. // Seems to throw a exception here occasionally
  695. // of 'duplicate key' despite being locked.
  696. // !?!?!?
  697. }
  698. }
  699. else
  700. {
  701. // Client.Log("Attempted to add a duplicate sequence number (" +
  702. // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
  703. // packet.Type.ToString(), Helpers.LogLevel.Warning);
  704. }
  705. }
  706. // Don't append ACKs to resent packets, in case that's what was causing the
  707. // delivery to fail
  708. if (!Pack.Header.Resent)
  709. {
  710. // Append any ACKs that need to be sent out to this packet
  711. lock (PendingAcks)
  712. {
  713. if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
  714. Pack.Type != PacketType.PacketAck &&
  715. Pack.Type != PacketType.LogoutRequest)
  716. {
  717. Pack.Header.AckList = new uint[PendingAcks.Count];
  718. int i = 0;
  719. foreach (uint ack in PendingAcks.Values)
  720. {
  721. Pack.Header.AckList[i] = ack;
  722. i++;
  723. }
  724. PendingAcks.Clear();
  725. Pack.Header.AppendedAcks = true;
  726. }
  727. }
  728. }
  729. }
  730. }
  731. byte[] ZeroOutBuffer = new byte[4096];
  732. byte[] sendbuffer;
  733. sendbuffer = Pack.ToBytes();
  734. try
  735. {
  736. if (Pack.Header.Zerocoded)
  737. {
  738. int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
  739. m_application.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, CircuitCode);//userEP);
  740. }
  741. else
  742. {
  743. m_application.SendPacketTo(sendbuffer, sendbuffer.Length, SocketFlags.None, CircuitCode); //userEP);
  744. }
  745. }
  746. catch (Exception)
  747. {
  748. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
  749. ClientThread.Abort();
  750. }
  751. }
  752. public virtual void InPacket(Packet NewPack)
  753. {
  754. // Handle appended ACKs
  755. if (NewPack.Header.AppendedAcks)
  756. {
  757. lock (NeedAck)
  758. {
  759. foreach (uint ack in NewPack.Header.AckList)
  760. {
  761. NeedAck.Remove(ack);
  762. }
  763. }
  764. }
  765. // Handle PacketAck packets
  766. if (NewPack.Type == PacketType.PacketAck)
  767. {
  768. PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
  769. lock (NeedAck)
  770. {
  771. foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
  772. {
  773. NeedAck.Remove(block.ID);
  774. }
  775. }
  776. }
  777. else if ((NewPack.Type == PacketType.StartPingCheck))
  778. {
  779. //reply to pingcheck
  780. libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
  781. libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
  782. endPing.PingID.PingID = startPing.PingID.PingID;
  783. OutPacket(endPing);
  784. }
  785. else
  786. {
  787. QueItem item = new QueItem();
  788. item.Packet = NewPack;
  789. item.Incoming = true;
  790. this.PacketQueue.Enqueue(item);
  791. }
  792. }
  793. public virtual void OutPacket(Packet NewPack)
  794. {
  795. QueItem item = new QueItem();
  796. item.Packet = NewPack;
  797. item.Incoming = false;
  798. this.PacketQueue.Enqueue(item);
  799. }
  800. protected virtual void ClientLoop()
  801. {
  802. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop");
  803. while (true)
  804. {
  805. QueItem nextPacket = PacketQueue.Dequeue();
  806. if (nextPacket.Incoming)
  807. {
  808. //is a incoming packet
  809. ProcessInPacket(nextPacket.Packet);
  810. }
  811. else
  812. {
  813. //is a out going packet
  814. ProcessOutPacket(nextPacket.Packet);
  815. }
  816. }
  817. }
  818. protected virtual void InitNewClient()
  819. {
  820. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world");
  821. m_world.AddViewerAgent(this);
  822. world.Entity tempent = m_world.Entities[this.AgentID];
  823. this.ClientAvatar = (world.Avatar)tempent;
  824. }
  825. protected virtual void AuthUser()
  826. {
  827. AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
  828. if (!sessionInfo.Authorised)
  829. {
  830. //session/circuit not authorised
  831. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString());
  832. ClientThread.Abort();
  833. }
  834. else
  835. {
  836. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString());
  837. //session is authorised
  838. this.AgentID = cirpack.CircuitCode.ID;
  839. this.SessionID = cirpack.CircuitCode.SessionID;
  840. this.CircuitCode = cirpack.CircuitCode.Code;
  841. InitNewClient(); //shouldn't be called here as we might be a child agent and not want a full avatar
  842. this.ClientAvatar.firstname = sessionInfo.LoginInfo.First;
  843. this.ClientAvatar.lastname = sessionInfo.LoginInfo.Last;
  844. if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero)
  845. {
  846. this.SecureSessionID = sessionInfo.LoginInfo.SecureSession;
  847. }
  848. // Create Inventory, currently only works for sandbox mode
  849. if (m_sandboxMode)
  850. {
  851. AgentInventory inventory = null;
  852. if (sessionInfo.LoginInfo.InventoryFolder != null)
  853. {
  854. inventory = this.CreateInventory(sessionInfo.LoginInfo.InventoryFolder);
  855. if (sessionInfo.LoginInfo.BaseFolder != null)
  856. {
  857. if (!inventory.HasFolder(sessionInfo.LoginInfo.BaseFolder))
  858. {
  859. m_inventoryCache.CreateNewInventoryFolder(this, sessionInfo.LoginInfo.BaseFolder);
  860. }
  861. this.newAssetFolder = sessionInfo.LoginInfo.BaseFolder;
  862. AssetBase[] inventorySet = m_assetCache.CreateNewInventorySet(this.AgentID);
  863. if (inventorySet != null)
  864. {
  865. for (int i = 0; i < inventorySet.Length; i++)
  866. {
  867. if (inventorySet[i] != null)
  868. {
  869. m_inventoryCache.AddNewInventoryItem(this, sessionInfo.LoginInfo.BaseFolder, inventorySet[i]);
  870. }
  871. }
  872. }
  873. }
  874. }
  875. }
  876. ClientLoop();
  877. }
  878. }
  879. #region Packet handlers
  880. protected virtual bool Logout(SimClient simClient, Packet packet)
  881. {
  882. OpenSim.Framework.Console.MainConsole.Instance.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request");
  883. //send reply to let the client logout
  884. LogoutReplyPacket logReply = new LogoutReplyPacket();
  885. logReply.AgentData.AgentID = this.AgentID;
  886. logReply.AgentData.SessionID = this.SessionID;
  887. logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
  888. logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
  889. logReply.InventoryData[0].ItemID = LLUUID.Zero;
  890. OutPacket(logReply);
  891. //tell all clients to kill our object
  892. KillObjectPacket kill = new KillObjectPacket();
  893. kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
  894. kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
  895. kill.ObjectData[0].ID = this.ClientAvatar.localid;
  896. foreach (SimClient client in m_clientThreads.Values)
  897. {
  898. client.OutPacket(kill);
  899. }
  900. if (this.m_userServer != null)
  901. {
  902. this.m_inventoryCache.ClientLeaving(this.AgentID, this.m_userServer);
  903. }
  904. else
  905. {
  906. this.m_inventoryCache.ClientLeaving(this.AgentID, null);
  907. }
  908. m_gridServer.LogoutSession(this.SessionID, this.AgentID, this.CircuitCode);
  909. /*lock (m_world.Entities)
  910. {
  911. m_world.Entities.Remove(this.AgentID);
  912. }*/
  913. m_world.RemoveViewerAgent(this);
  914. //need to do other cleaning up here too
  915. m_clientThreads.Remove(this.CircuitCode);
  916. m_application.RemoveClientCircuit(this.CircuitCode);
  917. this.ClientThread.Abort();
  918. return true;
  919. }
  920. protected bool AgentTextureCached(SimClient simclient, Packet packet)
  921. {
  922. // Console.WriteLine(packet.ToString());
  923. AgentCachedTexturePacket chechedtex = (AgentCachedTexturePacket)packet;
  924. AgentCachedTextureResponsePacket cachedresp = new AgentCachedTextureResponsePacket();
  925. cachedresp.AgentData.AgentID = this.AgentID;
  926. cachedresp.AgentData.SessionID = this.SessionID;
  927. cachedresp.AgentData.SerialNum = this.cachedtextureserial;
  928. this.cachedtextureserial++;
  929. cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[chechedtex.WearableData.Length];
  930. for (int i = 0; i < chechedtex.WearableData.Length; i++)
  931. {
  932. cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
  933. cachedresp.WearableData[i].TextureIndex = chechedtex.WearableData[i].TextureIndex;
  934. cachedresp.WearableData[i].TextureID = LLUUID.Zero;
  935. cachedresp.WearableData[i].HostName = new byte[0];
  936. }
  937. this.OutPacket(cachedresp);
  938. return true;
  939. }
  940. protected bool MultipleObjUpdate(SimClient simClient, Packet packet)
  941. {
  942. MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
  943. for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
  944. {
  945. if (multipleupdate.ObjectData[i].Type == 9) //change position
  946. {
  947. libsecondlife.LLVector3 pos = new LLVector3(multipleupdate.ObjectData[i].Data, 0);
  948. foreach (Entity ent in m_world.Entities.Values)
  949. {
  950. if (ent.localid == multipleupdate.ObjectData[i].ObjectLocalID)
  951. {
  952. ((OpenSim.world.Primitive)ent).UpdatePosition(pos);
  953. }
  954. }
  955. //should update stored position of the prim
  956. }
  957. else if (multipleupdate.ObjectData[i].Type == 10)//rotation
  958. {
  959. libsecondlife.LLQuaternion rot = new LLQuaternion(multipleupdate.ObjectData[i].Data, 0, true);
  960. foreach (Entity ent in m_world.Entities.Values)
  961. {
  962. if (ent.localid == multipleupdate.ObjectData[i].ObjectLocalID)
  963. {
  964. ent.rotation = new Axiom.MathLib.Quaternion(rot.W, rot.X, rot.Y, rot.Z);
  965. ((OpenSim.world.Primitive)ent).UpdateFlag = true;
  966. }
  967. }
  968. }
  969. else if (multipleupdate.ObjectData[i].Type == 13)//scale
  970. {
  971. libsecondlife.LLVector3 scale = new LLVector3(multipleupdate.ObjectData[i].Data, 12);
  972. foreach (Entity ent in m_world.Entities.Values)
  973. {
  974. if (ent.localid == multipleupdate.ObjectData[i].ObjectLocalID)
  975. {
  976. ((OpenSim.world.Primitive)ent).Scale = scale;
  977. }
  978. }
  979. }
  980. }
  981. return true;
  982. }
  983. #endregion
  984. private AgentInventory CreateInventory(LLUUID baseFolder)
  985. {
  986. AgentInventory inventory = null;
  987. if (this.m_userServer != null)
  988. {
  989. // a user server is set so request the inventory from it
  990. Console.WriteLine("getting inventory from user server");
  991. inventory = m_inventoryCache.FetchAgentsInventory(this.AgentID, m_userServer);
  992. }
  993. else
  994. {
  995. inventory = new AgentInventory();
  996. inventory.AgentID = this.AgentID;
  997. inventory.CreateRootFolder(this.AgentID, false);
  998. m_inventoryCache.AddNewAgentsInventory(inventory);
  999. m_inventoryCache.CreateNewInventoryFolder(this, baseFolder);
  1000. }
  1001. return inventory;
  1002. }
  1003. private void CreateInventoryItem(CreateInventoryItemPacket packet)
  1004. {
  1005. if (packet.InventoryBlock.Type == 7)
  1006. {
  1007. //lets try this out with creating a notecard
  1008. AssetBase asset = new AssetBase();
  1009. asset.Name = Util.FieldToString(packet.InventoryBlock.Name);
  1010. asset.Description = Util.FieldToString(packet.InventoryBlock.Description);
  1011. asset.InvType = packet.InventoryBlock.InvType;
  1012. asset.Type = packet.InventoryBlock.Type;
  1013. asset.FullID = LLUUID.Random();
  1014. asset.Data = new byte[0];
  1015. m_assetCache.AddAsset(asset);
  1016. m_inventoryCache.AddNewInventoryItem(this, packet.InventoryBlock.FolderID, asset);
  1017. }
  1018. }
  1019. }
  1020. }