aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/OpenSim.RegionServer/Client/ClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/OpenSim.RegionServer/Client/ClientView.cs')
-rw-r--r--OpenSim/OpenSim.RegionServer/Client/ClientView.cs459
1 files changed, 459 insertions, 0 deletions
diff --git a/OpenSim/OpenSim.RegionServer/Client/ClientView.cs b/OpenSim/OpenSim.RegionServer/Client/ClientView.cs
new file mode 100644
index 0000000..6d7c3f2
--- /dev/null
+++ b/OpenSim/OpenSim.RegionServer/Client/ClientView.cs
@@ -0,0 +1,459 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.org/
3* See CONTRIBUTORS.TXT for a full list of copyright holders.
4*
5* Redistribution and use in source and binary forms, with or without
6* modification, are permitted provided that the following conditions are met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above copyright
10* notice, this list of conditions and the following disclaimer in the
11* documentation and/or other materials provided with the distribution.
12* * Neither the name of the OpenSim Project nor the
13* names of its contributors may be used to endorse or promote products
14* derived from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
17* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*
27*/
28
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using libsecondlife;
33using libsecondlife.Packets;
34using Nwc.XmlRpc;
35using System.Net;
36using System.Net.Sockets;
37using System.IO;
38using System.Threading;
39using System.Timers;
40using OpenSim.Framework.Interfaces;
41using OpenSim.Framework.Types;
42using OpenSim.Framework.Inventory;
43using OpenSim.Framework.Utilities;
44using OpenSim.RegionServer.Simulator;
45using OpenSim.RegionServer.Assets;
46using OpenSim.Framework.Console;
47
48namespace OpenSim.RegionServer.Client
49{
50 public delegate bool PacketMethod(ClientView simClient, Packet packet);
51
52 /// <summary>
53 /// Handles new client connections
54 /// Constructor takes a single Packet and authenticates everything
55 /// </summary>
56 public partial class ClientView : ClientViewBase, IClientAPI
57 {
58 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
59 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); //local handlers for this instance
60
61 public LLUUID AgentID;
62 public LLUUID SessionID;
63 public LLUUID SecureSessionID = LLUUID.Zero;
64 public bool m_child;
65 public Simulator.Avatar ClientAvatar;
66 private UseCircuitCodePacket cirpack;
67 public Thread ClientThread;
68 public LLVector3 startpos;
69
70 private AgentAssetUpload UploadAssets;
71 private LLUUID newAssetFolder = LLUUID.Zero;
72 private bool debug = false;
73 private World m_world;
74 private Dictionary<uint, ClientView> m_clientThreads;
75 private AssetCache m_assetCache;
76 private IGridServer m_gridServer;
77 private IUserServer m_userServer = null;
78 private InventoryCache m_inventoryCache;
79 public bool m_sandboxMode;
80 private int cachedtextureserial = 0;
81 private RegionInfo m_regionData;
82 protected AuthenticateSessionsBase m_authenticateSessionsHandler;
83
84 public IUserServer UserServer
85 {
86 set
87 {
88 this.m_userServer = value;
89 }
90 }
91
92 public LLVector3 StartPos
93 {
94 get
95 {
96 return startpos;
97 }
98 set
99 {
100 startpos = value;
101 }
102 }
103
104 public ClientView(EndPoint remoteEP, UseCircuitCodePacket initialcirpack, World world, Dictionary<uint, ClientView> clientThreads, AssetCache assetCache, IGridServer gridServer, OpenSimNetworkHandler application, InventoryCache inventoryCache, bool sandboxMode, bool child, RegionInfo regionDat, AuthenticateSessionsBase authenSessions)
105 {
106 m_world = world;
107 m_clientThreads = clientThreads;
108 m_assetCache = assetCache;
109 m_gridServer = gridServer;
110 m_networkServer = application;
111 m_inventoryCache = inventoryCache;
112 m_sandboxMode = sandboxMode;
113 m_child = child;
114 m_regionData = regionDat;
115 m_authenticateSessionsHandler = authenSessions;
116 MainConsole.Instance.Notice("OpenSimClient.cs - Started up new client thread to handle incoming request");
117 cirpack = initialcirpack;
118 userEP = remoteEP;
119
120 if (m_gridServer.GetName() == "Remote")
121 {
122 this.m_child = m_authenticateSessionsHandler.GetAgentChildStatus(initialcirpack.CircuitCode.Code);
123 this.startpos = m_authenticateSessionsHandler.GetPosition(initialcirpack.CircuitCode.Code);
124
125 // Dont rez new users underground
126 float aboveGround = 3.0f; // rez at least 3 meters above ground
127 if (this.startpos.Z < (m_world.Terrain[(int)this.startpos.X, (int)this.startpos.Y] + aboveGround))
128 this.startpos.Z = m_world.Terrain[(int)this.startpos.X, (int)this.startpos.Y] + aboveGround;
129
130 }
131 else
132 {
133 this.startpos = new LLVector3(128, 128, m_world.Terrain[(int)128, (int)128] + 15.0f); // new LLVector3(128.0f, 128.0f, 60f);
134 }
135
136 PacketQueue = new BlockingQueue<QueItem>();
137
138 this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
139 AckTimer = new System.Timers.Timer(500);
140 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
141 AckTimer.Start();
142
143 this.RegisterLocalPacketHandlers();
144
145
146 m_world.parcelManager.sendParcelOverlay(this);
147
148 ClientThread = new Thread(new ThreadStart(AuthUser));
149 ClientThread.IsBackground = true;
150 ClientThread.Start();
151 }
152
153 # region Client Methods
154 public void UpgradeClient()
155 {
156 MainConsole.Instance.Notice("SimClient.cs:UpgradeClient() - upgrading child to full agent");
157 this.m_child = false;
158 //this.m_world.RemoveViewerAgent(this);
159 if (!this.m_sandboxMode)
160 {
161 this.startpos = m_authenticateSessionsHandler.GetPosition(CircuitCode);
162 m_authenticateSessionsHandler.UpdateAgentChildStatus(CircuitCode, false);
163 }
164 OnChildAgentStatus(this.m_child);
165 //this.InitNewClient();
166 }
167
168 public void DowngradeClient()
169 {
170 MainConsole.Instance.Notice("SimClient.cs:UpgradeClient() - changing full agent to child");
171 this.m_child = true;
172 OnChildAgentStatus(this.m_child);
173 //this.m_world.RemoveViewerAgent(this);
174 //this.m_world.AddViewerAgent(this);
175 }
176
177 public void KillClient()
178 {
179 KillObjectPacket kill = new KillObjectPacket();
180 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
181 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
182 kill.ObjectData[0].ID = this.ClientAvatar.localid;
183 foreach (ClientView client in m_clientThreads.Values)
184 {
185 client.OutPacket(kill);
186 }
187 if (this.m_userServer != null)
188 {
189 this.m_inventoryCache.ClientLeaving(this.AgentID, this.m_userServer);
190 }
191 else
192 {
193 this.m_inventoryCache.ClientLeaving(this.AgentID, null);
194 }
195
196 m_world.RemoveViewerAgent(this);
197
198 m_clientThreads.Remove(this.CircuitCode);
199 m_networkServer.RemoveClientCircuit(this.CircuitCode);
200 this.ClientThread.Abort();
201 }
202 #endregion
203
204 # region Packet Handling
205 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
206 {
207 bool result = false;
208 lock (PacketHandlers)
209 {
210 if (!PacketHandlers.ContainsKey(packetType))
211 {
212 PacketHandlers.Add(packetType, handler);
213 result = true;
214 }
215 }
216 return result;
217 }
218
219 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
220 {
221 bool result = false;
222 lock (m_packetHandlers)
223 {
224 if (!m_packetHandlers.ContainsKey(packetType))
225 {
226 m_packetHandlers.Add(packetType, handler);
227 result = true;
228 }
229 }
230 return result;
231 }
232
233 protected virtual bool ProcessPacketMethod(Packet packet)
234 {
235 bool result = false;
236 bool found = false;
237 PacketMethod method;
238 if (m_packetHandlers.TryGetValue(packet.Type, out method))
239 {
240 //there is a local handler for this packet type
241 result = method(this, packet);
242 }
243 else
244 {
245 //there is not a local handler so see if there is a Global handler
246 lock (PacketHandlers)
247 {
248 found = PacketHandlers.TryGetValue(packet.Type, out method);
249 }
250 if (found)
251 {
252 result = method(this, packet);
253 }
254 }
255 return result;
256 }
257
258 protected virtual void ClientLoop()
259 {
260 MainConsole.Instance.Notice("OpenSimClient.cs:ClientLoop() - Entered loop");
261 while (true)
262 {
263 QueItem nextPacket = PacketQueue.Dequeue();
264 if (nextPacket.Incoming)
265 {
266 //is a incoming packet
267 ProcessInPacket(nextPacket.Packet);
268 }
269 else
270 {
271 //is a out going packet
272 ProcessOutPacket(nextPacket.Packet);
273 }
274 }
275 }
276 # endregion
277
278 # region Setup
279
280 protected virtual void InitNewClient()
281 {
282 MainConsole.Instance.Notice("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world");
283 this.ClientAvatar = m_world.AddViewerAgent(this);
284 }
285
286 protected virtual void AuthUser()
287 {
288 // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
289 AuthenticateResponse sessionInfo = this.m_networkServer.AuthenticateSession(cirpack.CircuitCode.SessionID, cirpack.CircuitCode.ID, cirpack.CircuitCode.Code);
290 if (!sessionInfo.Authorised)
291 {
292 //session/circuit not authorised
293 OpenSim.Framework.Console.MainConsole.Instance.Notice("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString());
294 ClientThread.Abort();
295 }
296 else
297 {
298 OpenSim.Framework.Console.MainConsole.Instance.Notice("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString());
299 //session is authorised
300 this.AgentID = cirpack.CircuitCode.ID;
301 this.SessionID = cirpack.CircuitCode.SessionID;
302 this.CircuitCode = cirpack.CircuitCode.Code;
303 InitNewClient();
304 this.ClientAvatar.firstname = sessionInfo.LoginInfo.First;
305 this.ClientAvatar.lastname = sessionInfo.LoginInfo.Last;
306 if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero)
307 {
308 this.SecureSessionID = sessionInfo.LoginInfo.SecureSession;
309 }
310
311 // Create Inventory, currently only works for sandbox mode
312 if (m_sandboxMode)
313 {
314 this.SetupInventory(sessionInfo);
315 }
316
317 ClientLoop();
318 }
319 }
320 # endregion
321
322
323 protected override void KillThread()
324 {
325 this.ClientThread.Abort();
326 }
327
328 #region World/Avatar To Viewer Methods
329
330 public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID)
331 {
332 System.Text.Encoding enc = System.Text.Encoding.ASCII;
333 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket();
334 reply.ChatData.Audible = 1;
335 reply.ChatData.Message = message;
336 reply.ChatData.ChatType = type;
337 reply.ChatData.SourceType = 1;
338 reply.ChatData.Position = fromPos;
339 reply.ChatData.FromName = enc.GetBytes(fromName + "\0");
340 reply.ChatData.OwnerID = fromAgentID;
341 reply.ChatData.SourceID = fromAgentID;
342
343 this.OutPacket(reply);
344 }
345
346 public void SendAppearance(AvatarWearable[] wearables)
347 {
348 AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket();
349 aw.AgentData.AgentID = this.AgentID;
350 aw.AgentData.SerialNum = 0;
351 aw.AgentData.SessionID = this.SessionID;
352
353 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
354 AgentWearablesUpdatePacket.WearableDataBlock awb;
355 for (int i = 0; i < wearables.Length; i++)
356 {
357 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
358 awb.WearableType = (byte)i;
359 awb.AssetID = wearables[i].AssetID;
360 awb.ItemID = wearables[i].ItemID;
361 aw.WearableData[i] = awb;
362 }
363
364 this.OutPacket(aw);
365 }
366 #endregion
367
368 #region Inventory Creation
369 private void SetupInventory(AuthenticateResponse sessionInfo)
370 {
371 AgentInventory inventory = null;
372 if (sessionInfo.LoginInfo.InventoryFolder != null)
373 {
374 inventory = this.CreateInventory(sessionInfo.LoginInfo.InventoryFolder);
375 if (sessionInfo.LoginInfo.BaseFolder != null)
376 {
377 if (!inventory.HasFolder(sessionInfo.LoginInfo.BaseFolder))
378 {
379 m_inventoryCache.CreateNewInventoryFolder(this, sessionInfo.LoginInfo.BaseFolder);
380 }
381 this.newAssetFolder = sessionInfo.LoginInfo.BaseFolder;
382 AssetBase[] inventorySet = m_assetCache.CreateNewInventorySet(this.AgentID);
383 if (inventorySet != null)
384 {
385 for (int i = 0; i < inventorySet.Length; i++)
386 {
387 if (inventorySet[i] != null)
388 {
389 m_inventoryCache.AddNewInventoryItem(this, sessionInfo.LoginInfo.BaseFolder, inventorySet[i]);
390 }
391 }
392 }
393 }
394 }
395 }
396 private AgentInventory CreateInventory(LLUUID baseFolder)
397 {
398 AgentInventory inventory = null;
399 if (this.m_userServer != null)
400 {
401 // a user server is set so request the inventory from it
402 MainConsole.Instance.Verbose("getting inventory from user server");
403 inventory = m_inventoryCache.FetchAgentsInventory(this.AgentID, m_userServer);
404 }
405 else
406 {
407 inventory = new AgentInventory();
408 inventory.AgentID = this.AgentID;
409 inventory.CreateRootFolder(this.AgentID, false);
410 m_inventoryCache.AddNewAgentsInventory(inventory);
411 m_inventoryCache.CreateNewInventoryFolder(this, baseFolder);
412 }
413 return inventory;
414 }
415
416 private void CreateInventoryItem(CreateInventoryItemPacket packet)
417 {
418 if (!(packet.InventoryBlock.Type == 3 || packet.InventoryBlock.Type == 7))
419 {
420 MainConsole.Instance.Warn("Attempted to create " + Util.FieldToString(packet.InventoryBlock.Name) + " in inventory. Unsupported type");
421 return;
422 }
423
424 //lets try this out with creating a notecard
425 AssetBase asset = new AssetBase();
426
427 asset.Name = Util.FieldToString(packet.InventoryBlock.Name);
428 asset.Description = Util.FieldToString(packet.InventoryBlock.Description);
429 asset.InvType = packet.InventoryBlock.InvType;
430 asset.Type = packet.InventoryBlock.Type;
431 asset.FullID = LLUUID.Random();
432
433 switch (packet.InventoryBlock.Type)
434 {
435 case 7: // Notecard
436 asset.Data = new byte[0];
437 break;
438
439 case 3: // Landmark
440 String content;
441 content = "Landmark version 2\n";
442 content += "region_id " + m_regionData.SimUUID + "\n";
443 String strPos = String.Format("%.2f %.2f %.2f>",
444 this.ClientAvatar.Pos.X,
445 this.ClientAvatar.Pos.Y,
446 this.ClientAvatar.Pos.Z);
447 content += "local_pos " + strPos + "\n";
448 asset.Data = (new System.Text.ASCIIEncoding()).GetBytes(content);
449 break;
450 default:
451 break;
452 }
453 m_assetCache.AddAsset(asset);
454 m_inventoryCache.AddNewInventoryItem(this, packet.InventoryBlock.FolderID, asset);
455 }
456 #endregion
457
458 }
459}