aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMike Mazur2008-08-06 01:34:50 +0000
committerMike Mazur2008-08-06 01:34:50 +0000
commitf180fa57e7e6e62c361fa978a86d3a6e48bb889d (patch)
tree7fc771fa090b4a6aebddda68c4dfd84970047166
parentThanks, zaki, for a patch that embeds plugin manifest files into plugin dlls.... (diff)
downloadopensim-SC-f180fa57e7e6e62c361fa978a86d3a6e48bb889d.zip
opensim-SC-f180fa57e7e6e62c361fa978a86d3a6e48bb889d.tar.gz
opensim-SC-f180fa57e7e6e62c361fa978a86d3a6e48bb889d.tar.bz2
opensim-SC-f180fa57e7e6e62c361fa978a86d3a6e48bb889d.tar.xz
Create FunSLUDP client stack. At the moment it's only a copy of the LindenUDP
client stack.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs38
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs6315
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs702
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs567
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs150
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs93
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs45
-rw-r--r--OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs545
-rw-r--r--prebuild.xml36
9 files changed, 8491 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs
new file mode 100644
index 0000000..857ce13
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLClientStackNetworkHandler.cs
@@ -0,0 +1,38 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System.Net.Sockets;
29
30namespace OpenSim.Region.ClientStack.LindenUDP
31{
32 public interface LLClientStackNetworkHandler
33 {
34 void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode); // EndPoint packetSender);
35 void RemoveClientCircuit(uint circuitcode);
36 void RegisterPacketServer(LLPacketServer server);
37 }
38} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs
new file mode 100644
index 0000000..4e9b1ae
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLClientView.cs
@@ -0,0 +1,6315 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Net.Sockets;
32using System.Reflection;
33using System.Text;
34using System.Threading;
35using System.Timers;
36using Axiom.Math;
37using libsecondlife;
38using libsecondlife.Packets;
39using log4net;
40using OpenSim.Framework;
41using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Statistics;
43using OpenSim.Region.ClientStack.LindenUDP;
44using OpenSim.Region.Environment.Scenes;
45using Timer = System.Timers.Timer;
46
47namespace OpenSim.Region.ClientStack.LindenUDP
48{
49 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
50
51
52 /// <summary>
53 /// Handles new client connections
54 /// Constructor takes a single Packet and authenticates everything
55 /// </summary>
56 public class LLClientView : IClientAPI
57 {
58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 // ~ClientView()
61 // {
62 // m_log.Info("[CLIENTVIEW]: Destructor called");
63 // }
64
65 /* static variables */
66 public static TerrainManager TerrainManager = new TerrainManager(new SecondLife());
67
68 public static SynchronizeClientHandler SynchronizeClient = null;
69 /* private variables */
70 private readonly LLUUID m_sessionId;
71 private LLUUID m_secureSessionId = LLUUID.Zero;
72 //private AgentAssetUpload UploadAssets;
73 private int m_debug = 0;
74 private readonly AssetCache m_assetCache;
75 // private InventoryCache m_inventoryCache;
76 private int m_cachedTextureSerial = 0;
77 private Timer m_clientPingTimer;
78
79 private bool m_clientBlocked = false;
80
81 private int m_probesWithNoIngressPackets = 0;
82 //private int m_lastPacketsReceived = 0;
83 private byte[] ZeroOutBuffer = new byte[4096];
84
85 private readonly LLUUID m_agentId;
86 private readonly uint m_circuitCode;
87 private int m_moneyBalance;
88 private IPacketHandler m_PacketHandler;
89
90 private int m_animationSequenceNumber = 1;
91
92 private byte[] m_channelVersion = Helpers.StringToField("OpenSimulator 0.5"); // Dummy value needed by libSL
93
94 private Dictionary<string, LLUUID> m_defaultAnimations = new Dictionary<string, LLUUID>();
95
96 /* protected variables */
97
98 protected static Dictionary<PacketType, PacketMethod> PacketHandlers =
99 new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
100
101 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
102
103 protected IScene m_scene;
104 protected AgentCircuitManager m_authenticateSessionsHandler;
105
106 protected LLPacketServer m_networkServer;
107
108 /* public variables */
109 protected string m_firstName;
110 protected string m_lastName;
111 protected Thread m_clientThread;
112 protected LLVector3 m_startpos;
113 protected EndPoint m_userEndPoint;
114 protected EndPoint m_proxyEndPoint;
115 protected LLUUID m_activeGroupID = LLUUID.Zero;
116 protected string m_activeGroupName = String.Empty;
117 protected ulong m_activeGroupPowers = 0;
118 protected Dictionary<LLUUID,ulong> m_groupPowers = new Dictionary<LLUUID, ulong>();
119
120 /* Instantiated Designated Event Delegates */
121 //- used so we don't create new objects for each incoming packet and then toss it out later */
122
123 private RequestAvatarProperties handlerRequestAvatarProperties = null; //OnRequestAvatarProperties;
124 private UpdateAvatarProperties handlerUpdateAvatarProperties = null; // OnUpdateAvatarProperties;
125 private ChatMessage handlerChatFromViewer = null; //OnChatFromViewer;
126 private ChatMessage handlerChatFromViewer2 = null; //OnChatFromViewer;
127 private ImprovedInstantMessage handlerInstantMessage = null; //OnInstantMessage;
128 private FriendActionDelegate handlerApproveFriendRequest = null; //OnApproveFriendRequest;
129 private FriendshipTermination handlerTerminateFriendship = null; //OnTerminateFriendship;
130 private RezObject handlerRezObject = null; //OnRezObject;
131 private GenericCall4 handlerDeRezObject = null; //OnDeRezObject;
132 private ModifyTerrain handlerModifyTerrain = null;
133 private BakeTerrain handlerBakeTerrain = null;
134 private EstateChangeInfo handlerEstateChangeInfo = null;
135 private Action<IClientAPI> handlerRegionHandShakeReply = null; //OnRegionHandShakeReply;
136 private GenericCall2 handlerRequestWearables = null; //OnRequestWearables;
137 private Action<IClientAPI> handlerRequestAvatarsData = null; //OnRequestAvatarsData;
138 private SetAppearance handlerSetAppearance = null; //OnSetAppearance;
139 private AvatarNowWearing handlerAvatarNowWearing = null; //OnAvatarNowWearing;
140 private RezSingleAttachmentFromInv handlerRezSingleAttachment = null; //OnRezSingleAttachmentFromInv;
141 private UUIDNameRequest handlerDetachAttachmentIntoInv = null; // Detach attachment!
142 private ObjectAttach handlerObjectAttach = null; //OnObjectAttach;
143 private SetAlwaysRun handlerSetAlwaysRun = null; //OnSetAlwaysRun;
144 private GenericCall2 handlerCompleteMovementToRegion = null; //OnCompleteMovementToRegion;
145 private UpdateAgent handlerAgentUpdate = null; //OnAgentUpdate;
146 private StartAnim handlerStartAnim = null;
147 private StopAnim handlerStopAnim = null;
148 private AgentRequestSit handlerAgentRequestSit = null; //OnAgentRequestSit;
149 private AgentSit handlerAgentSit = null; //OnAgentSit;
150 private AvatarPickerRequest handlerAvatarPickerRequest = null; //OnAvatarPickerRequest;
151 private FetchInventory handlerAgentDataUpdateRequest = null; //OnAgentDataUpdateRequest;
152 private FetchInventory handlerUserInfoRequest = null; //OnUserInfoRequest;
153 private TeleportLocationRequest handlerSetStartLocationRequest = null; //OnSetStartLocationRequest;
154 private TeleportLandmarkRequest handlerTeleportLandmarkRequest = null; //OnTeleportLandmarkRequest;
155 private LinkObjects handlerLinkObjects = null; //OnLinkObjects;
156 private DelinkObjects handlerDelinkObjects = null; //OnDelinkObjects;
157 private AddNewPrim handlerAddPrim = null; //OnAddPrim;
158 private UpdateShape handlerUpdatePrimShape = null; //null;
159 private ObjectExtraParams handlerUpdateExtraParams = null; //OnUpdateExtraParams;
160 private ObjectDuplicate handlerObjectDuplicate = null;
161 private ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null;
162 private ObjectSelect handlerObjectSelect = null;
163 private ObjectDeselect handlerObjectDeselect = null;
164 private ObjectIncludeInSearch handlerObjectIncludeInSearch = null;
165 private UpdatePrimFlags handlerUpdatePrimFlags = null; //OnUpdatePrimFlags;
166 private UpdatePrimTexture handlerUpdatePrimTexture = null;
167 private UpdateVector handlerGrabObject = null; //OnGrabObject;
168 private MoveObject handlerGrabUpdate = null; //OnGrabUpdate;
169 private ObjectSelect handlerDeGrabObject = null; //OnDeGrabObject;
170 private GenericCall7 handlerObjectDescription = null;
171 private GenericCall7 handlerObjectName = null;
172 private ObjectPermissions handlerObjectPermissions = null;
173 private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = null; //OnRequestObjectPropertiesFamily;
174 private TextureRequest handlerTextureRequest = null;
175 private UDPAssetUploadRequest handlerAssetUploadRequest = null; //OnAssetUploadRequest;
176 private RequestXfer handlerRequestXfer = null; //OnRequestXfer;
177 private XferReceive handlerXferReceive = null; //OnXferReceive;
178 private ConfirmXfer handlerConfirmXfer = null; //OnConfirmXfer;
179 private CreateInventoryFolder handlerCreateInventoryFolder = null; //OnCreateNewInventoryFolder;
180 private UpdateInventoryFolder handlerUpdateInventoryFolder = null;
181 private MoveInventoryFolder handlerMoveInventoryFolder = null;
182 private CreateNewInventoryItem handlerCreateNewInventoryItem = null; //OnCreateNewInventoryItem;
183 private FetchInventory handlerFetchInventory = null;
184 private FetchInventoryDescendents handlerFetchInventoryDescendents = null; //OnFetchInventoryDescendents;
185 private PurgeInventoryDescendents handlerPurgeInventoryDescendents = null; //OnPurgeInventoryDescendents;
186 private UpdateInventoryItem handlerUpdateInventoryItem = null;
187 private CopyInventoryItem handlerCopyInventoryItem = null;
188 private MoveInventoryItem handlerMoveInventoryItem = null;
189 private RemoveInventoryItem handlerRemoveInventoryItem = null;
190 private RemoveInventoryFolder handlerRemoveInventoryFolder = null;
191 private RequestTaskInventory handlerRequestTaskInventory = null; //OnRequestTaskInventory;
192 private UpdateTaskInventory handlerUpdateTaskInventory = null; //OnUpdateTaskInventory;
193 private MoveTaskInventory handlerMoveTaskItem = null;
194 private RemoveTaskInventory handlerRemoveTaskItem = null; //OnRemoveTaskItem;
195 private RezScript handlerRezScript = null; //OnRezScript;
196 private RequestMapBlocks handlerRequestMapBlocks = null; //OnRequestMapBlocks;
197 private RequestMapName handlerMapNameRequest = null; //OnMapNameRequest;
198 private TeleportLocationRequest handlerTeleportLocationRequest = null; //OnTeleportLocationRequest;
199 private MoneyBalanceRequest handlerMoneyBalanceRequest = null; //OnMoneyBalanceRequest;
200 private UUIDNameRequest handlerNameRequest = null;
201 private ParcelAccessListRequest handlerParcelAccessListRequest = null; //OnParcelAccessListRequest;
202 private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = null; //OnParcelAccessListUpdateRequest;
203 private ParcelPropertiesRequest handlerParcelPropertiesRequest = null; //OnParcelPropertiesRequest;
204 private ParcelDivideRequest handlerParcelDivideRequest = null; //OnParcelDivideRequest;
205 private ParcelJoinRequest handlerParcelJoinRequest = null; //OnParcelJoinRequest;
206 private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = null; //OnParcelPropertiesUpdateRequest;
207 private ParcelSelectObjects handlerParcelSelectObjects = null; //OnParcelSelectObjects;
208 private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = null; //OnParcelObjectOwnerRequest;
209 private ParcelAbandonRequest handlerParcelAbandonRequest = null;
210 private ParcelReclaim handlerParcelReclaim = null;
211 private ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = null;
212 private RegionInfoRequest handlerRegionInfoRequest = null; //OnRegionInfoRequest;
213 private EstateCovenantRequest handlerEstateCovenantRequest = null; //OnEstateCovenantRequest;
214 private RequestGodlikePowers handlerReqGodlikePowers = null; //OnRequestGodlikePowers;
215 private GodKickUser handlerGodKickUser = null; //OnGodKickUser;
216 private ViewerEffectEventHandler handlerViewerEffect = null; //OnViewerEffect;
217 private Action<IClientAPI> handlerLogout = null; //OnLogout;
218 private MoneyTransferRequest handlerMoneyTransferRequest = null; //OnMoneyTransferRequest;
219 private ParcelBuy handlerParcelBuy = null;
220 private EconomyDataRequest handlerEconomoyDataRequest = null;
221
222 private UpdateVector handlerUpdatePrimSinglePosition = null; //OnUpdatePrimSinglePosition;
223 private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = null; //OnUpdatePrimSingleRotation;
224 private UpdateVector handlerUpdatePrimScale = null; //OnUpdatePrimScale;
225 private UpdateVector handlerUpdatePrimGroupScale = null; //OnUpdateGroupScale;
226 private UpdateVector handlerUpdateVector = null; //OnUpdatePrimGroupPosition;
227 private UpdatePrimRotation handlerUpdatePrimRotation = null; //OnUpdatePrimGroupRotation;
228 // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = null; //OnUpdatePrimGroupMouseRotation;
229 // private RequestAsset handlerRequestAsset = null; // OnRequestAsset;
230 private UUIDNameRequest handlerTeleportHomeRequest = null;
231
232 private ScriptAnswer handlerScriptAnswer = null;
233 private RequestPayPrice handlerRequestPayPrice = null;
234 private ObjectDeselect handlerObjectDetach = null;
235 private AgentSit handlerOnUndo = null;
236
237 private ForceReleaseControls handlerForceReleaseControls = null;
238
239 private GodLandStatRequest handlerLandStatRequest = null;
240
241 private UUIDNameRequest handlerUUIDGroupNameRequest = null;
242
243 private RequestObjectPropertiesFamily handlerObjectGroupRequest = null;
244 private ScriptReset handlerScriptReset = null;
245 private GetScriptRunning handlerGetScriptRunning = null;
246 private SetScriptRunning handlerSetScriptRunning = null;
247 private UpdateVector handlerAutoPilotGo = null;
248
249 //private TerrainUnacked handlerUnackedTerrain = null;
250
251 //**
252
253 /* Properties */
254
255 public LLUUID SecureSessionId
256 {
257 get { return m_secureSessionId; }
258 }
259
260 public IScene Scene
261 {
262 get { return m_scene; }
263 }
264
265 public LLUUID SessionId
266 {
267 get { return m_sessionId; }
268 }
269
270 public LLVector3 StartPos
271 {
272 get { return m_startpos; }
273 set { m_startpos = value; }
274 }
275
276 public LLUUID AgentId
277 {
278 get { return m_agentId; }
279 }
280
281 public LLUUID ActiveGroupId
282 {
283 get { return m_activeGroupID; }
284 }
285
286 public string ActiveGroupName
287 {
288 get { return m_activeGroupName; }
289 }
290
291 public ulong ActiveGroupPowers
292 {
293 get { return m_activeGroupPowers; }
294 }
295
296 public ulong GetGroupPowers(LLUUID groupID)
297 {
298 if(m_groupPowers.ContainsKey(groupID))
299 return m_groupPowers[groupID];
300 return 0;
301 }
302
303 /// <summary>
304 /// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
305 /// </summary>
306 public bool ChildAgentStatus()
307 {
308 return m_scene.PresenceChildStatus(AgentId);
309 }
310
311 /// <summary>
312 /// First name of the agent/avatar represented by the client
313 /// </summary>
314 public string FirstName
315 {
316 get { return m_firstName; }
317 }
318
319 /// <summary>
320 /// Last name of the agent/avatar represented by the client
321 /// </summary>
322 public string LastName
323 {
324 get { return m_lastName; }
325 }
326
327 /// <summary>
328 /// Full name of the client (first name and last name)
329 /// </summary>
330 public string Name
331 {
332 get { return FirstName + " " + LastName; }
333 }
334
335 public uint CircuitCode
336 {
337 get { return m_circuitCode; }
338 }
339
340 public int MoneyBalance
341 {
342 get { return m_moneyBalance; }
343 }
344
345 public int NextAnimationSequenceNumber
346 {
347 get { return m_animationSequenceNumber++; }
348 }
349
350 public IPacketHandler PacketHandler
351 {
352 get { return m_PacketHandler; }
353 }
354
355 bool m_IsActive = true;
356
357 public bool IsActive
358 {
359 get { return m_IsActive; }
360 set { m_IsActive = value; }
361 }
362
363 /* METHODS */
364
365 public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer,
366 AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP)
367 {
368 m_moneyBalance = 1000;
369
370 m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion());
371
372 InitDefaultAnimations();
373
374 m_scene = scene;
375 m_assetCache = assetCache;
376
377 m_networkServer = packServer;
378 // m_inventoryCache = inventoryCache;
379 m_authenticateSessionsHandler = authenSessions;
380
381 m_agentId = agentId;
382 m_sessionId = sessionId;
383 m_circuitCode = circuitCode;
384
385 m_userEndPoint = remoteEP;
386 m_proxyEndPoint = proxyEP;
387
388 m_startpos = m_authenticateSessionsHandler.GetPosition(circuitCode);
389
390 // While working on this, the BlockingQueue had me fooled for a bit.
391 // The Blocking queue causes the thread to stop until there's something
392 // in it to process. It's an on-purpose threadlock though because
393 // without it, the clientloop will suck up all sim resources.
394
395 m_PacketHandler = new LLPacketHandler(this);
396 m_PacketHandler.SynchronizeClient = SynchronizeClient;
397
398 RegisterLocalPacketHandlers();
399
400 m_clientThread = new Thread(new ThreadStart(AuthUser));
401 m_clientThread.Name = "ClientThread";
402 m_clientThread.IsBackground = true;
403 m_clientThread.Start();
404 ThreadTracker.Add(m_clientThread);
405
406 m_log.Info("[CLIENT]: Started up new thread to handle client UDP session");
407 }
408
409 public void SetDebug(int newDebug)
410 {
411 m_debug = newDebug;
412 }
413
414 # region Client Methods
415
416 private void CloseCleanup(bool shutdownCircuit)
417 {
418 m_scene.RemoveClient(AgentId);
419
420 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
421 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
422
423 // Send the STOP packet
424 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
425 OutPacket(disable, ThrottleOutPacketType.Unknown);
426
427 Thread.Sleep(2000);
428
429 // Shut down timers
430 m_clientPingTimer.Stop();
431
432 // This is just to give the client a reasonable chance of
433 // flushing out all it's packets. There should probably
434 // be a better mechanism here
435
436 // We can't reach into other scenes and close the connection
437 // We need to do this over grid communications
438 //m_scene.CloseAllAgents(CircuitCode);
439
440 // If we're not shutting down the circuit, then this is the last time we'll go here.
441 // If we are shutting down the circuit, the UDP Server will come back here with
442 // ShutDownCircuit = false
443 if (!(shutdownCircuit))
444 {
445 GC.Collect();
446 m_clientThread.Abort();
447 }
448 }
449
450 /// <summary>
451 /// Close down the client view. This *must* be the last method called, since the last #
452 /// statement of CloseCleanup() aborts the thread.
453 /// </summary>
454 /// <param name="shutdownCircuit"></param>
455 public void Close(bool shutdownCircuit)
456 {
457 // Pull Client out of Region
458 m_log.Info("[CLIENT]: Close has been called");
459 m_PacketHandler.Flush();
460
461 //raiseevent on the packet server to Shutdown the circuit
462 if (shutdownCircuit)
463 {
464 OnConnectionClosed(this);
465 }
466
467 CloseCleanup(shutdownCircuit);
468 }
469
470 public void Kick(string message)
471 {
472 if (!ChildAgentStatus())
473 {
474 KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
475 kupack.UserInfo.AgentID = AgentId;
476 kupack.UserInfo.SessionID = SessionId;
477 kupack.TargetBlock.TargetIP = (uint)0;
478 kupack.TargetBlock.TargetPort = (ushort)0;
479 kupack.UserInfo.Reason = Helpers.StringToField(message);
480 OutPacket(kupack, ThrottleOutPacketType.Task);
481 // You must sleep here or users get no message!
482 Thread.Sleep(500);
483 }
484 }
485
486 public void Stop()
487 {
488 // Shut down timers
489 m_clientPingTimer.Stop();
490 }
491
492 public void Restart()
493 {
494 // re-construct
495 m_PacketHandler.Clear();
496
497 m_clientPingTimer = new Timer(5000);
498 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity);
499 m_clientPingTimer.Enabled = true;
500 }
501
502 public void Terminate()
503 {
504 m_PacketHandler.Stop();
505
506 // wait for thread stoped
507 m_clientThread.Join();
508
509 // delete circuit code
510 m_networkServer.CloseClient(this);
511 }
512
513 #endregion
514
515 # region Packet Handling
516
517 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
518 {
519 bool result = false;
520 lock (PacketHandlers)
521 {
522 if (!PacketHandlers.ContainsKey(packetType))
523 {
524 PacketHandlers.Add(packetType, handler);
525 result = true;
526 }
527 }
528 return result;
529 }
530
531 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
532 {
533 bool result = false;
534 lock (m_packetHandlers)
535 {
536 if (!m_packetHandlers.ContainsKey(packetType))
537 {
538 m_packetHandlers.Add(packetType, handler);
539 result = true;
540 }
541 }
542 return result;
543 }
544
545 /// <summary>
546 /// Try to process a packet using registered packet handlers
547 /// </summary>
548 /// <param name="packet"></param>
549 /// <returns>True if a handler was found which successfully processed the packet.</returns>
550 protected virtual bool ProcessPacketMethod(Packet packet)
551 {
552 bool result = false;
553 bool found = false;
554 PacketMethod method;
555 if (m_packetHandlers.TryGetValue(packet.Type, out method))
556 {
557 //there is a local handler for this packet type
558 result = method(this, packet);
559 }
560 else
561 {
562 //there is not a local handler so see if there is a Global handler
563 lock (PacketHandlers)
564 {
565 found = PacketHandlers.TryGetValue(packet.Type, out method);
566 }
567 if (found)
568 {
569 result = method(this, packet);
570 }
571 }
572 return result;
573 }
574
575 protected void DebugPacket(string direction, Packet packet)
576 {
577 if (m_debug > 0)
578 {
579 string info = String.Empty;
580
581 if (m_debug < 255 && packet.Type == PacketType.AgentUpdate)
582 return;
583 if (m_debug < 254 && packet.Type == PacketType.ViewerEffect)
584 return;
585 if (m_debug < 253 && (
586 packet.Type == PacketType.CompletePingCheck ||
587 packet.Type == PacketType.StartPingCheck
588 ))
589 return;
590 if (m_debug < 252 && packet.Type == PacketType.PacketAck)
591 return;
592
593 if (m_debug > 1)
594 {
595 info = packet.ToString();
596 }
597 else
598 {
599 info = packet.Type.ToString();
600 }
601 Console.WriteLine(m_circuitCode + ":" + direction + ": " + info);
602 }
603 }
604
605 protected virtual void ClientLoop()
606 {
607 m_log.Info("[CLIENT]: Entered loop");
608 while (true)
609 {
610 LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue();
611 if (nextPacket == null)
612 {
613 m_log.Error("Got a NULL packet in Client Loop, bailing out of our client loop");
614 break;
615 }
616 if (nextPacket.Incoming)
617 {
618 DebugPacket("IN", nextPacket.Packet);
619 m_PacketHandler.ProcessInPacket(nextPacket.Packet);
620 }
621 else
622 {
623 DebugPacket("OUT", nextPacket.Packet);
624 ProcessOutPacket(nextPacket.Packet);
625 }
626 }
627 }
628
629 # endregion
630
631 protected int m_terrainCheckerCount = 0;
632 /// <summary>
633 /// Event handler for check client timer
634 /// checks to ensure that the client is still connected
635 /// </summary>
636 /// <param name="sender"></param>
637 /// <param name="e"></param>
638 protected void CheckClientConnectivity(object sender, ElapsedEventArgs e)
639 {
640 if (m_PacketHandler.PacketsReceived == m_PacketHandler.PacketsReceivedReported)
641 {
642 m_probesWithNoIngressPackets++;
643 if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) || (m_probesWithNoIngressPackets > 90 && m_clientBlocked))
644 {
645
646 if (OnConnectionClosed != null)
647 {
648 OnConnectionClosed(this);
649 }
650 }
651 else
652 {
653 // this will normally trigger at least one packet (ping response)
654 SendStartPingCheck(0);
655 }
656 }
657 else
658 {
659 // Something received in the meantime - we can reset the counters
660 m_probesWithNoIngressPackets = 0;
661 }
662
663 }
664
665 # region Setup
666
667 /// <summary>
668 /// Starts up the timers to check the client and resend unacked packets
669 /// Adds the client to the OpenSim.Region.Environment.Scenes.Scene
670 /// </summary>
671 protected virtual void InitNewClient()
672 {
673 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
674
675 // Establish our two timers. We could probably get this down to one
676
677 m_clientPingTimer = new Timer(5000);
678 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity);
679 m_clientPingTimer.Enabled = true;
680
681 m_scene.AddNewClient(this, true);
682 }
683
684 /// <summary>
685 /// Authorize an incoming user session. This method lies at the base of the entire client thread.
686 /// </summary>
687 protected virtual void AuthUser()
688 {
689
690 //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US)
691 //otherwise it will override this and use the system default
692 Culture.SetCurrentCulture();
693
694 try
695 {
696 // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(m_cirpack.m_circuitCode.m_sessionId, m_cirpack.m_circuitCode.ID, m_cirpack.m_circuitCode.Code);
697 AuthenticateResponse sessionInfo =
698 m_authenticateSessionsHandler.AuthenticateSession(m_sessionId, m_agentId,
699 m_circuitCode);
700 if (!sessionInfo.Authorised)
701 {
702 //session/circuit not authorised
703 m_log.WarnFormat(
704 "[CLIENT]: New user request denied to avatar {0} connecting with circuit code {1} from {2}",
705 m_agentId, m_circuitCode, m_userEndPoint);
706
707 m_PacketHandler.Stop();
708 m_clientThread.Abort();
709 }
710 else
711 {
712 m_log.Info("[CLIENT]: Got authenticated connection from " + m_userEndPoint.ToString());
713 //session is authorised
714 m_firstName = sessionInfo.LoginInfo.First;
715 m_lastName = sessionInfo.LoginInfo.Last;
716
717 if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero)
718 {
719 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
720 }
721
722 // This sets up all the timers
723 InitNewClient();
724
725 ClientLoop();
726 }
727 }
728 catch (Exception e)
729 {
730 if (e is ThreadAbortException)
731 throw e;
732
733 if (StatsManager.SimExtraStats != null)
734 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
735
736 // Don't let a failure in an individual client thread crash the whole sim.
737 m_log.ErrorFormat("[CLIENT]: Client thread for {0} {1} crashed. Logging them out. Exception {2}", Name, AgentId, e);
738
739 try
740 {
741 // Make an attempt to alert the user that their session has crashed
742 AgentAlertMessagePacket packet
743 = BuildAgentAlertPacket(
744 "Unfortunately the session for this client on the server has crashed.\n"
745 + "Any further actions taken will not be processed.\n"
746 + "Please relog", true);
747
748 ProcessOutPacket(packet);
749
750 // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to
751 // listeners yet, though.
752 Logout(this);
753 }
754 catch (Exception e2)
755 {
756 if (e2 is ThreadAbortException)
757 throw e2;
758
759 m_log.ErrorFormat("[CLIENT]: Further exception thrown on forced session logout. {0}", e2);
760 }
761 }
762 }
763
764 # endregion
765
766 // Previously ClientView.API partial class
767 public event Action<IClientAPI> OnLogout;
768 public event ObjectPermissions OnObjectPermissions;
769 public event Action<IClientAPI> OnConnectionClosed;
770 public event ViewerEffectEventHandler OnViewerEffect;
771 public event ImprovedInstantMessage OnInstantMessage;
772 public event ChatMessage OnChatFromViewer;
773 public event TextureRequest OnRequestTexture;
774 public event RezObject OnRezObject;
775 public event GenericCall4 OnDeRezObject;
776 public event ModifyTerrain OnModifyTerrain;
777 public event Action<IClientAPI> OnRegionHandShakeReply;
778 public event GenericCall2 OnRequestWearables;
779 public event SetAppearance OnSetAppearance;
780 public event AvatarNowWearing OnAvatarNowWearing;
781 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
782 public event UUIDNameRequest OnDetachAttachmentIntoInv;
783 public event ObjectAttach OnObjectAttach;
784 public event ObjectDeselect OnObjectDetach;
785 public event GenericCall2 OnCompleteMovementToRegion;
786 public event UpdateAgent OnAgentUpdate;
787 public event AgentRequestSit OnAgentRequestSit;
788 public event AgentSit OnAgentSit;
789 public event AvatarPickerRequest OnAvatarPickerRequest;
790 public event StartAnim OnStartAnim;
791 public event StopAnim OnStopAnim;
792 public event Action<IClientAPI> OnRequestAvatarsData;
793 public event LinkObjects OnLinkObjects;
794 public event DelinkObjects OnDelinkObjects;
795 public event UpdateVector OnGrabObject;
796 public event ObjectSelect OnDeGrabObject;
797 public event ObjectDuplicate OnObjectDuplicate;
798 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
799 public event MoveObject OnGrabUpdate;
800 public event AddNewPrim OnAddPrim;
801 public event RequestGodlikePowers OnRequestGodlikePowers;
802 public event GodKickUser OnGodKickUser;
803 public event ObjectExtraParams OnUpdateExtraParams;
804 public event UpdateShape OnUpdatePrimShape;
805 public event ObjectSelect OnObjectSelect;
806 public event ObjectDeselect OnObjectDeselect;
807 public event GenericCall7 OnObjectDescription;
808 public event GenericCall7 OnObjectName;
809 public event ObjectIncludeInSearch OnObjectIncludeInSearch;
810 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
811 public event UpdatePrimFlags OnUpdatePrimFlags;
812 public event UpdatePrimTexture OnUpdatePrimTexture;
813 public event UpdateVector OnUpdatePrimGroupPosition;
814 public event UpdateVector OnUpdatePrimSinglePosition;
815 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
816 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
817 public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
818 public event UpdateVector OnUpdatePrimScale;
819 public event UpdateVector OnUpdatePrimGroupScale;
820 public event StatusChange OnChildAgentStatus;
821 public event GenericCall2 OnStopMovement;
822 public event Action<LLUUID> OnRemoveAvatar;
823 public event RequestMapBlocks OnRequestMapBlocks;
824 public event RequestMapName OnMapNameRequest;
825 public event TeleportLocationRequest OnTeleportLocationRequest;
826 public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
827 public event DisconnectUser OnDisconnectUser;
828 public event RequestAvatarProperties OnRequestAvatarProperties;
829 public event SetAlwaysRun OnSetAlwaysRun;
830 public event FetchInventory OnAgentDataUpdateRequest;
831 public event FetchInventory OnUserInfoRequest;
832 public event TeleportLocationRequest OnSetStartLocationRequest;
833 public event UpdateAvatarProperties OnUpdateAvatarProperties;
834 public event CreateNewInventoryItem OnCreateNewInventoryItem;
835 public event CreateInventoryFolder OnCreateNewInventoryFolder;
836 public event UpdateInventoryFolder OnUpdateInventoryFolder;
837 public event MoveInventoryFolder OnMoveInventoryFolder;
838 public event FetchInventoryDescendents OnFetchInventoryDescendents;
839 public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
840 public event FetchInventory OnFetchInventory;
841 public event RequestTaskInventory OnRequestTaskInventory;
842 public event UpdateInventoryItem OnUpdateInventoryItem;
843 public event CopyInventoryItem OnCopyInventoryItem;
844 public event MoveInventoryItem OnMoveInventoryItem;
845 public event RemoveInventoryItem OnRemoveInventoryItem;
846 public event RemoveInventoryFolder OnRemoveInventoryFolder;
847 public event UDPAssetUploadRequest OnAssetUploadRequest;
848 public event XferReceive OnXferReceive;
849 public event RequestXfer OnRequestXfer;
850 public event ConfirmXfer OnConfirmXfer;
851 public event RezScript OnRezScript;
852 public event UpdateTaskInventory OnUpdateTaskInventory;
853 public event MoveTaskInventory OnMoveTaskItem;
854 public event RemoveTaskInventory OnRemoveTaskItem;
855 public event RequestAsset OnRequestAsset;
856 public event UUIDNameRequest OnNameFromUUIDRequest;
857 public event ParcelAccessListRequest OnParcelAccessListRequest;
858 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
859 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
860 public event ParcelDivideRequest OnParcelDivideRequest;
861 public event ParcelJoinRequest OnParcelJoinRequest;
862 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
863 public event ParcelSelectObjects OnParcelSelectObjects;
864 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
865 public event ParcelAbandonRequest OnParcelAbandonRequest;
866 public event ParcelReclaim OnParcelReclaim;
867 public event ParcelReturnObjectsRequest OnParcelReturnObjectsRequest;
868 public event RegionInfoRequest OnRegionInfoRequest;
869 public event EstateCovenantRequest OnEstateCovenantRequest;
870 public event FriendActionDelegate OnApproveFriendRequest;
871 public event FriendActionDelegate OnDenyFriendRequest;
872 public event FriendshipTermination OnTerminateFriendship;
873 public event MoneyTransferRequest OnMoneyTransferRequest;
874 public event EconomyDataRequest OnEconomyDataRequest;
875 public event MoneyBalanceRequest OnMoneyBalanceRequest;
876 public event ParcelBuy OnParcelBuy;
877 public event UUIDNameRequest OnTeleportHomeRequest;
878 public event UUIDNameRequest OnUUIDGroupNameRequest;
879 public event ScriptAnswer OnScriptAnswer;
880 public event RequestPayPrice OnRequestPayPrice;
881 public event AgentSit OnUndo;
882 public event ForceReleaseControls OnForceReleaseControls;
883 public event GodLandStatRequest OnLandStatRequest;
884 public event RequestObjectPropertiesFamily OnObjectGroupRequest;
885 public event DetailedEstateDataRequest OnDetailedEstateDataRequest;
886 public event SetEstateFlagsRequest OnSetEstateFlagsRequest;
887 public event SetEstateTerrainBaseTexture OnSetEstateTerrainBaseTexture;
888 public event SetEstateTerrainDetailTexture OnSetEstateTerrainDetailTexture;
889 public event SetEstateTerrainTextureHeights OnSetEstateTerrainTextureHeights;
890 public event CommitEstateTerrainTextureRequest OnCommitEstateTerrainTextureRequest;
891 public event SetRegionTerrainSettings OnSetRegionTerrainSettings;
892 public event BakeTerrain OnBakeTerrain;
893 public event EstateChangeInfo OnEstateChangeInfo;
894 public event EstateRestartSimRequest OnEstateRestartSimRequest;
895 public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
896 public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
897 public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
898 public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
899 public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
900 public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
901 public event ScriptReset OnScriptReset;
902 public event GetScriptRunning OnGetScriptRunning;
903 public event SetScriptRunning OnSetScriptRunning;
904 public event UpdateVector OnAutoPilotGo;
905
906 public event TerrainUnacked OnUnackedTerrain;
907
908 #region Scene/Avatar to Client
909
910 /// <summary>
911 ///
912 /// </summary>
913 /// <param name="regionInfo"></param>
914 public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args)
915 {
916 RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake);
917
918 handshake.RegionInfo.BillableFactor = args.billableFactor;
919 handshake.RegionInfo.IsEstateManager = args.isEstateManager;
920 handshake.RegionInfo.TerrainHeightRange00 = args.terrainHeightRange0;
921 handshake.RegionInfo.TerrainHeightRange01 = args.terrainHeightRange1;
922 handshake.RegionInfo.TerrainHeightRange10 = args.terrainHeightRange2;
923 handshake.RegionInfo.TerrainHeightRange11 = args.terrainHeightRange3;
924 handshake.RegionInfo.TerrainStartHeight00 = args.terrainStartHeight0;
925 handshake.RegionInfo.TerrainStartHeight01 = args.terrainStartHeight1;
926 handshake.RegionInfo.TerrainStartHeight10 = args.terrainStartHeight2;
927 handshake.RegionInfo.TerrainStartHeight11 = args.terrainStartHeight3;
928 handshake.RegionInfo.SimAccess = args.simAccess;
929 handshake.RegionInfo.WaterHeight = args.waterHeight;
930
931 handshake.RegionInfo.RegionFlags = args.regionFlags;
932 handshake.RegionInfo.SimName = Helpers.StringToField(args.regionName);
933 handshake.RegionInfo.SimOwner = args.SimOwner;
934 handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
935 handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
936 handshake.RegionInfo.TerrainBase2 = args.terrainBase2;
937 handshake.RegionInfo.TerrainBase3 = args.terrainBase3;
938 handshake.RegionInfo.TerrainDetail0 = args.terrainDetail0;
939 handshake.RegionInfo.TerrainDetail1 = args.terrainDetail1;
940 handshake.RegionInfo.TerrainDetail2 = args.terrainDetail2;
941 handshake.RegionInfo.TerrainDetail3 = args.terrainDetail3;
942 handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting?
943
944 OutPacket(handshake, ThrottleOutPacketType.Task);
945 }
946
947 /// <summary>
948 ///
949 /// </summary>
950 /// <param name="regInfo"></param>
951 public void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look)
952 {
953 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
954 mov.SimData.ChannelVersion = m_channelVersion;
955 mov.AgentData.SessionID = m_sessionId;
956 mov.AgentData.AgentID = AgentId;
957 mov.Data.RegionHandle = regInfo.RegionHandle;
958 mov.Data.Timestamp = 1172750370; // TODO - dynamicalise this
959
960 if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
961 {
962 mov.Data.Position = m_startpos;
963 }
964 else
965 {
966 mov.Data.Position = pos;
967 }
968 mov.Data.LookAt = look;
969
970 // Hack to get this out immediately and skip the throttles
971 OutPacket(mov, ThrottleOutPacketType.Unknown);
972 }
973
974 /// <summary>
975 ///
976 /// </summary>
977 /// <param name="message"></param>
978 /// <param name="type"></param>
979 /// <param name="fromPos"></param>
980 /// <param name="fromName"></param>
981 /// <param name="fromAgentID"></param>
982 public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName,
983 LLUUID fromAgentID, byte source, byte audible)
984 {
985 SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID, source, audible);
986 }
987
988 public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName,
989 LLUUID fromAgentID, byte source, byte audible)
990 {
991 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
992 reply.ChatData.Audible = audible;
993 reply.ChatData.Message = message;
994 reply.ChatData.ChatType = type;
995 reply.ChatData.SourceType = source;
996 reply.ChatData.Position = fromPos;
997 reply.ChatData.FromName = Helpers.StringToField(fromName);
998 reply.ChatData.OwnerID = fromAgentID;
999 reply.ChatData.SourceID = fromAgentID;
1000
1001 OutPacket(reply, ThrottleOutPacketType.Task);
1002 }
1003
1004 /// <summary>
1005 /// Send an instant message to this client
1006 /// </summary>
1007 /// <param name="message"></param>
1008 /// <param name="target"></param>
1009 public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent,
1010 LLUUID imSessionID, string fromName, byte dialog, uint timeStamp)
1011 {
1012 SendInstantMessage(
1013 fromAgent, fromAgentSession, message, toAgent,
1014 imSessionID, fromName, dialog, timeStamp, new byte[0]);
1015 }
1016
1017 /// <summary>
1018 /// Send an instant message to this client
1019 /// </summary>
1020 /// <param name="message"></param>
1021 /// <param name="target"></param>
1022 public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent,
1023 LLUUID imSessionID, string fromName, byte dialog, uint timeStamp,
1024 byte[] binaryBucket)
1025 {
1026 if (((Scene)(this.m_scene)).ExternalChecks.ExternalChecksCanInstantMessage(fromAgent, toAgent))
1027 {
1028 ImprovedInstantMessagePacket msg
1029 = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage);
1030
1031 msg.AgentData.AgentID = fromAgent;
1032 msg.AgentData.SessionID = fromAgentSession;
1033 msg.MessageBlock.FromAgentName = Helpers.StringToField(fromName);
1034 msg.MessageBlock.Dialog = dialog;
1035 msg.MessageBlock.FromGroup = false;
1036 msg.MessageBlock.ID = imSessionID;
1037 msg.MessageBlock.Offline = 0;
1038 msg.MessageBlock.ParentEstateID = 0;
1039 msg.MessageBlock.Position = new LLVector3();
1040 msg.MessageBlock.RegionID = LLUUID.Random();
1041 msg.MessageBlock.Timestamp = timeStamp;
1042 msg.MessageBlock.ToAgentID = toAgent;
1043 msg.MessageBlock.Message = Helpers.StringToField(message);
1044 msg.MessageBlock.BinaryBucket = binaryBucket;
1045
1046 OutPacket(msg, ThrottleOutPacketType.Task);
1047 }
1048 }
1049
1050 /// <summary>
1051 /// Send the region heightmap to the client
1052 /// </summary>
1053 /// <param name="map">heightmap</param>
1054 public virtual void SendLayerData(float[] map)
1055 {
1056 ThreadPool.QueueUserWorkItem(new WaitCallback(DoSendLayerData), (object)map);
1057 }
1058
1059 /// <summary>
1060 /// Send terrain layer information to the client.
1061 /// </summary>
1062 /// <param name="o"></param>
1063 private void DoSendLayerData(object o)
1064 {
1065 float[] map = (float[])o;
1066
1067 try
1068 {
1069 for (int y = 0; y < 16; y++)
1070 {
1071 // For some terrains, sending more than one terrain patch at once results in a libsecondlife exception
1072 // see http://opensimulator.org/mantis/view.php?id=1662
1073 //for (int x = 0; x < 16; x += 4)
1074 //{
1075 // SendLayerPacket(map, y, x);
1076 // Thread.Sleep(150);
1077 //}
1078 for (int x = 0; x < 16; x++)
1079 {
1080 SendLayerData(x, y, map);
1081 Thread.Sleep(35);
1082 }
1083 }
1084 }
1085 catch (Exception e)
1086 {
1087 m_log.Warn("[CLIENT]: ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString());
1088 }
1089 }
1090
1091 /// <summary>
1092 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1093 /// </summary>
1094 /// <param name="map">heightmap</param>
1095 /// <param name="px">X coordinate for patches 0..12</param>
1096 /// <param name="py">Y coordinate for patches 0..15</param>
1097 // private void SendLayerPacket(float[] map, int y, int x)
1098 // {
1099 // int[] patches = new int[4];
1100 // patches[0] = x + 0 + y * 16;
1101 // patches[1] = x + 1 + y * 16;
1102 // patches[2] = x + 2 + y * 16;
1103 // patches[3] = x + 3 + y * 16;
1104
1105 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1106 // OutPacket(layerpack, ThrottleOutPacketType.Land);
1107 // }
1108
1109 /// <summary>
1110 /// Sends a specified patch to a client
1111 /// </summary>
1112 /// <param name="px">Patch coordinate (x) 0..15</param>
1113 /// <param name="py">Patch coordinate (y) 0..15</param>
1114 /// <param name="map">heightmap</param>
1115 public void SendLayerData(int px, int py, float[] map)
1116 {
1117 try
1118 {
1119 int[] patches = new int[1];
1120 int patchx, patchy;
1121 patchx = px;
1122 patchy = py;
1123
1124 patches[0] = patchx + 0 + patchy * 16;
1125
1126 LayerDataPacket layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1127 layerpack.Header.Zerocoded = true;
1128
1129 OutPacket(layerpack, ThrottleOutPacketType.Land);
1130 }
1131 catch (Exception e)
1132 {
1133 m_log.Warn("[client]: ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString());
1134 }
1135 }
1136
1137 /// <summary>
1138 /// Tell the client that the given neighbour region is ready to receive a child agent.
1139 /// </summary>
1140 /// <param name="neighbourHandle"></param>
1141 /// <param name="neighbourIP"></param>
1142 /// <param name="neighbourPort"></param>
1143 public void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint)
1144 {
1145 IPAddress neighbourIP = neighbourEndPoint.Address;
1146 ushort neighbourPort = (ushort)neighbourEndPoint.Port;
1147
1148 EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator);
1149 // TODO: don't create new blocks if recycling an old packet
1150 enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock();
1151 enablesimpacket.SimulatorInfo.Handle = neighbourHandle;
1152
1153 byte[] byteIP = neighbourIP.GetAddressBytes();
1154 enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24;
1155 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16;
1156 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8;
1157 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0];
1158 enablesimpacket.SimulatorInfo.Port = neighbourPort;
1159 OutPacket(enablesimpacket, ThrottleOutPacketType.Task);
1160 }
1161
1162 /// <summary>
1163 ///
1164 /// </summary>
1165 /// <returns></returns>
1166 public AgentCircuitData RequestClientInfo()
1167 {
1168 AgentCircuitData agentData = new AgentCircuitData();
1169 agentData.AgentID = AgentId;
1170 agentData.SessionID = m_sessionId;
1171 agentData.SecureSessionID = SecureSessionId;
1172 agentData.circuitcode = m_circuitCode;
1173 agentData.child = false;
1174 agentData.firstname = m_firstName;
1175 agentData.lastname = m_lastName;
1176 agentData.CapsPath = m_scene.GetCapsPath(m_agentId);
1177 return agentData;
1178 }
1179
1180 public void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint externalIPEndPoint,
1181 string capsURL)
1182 {
1183 LLVector3 look = new LLVector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10);
1184
1185 //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion);
1186 CrossedRegionPacket newSimPack = new CrossedRegionPacket();
1187 // TODO: don't create new blocks if recycling an old packet
1188 newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
1189 newSimPack.AgentData.AgentID = AgentId;
1190 newSimPack.AgentData.SessionID = m_sessionId;
1191 newSimPack.Info = new CrossedRegionPacket.InfoBlock();
1192 newSimPack.Info.Position = pos;
1193 newSimPack.Info.LookAt = look;
1194 newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock();
1195 newSimPack.RegionData.RegionHandle = newRegionHandle;
1196 byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes();
1197 newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
1198 newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
1199 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1200 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1201 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1202 newSimPack.RegionData.SeedCapability = Helpers.StringToField(capsURL);
1203
1204 // Hack to get this out immediately and skip throttles
1205 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
1206 }
1207
1208 internal void SendMapBlockSplit(List<MapBlockData> mapBlocks, uint flag)
1209 {
1210 MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply);
1211 // TODO: don't create new blocks if recycling an old packet
1212
1213 MapBlockData[] mapBlocks2 = mapBlocks.ToArray();
1214
1215 mapReply.AgentData.AgentID = AgentId;
1216 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1217 mapReply.AgentData.Flags = flag;
1218
1219 for (int i = 0; i < mapBlocks2.Length; i++)
1220 {
1221 mapReply.Data[i] = new MapBlockReplyPacket.DataBlock();
1222 mapReply.Data[i].MapImageID = mapBlocks2[i].MapImageId;
1223 //m_log.Warn(mapBlocks2[i].MapImageId.ToString());
1224 mapReply.Data[i].X = mapBlocks2[i].X;
1225 mapReply.Data[i].Y = mapBlocks2[i].Y;
1226 mapReply.Data[i].WaterHeight = mapBlocks2[i].WaterHeight;
1227 mapReply.Data[i].Name = Helpers.StringToField(mapBlocks2[i].Name);
1228 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1229 mapReply.Data[i].Access = mapBlocks2[i].Access;
1230 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1231 }
1232 OutPacket(mapReply, ThrottleOutPacketType.Land);
1233 }
1234
1235 public void SendMapBlock(List<MapBlockData> mapBlocks, uint flag)
1236 {
1237
1238 MapBlockData[] mapBlocks2 = mapBlocks.ToArray();
1239
1240 int maxsend = 10;
1241
1242 //int packets = Math.Ceiling(mapBlocks2.Length / maxsend);
1243
1244 List<MapBlockData> sendingBlocks = new List<MapBlockData>();
1245
1246 for (int i = 0; i < mapBlocks2.Length; i++)
1247 {
1248 sendingBlocks.Add(mapBlocks2[i]);
1249 if (((i + 1) == mapBlocks2.Length) || ((i % maxsend) == 0))
1250 {
1251 SendMapBlockSplit(sendingBlocks, flag);
1252 sendingBlocks = new List<MapBlockData>();
1253 }
1254 }
1255 }
1256
1257 public void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags)
1258 {
1259 TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal);
1260 tpLocal.Info.AgentID = AgentId;
1261 tpLocal.Info.TeleportFlags = flags;
1262 tpLocal.Info.LocationID = 2;
1263 tpLocal.Info.LookAt = lookAt;
1264 tpLocal.Info.Position = position;
1265
1266 // Hack to get this out immediately and skip throttles
1267 OutPacket(tpLocal, ThrottleOutPacketType.Unknown);
1268 }
1269
1270 public void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID,
1271 uint flags, string capsURL)
1272 {
1273 //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish);
1274
1275 TeleportFinishPacket teleport = new TeleportFinishPacket();
1276 teleport.Info.AgentID = AgentId;
1277 teleport.Info.RegionHandle = regionHandle;
1278 teleport.Info.SimAccess = simAccess;
1279
1280 teleport.Info.SeedCapability = Helpers.StringToField(capsURL);
1281
1282 IPAddress oIP = newRegionEndPoint.Address;
1283 byte[] byteIP = oIP.GetAddressBytes();
1284 uint ip = (uint)byteIP[3] << 24;
1285 ip += (uint)byteIP[2] << 16;
1286 ip += (uint)byteIP[1] << 8;
1287 ip += (uint)byteIP[0];
1288
1289 teleport.Info.SimIP = ip;
1290 teleport.Info.SimPort = (ushort)newRegionEndPoint.Port;
1291 teleport.Info.LocationID = 4;
1292 teleport.Info.TeleportFlags = 1 << 4;
1293
1294 // Hack to get this out immediately and skip throttles.
1295 OutPacket(teleport, ThrottleOutPacketType.Unknown);
1296 }
1297
1298 /// <summary>
1299 ///
1300 /// </summary>
1301 public void SendTeleportFailed(string reason)
1302 {
1303 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1304 tpFailed.Info.AgentID = AgentId;
1305 tpFailed.Info.Reason = Helpers.StringToField(reason);
1306
1307 // Hack to get this out immediately and skip throttles
1308 OutPacket(tpFailed, ThrottleOutPacketType.Unknown);
1309 }
1310
1311 /// <summary>
1312 ///
1313 /// </summary>
1314 public void SendTeleportLocationStart()
1315 {
1316 //TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart);
1317 TeleportStartPacket tpStart = new TeleportStartPacket();
1318 tpStart.Info.TeleportFlags = 16; // Teleport via location
1319
1320 // Hack to get this out immediately and skip throttles
1321 OutPacket(tpStart, ThrottleOutPacketType.Unknown);
1322 }
1323
1324 public void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance)
1325 {
1326 MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
1327 money.MoneyData.AgentID = AgentId;
1328 money.MoneyData.TransactionID = transaction;
1329 money.MoneyData.TransactionSuccess = success;
1330 money.MoneyData.Description = description;
1331 money.MoneyData.MoneyBalance = balance;
1332 OutPacket(money, ThrottleOutPacketType.Task);
1333 }
1334
1335 public void SendPayPrice(LLUUID objectID, int[] payPrice)
1336 {
1337 if (payPrice[0] == 0 &&
1338 payPrice[1] == 0 &&
1339 payPrice[2] == 0 &&
1340 payPrice[3] == 0 &&
1341 payPrice[4] == 0)
1342 return;
1343
1344 PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply);
1345 payPriceReply.ObjectData.ObjectID = objectID;
1346 payPriceReply.ObjectData.DefaultPayPrice = payPrice[0];
1347
1348 payPriceReply.ButtonData = new PayPriceReplyPacket.ButtonDataBlock[4];
1349 payPriceReply.ButtonData[0] = new PayPriceReplyPacket.ButtonDataBlock();
1350 payPriceReply.ButtonData[0].PayButton = payPrice[1];
1351 payPriceReply.ButtonData[1] = new PayPriceReplyPacket.ButtonDataBlock();
1352 payPriceReply.ButtonData[1].PayButton = payPrice[2];
1353 payPriceReply.ButtonData[2] = new PayPriceReplyPacket.ButtonDataBlock();
1354 payPriceReply.ButtonData[2].PayButton = payPrice[3];
1355 payPriceReply.ButtonData[3] = new PayPriceReplyPacket.ButtonDataBlock();
1356 payPriceReply.ButtonData[3].PayButton = payPrice[4];
1357
1358 OutPacket(payPriceReply, ThrottleOutPacketType.Task);
1359 }
1360
1361 public void SendStartPingCheck(byte seq)
1362 {
1363 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
1364 pc.PingID.PingID = seq;
1365 pc.Header.Reliable = false;
1366 OutPacket(pc, ThrottleOutPacketType.Unknown);
1367 }
1368
1369 public void SendKillObject(ulong regionHandle, uint localID)
1370 {
1371 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1372 // TODO: don't create new blocks if recycling an old packet
1373 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
1374 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
1375 kill.ObjectData[0].ID = localID;
1376 kill.Header.Reliable = false;
1377 kill.Header.Zerocoded = true;
1378 OutPacket(kill, ThrottleOutPacketType.Task);
1379 }
1380
1381 /// <summary>
1382 /// Send information about the items contained in a folder to the client.
1383 ///
1384 /// XXX This method needs some refactoring loving
1385 /// </summary>
1386 /// <param name="ownerID">The owner of the folder</param>
1387 /// <param name="folderID">The id of the folder</param>
1388 /// <param name="items">The items contained in the folder identified by folderID</param>
1389 /// <param name="fetchFolders">Do we need to send folder information?</param>
1390 /// <param name="fetchItems">Do we need to send item information?</param>
1391 public void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List<InventoryItemBase> items,
1392 List<InventoryFolderBase> folders,
1393 bool fetchFolders, bool fetchItems)
1394 {
1395 // An inventory descendents packet consists of a single agent section and an inventory details
1396 // section for each inventory item. The size of each inventory item is approximately 550 bytes.
1397 // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent
1398 // packets containing metadata for in excess of 100 items. But in practice, there may be other
1399 // factors (e.g. firewalls) restraining the maximum UDP packet size. See,
1400 //
1401 // http://opensimulator.org/mantis/view.php?id=226
1402 //
1403 // for one example of this kind of thing. In fact, the Linden servers appear to only send about
1404 // 6 to 7 items at a time, so let's stick with 6
1405 int MAX_ITEMS_PER_PACKET = 6;
1406
1407 //Ckrinke This variable is not used, so comment out to remove the warning from the compiler (3-21-08)
1408 //Ckrinke uint FULL_MASK_PERMISSIONS = 2147483647;
1409
1410 if (fetchItems)
1411 {
1412 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1413
1414 if (items.Count < MAX_ITEMS_PER_PACKET)
1415 {
1416 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count];
1417 descend.AgentData.Descendents = items.Count;
1418 }
1419 else
1420 {
1421 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET];
1422 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1423 }
1424
1425 // Even if we aren't fetching the folders, we still need to include the folder count
1426 // in the total number of descendents. Failure to do so will cause subtle bugs such
1427 // as the failure of textures which haven't been expanded in inventory to show up
1428 // in the texture prim edit selection panel.
1429 if (!fetchFolders)
1430 {
1431 descend.AgentData.Descendents += folders.Count;
1432 }
1433
1434 int count = 0;
1435 int i = 0;
1436 foreach (InventoryItemBase item in items)
1437 {
1438 descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock();
1439 descend.ItemData[i].ItemID = item.ID;
1440 descend.ItemData[i].AssetID = item.AssetID;
1441 descend.ItemData[i].CreatorID = item.Creator;
1442 descend.ItemData[i].BaseMask = item.BasePermissions;
1443 descend.ItemData[i].Description = Helpers.StringToField(item.Description);
1444 descend.ItemData[i].EveryoneMask = item.EveryOnePermissions;
1445 descend.ItemData[i].OwnerMask = item.CurrentPermissions;
1446 descend.ItemData[i].FolderID = item.Folder;
1447 descend.ItemData[i].InvType = (sbyte)item.InvType;
1448 descend.ItemData[i].Name = Helpers.StringToField(item.Name);
1449 descend.ItemData[i].NextOwnerMask = item.NextPermissions;
1450 descend.ItemData[i].OwnerID = item.Owner;
1451 descend.ItemData[i].Type = (sbyte)item.AssetType;
1452
1453 //descend.ItemData[i].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1454 descend.ItemData[i].GroupID = item.GroupID;
1455 descend.ItemData[i].GroupOwned = item.GroupOwned;
1456 descend.ItemData[i].GroupMask = 0;
1457 descend.ItemData[i].CreationDate = item.CreationDate;
1458 descend.ItemData[i].SalePrice = item.SalePrice;
1459 descend.ItemData[i].SaleType = item.SaleType;
1460 descend.ItemData[i].Flags = item.Flags;
1461
1462 descend.ItemData[i].CRC =
1463 Helpers.InventoryCRC(descend.ItemData[i].CreationDate, descend.ItemData[i].SaleType,
1464 descend.ItemData[i].InvType, descend.ItemData[i].Type,
1465 descend.ItemData[i].AssetID, descend.ItemData[i].GroupID,
1466 descend.ItemData[i].SalePrice,
1467 descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID,
1468 descend.ItemData[i].ItemID, descend.ItemData[i].FolderID,
1469 descend.ItemData[i].EveryoneMask,
1470 descend.ItemData[i].Flags, descend.ItemData[i].OwnerMask,
1471 descend.ItemData[i].GroupMask, item.CurrentPermissions);
1472
1473 i++;
1474 count++;
1475 if (i == MAX_ITEMS_PER_PACKET)
1476 {
1477 descend.Header.Zerocoded = true;
1478 OutPacket(descend, ThrottleOutPacketType.Asset);
1479
1480 if ((items.Count - count) > 0)
1481 {
1482 descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1483 if ((items.Count - count) < MAX_ITEMS_PER_PACKET)
1484 {
1485 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count];
1486 descend.AgentData.Descendents = items.Count - count;
1487 }
1488 else
1489 {
1490 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET];
1491 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1492 }
1493 i = 0;
1494 }
1495 }
1496 }
1497
1498 if (i < MAX_ITEMS_PER_PACKET)
1499 {
1500 OutPacket(descend, ThrottleOutPacketType.Asset);
1501 }
1502 }
1503
1504 //send subfolders
1505 if (fetchFolders)
1506 {
1507 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1508
1509 if (folders.Count < MAX_ITEMS_PER_PACKET)
1510 {
1511 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders.Count];
1512 descend.AgentData.Descendents = folders.Count;
1513 }
1514 else
1515 {
1516 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET];
1517 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1518 }
1519
1520 // Not sure if this scenario ever actually occurs, but nonetheless we include the items
1521 // count even if we're not sending item data for the same reasons as above.
1522 if (!fetchItems)
1523 {
1524 descend.AgentData.Descendents += items.Count;
1525 }
1526
1527 int i = 0;
1528 int count = 0;
1529 foreach (InventoryFolderBase folder in folders)
1530 {
1531 descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock();
1532 descend.FolderData[i].FolderID = folder.ID;
1533 descend.FolderData[i].Name = Helpers.StringToField(folder.Name);
1534 descend.FolderData[i].ParentID = folder.ParentID;
1535 descend.FolderData[i].Type = (sbyte)folder.Type;
1536
1537 i++;
1538 count++;
1539 if (i == MAX_ITEMS_PER_PACKET)
1540 {
1541 OutPacket(descend, ThrottleOutPacketType.Asset);
1542
1543 if ((folders.Count - count) > 0)
1544 {
1545 descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1546 if ((folders.Count - count) < MAX_ITEMS_PER_PACKET)
1547 {
1548 descend.FolderData =
1549 new InventoryDescendentsPacket.FolderDataBlock[folders.Count - count];
1550 descend.AgentData.Descendents = folders.Count - count;
1551 }
1552 else
1553 {
1554 descend.FolderData =
1555 new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET];
1556 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1557 }
1558 i = 0;
1559 }
1560 }
1561 }
1562
1563 if (i < MAX_ITEMS_PER_PACKET)
1564 {
1565 OutPacket(descend, ThrottleOutPacketType.Asset);
1566 }
1567 }
1568 }
1569
1570 private InventoryDescendentsPacket CreateInventoryDescendentsPacket(LLUUID ownerID, LLUUID folderID)
1571 {
1572 InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents);
1573 descend.Header.Zerocoded = true;
1574 descend.AgentData.AgentID = AgentId;
1575 descend.AgentData.OwnerID = ownerID;
1576 descend.AgentData.FolderID = folderID;
1577 descend.AgentData.Version = 1;
1578
1579 return descend;
1580 }
1581
1582 public void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item)
1583 {
1584 uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1585 FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply);
1586 // TODO: don't create new blocks if recycling an old packet
1587 inventoryReply.AgentData.AgentID = AgentId;
1588 inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1];
1589 inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock();
1590 inventoryReply.InventoryData[0].ItemID = item.ID;
1591 inventoryReply.InventoryData[0].AssetID = item.AssetID;
1592 inventoryReply.InventoryData[0].CreatorID = item.Creator;
1593 inventoryReply.InventoryData[0].BaseMask = item.BasePermissions;
1594 inventoryReply.InventoryData[0].CreationDate =
1595 (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
1596 inventoryReply.InventoryData[0].Description = Helpers.StringToField(item.Description);
1597 inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions;
1598 inventoryReply.InventoryData[0].FolderID = item.Folder;
1599 inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType;
1600 inventoryReply.InventoryData[0].Name = Helpers.StringToField(item.Name);
1601 inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions;
1602 inventoryReply.InventoryData[0].OwnerID = item.Owner;
1603 inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions;
1604 inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType;
1605
1606 //inventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1607 inventoryReply.InventoryData[0].GroupID = item.GroupID;
1608 inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned;
1609 inventoryReply.InventoryData[0].GroupMask = 0;
1610 inventoryReply.InventoryData[0].Flags = item.Flags;
1611 inventoryReply.InventoryData[0].SalePrice = item.SalePrice;
1612 inventoryReply.InventoryData[0].SaleType = item.SaleType;
1613
1614 inventoryReply.InventoryData[0].CRC =
1615 Helpers.InventoryCRC(1000, 0, inventoryReply.InventoryData[0].InvType,
1616 inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID,
1617 inventoryReply.InventoryData[0].GroupID, 100,
1618 inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID,
1619 inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID,
1620 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1621 FULL_MASK_PERMISSIONS);
1622 inventoryReply.Header.Zerocoded = true;
1623 OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
1624 }
1625
1626 /// <see>IClientAPI.SendBulkUpdateInventory(InventoryItemBase)</see>
1627 public void SendBulkUpdateInventory(InventoryItemBase item)
1628 {
1629 uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1630
1631 BulkUpdateInventoryPacket bulkUpdate
1632 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1633
1634 bulkUpdate.AgentData.AgentID = AgentId;
1635 bulkUpdate.AgentData.TransactionID = LLUUID.Random();
1636
1637 bulkUpdate.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1];
1638 bulkUpdate.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock();
1639 bulkUpdate.FolderData[0].FolderID = LLUUID.Zero;
1640 bulkUpdate.FolderData[0].ParentID = LLUUID.Zero;
1641 bulkUpdate.FolderData[0].Type = -1;
1642 bulkUpdate.FolderData[0].Name = new byte[0];
1643
1644 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1];
1645 bulkUpdate.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock();
1646 bulkUpdate.ItemData[0].ItemID = item.ID;
1647 bulkUpdate.ItemData[0].AssetID = item.AssetID;
1648 bulkUpdate.ItemData[0].CreatorID = item.Creator;
1649 bulkUpdate.ItemData[0].BaseMask = item.BasePermissions;
1650 bulkUpdate.ItemData[0].CreationDate = 1000;
1651 bulkUpdate.ItemData[0].Description = Helpers.StringToField(item.Description);
1652 bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions;
1653 bulkUpdate.ItemData[0].FolderID = item.Folder;
1654 bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType;
1655 bulkUpdate.ItemData[0].Name = Helpers.StringToField(item.Name);
1656 bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions;
1657 bulkUpdate.ItemData[0].OwnerID = item.Owner;
1658 bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions;
1659 bulkUpdate.ItemData[0].Type = (sbyte)item.AssetType;
1660
1661 //bulkUpdate.ItemData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1662 bulkUpdate.ItemData[0].GroupID = item.GroupID;
1663 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
1664 bulkUpdate.ItemData[0].GroupMask = 0;
1665 bulkUpdate.ItemData[0].Flags = item.Flags;
1666 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
1667 bulkUpdate.ItemData[0].SaleType = item.SaleType;
1668
1669 bulkUpdate.ItemData[0].CRC =
1670 Helpers.InventoryCRC(1000, 0, bulkUpdate.ItemData[0].InvType,
1671 bulkUpdate.ItemData[0].Type, bulkUpdate.ItemData[0].AssetID,
1672 bulkUpdate.ItemData[0].GroupID, 100,
1673 bulkUpdate.ItemData[0].OwnerID, bulkUpdate.ItemData[0].CreatorID,
1674 bulkUpdate.ItemData[0].ItemID, bulkUpdate.ItemData[0].FolderID,
1675 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1676 FULL_MASK_PERMISSIONS);
1677 bulkUpdate.Header.Zerocoded = true;
1678 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1679 }
1680
1681 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
1682 public void SendInventoryItemCreateUpdate(InventoryItemBase Item)
1683 {
1684 uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1685
1686 UpdateCreateInventoryItemPacket InventoryReply
1687 = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket(
1688 PacketType.UpdateCreateInventoryItem);
1689
1690 // TODO: don't create new blocks if recycling an old packet
1691 InventoryReply.AgentData.AgentID = AgentId;
1692 InventoryReply.AgentData.SimApproved = true;
1693 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
1694 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
1695 InventoryReply.InventoryData[0].ItemID = Item.ID;
1696 InventoryReply.InventoryData[0].AssetID = Item.AssetID;
1697 InventoryReply.InventoryData[0].CreatorID = Item.Creator;
1698 InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions;
1699 InventoryReply.InventoryData[0].Description = Helpers.StringToField(Item.Description);
1700 InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions;
1701 InventoryReply.InventoryData[0].FolderID = Item.Folder;
1702 InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType;
1703 InventoryReply.InventoryData[0].Name = Helpers.StringToField(Item.Name);
1704 InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions;
1705 InventoryReply.InventoryData[0].OwnerID = Item.Owner;
1706 InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions;
1707 InventoryReply.InventoryData[0].Type = (sbyte)Item.AssetType;
1708
1709 //InventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1710 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
1711 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
1712 InventoryReply.InventoryData[0].GroupMask = 0;
1713 InventoryReply.InventoryData[0].Flags = Item.Flags;
1714 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
1715 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
1716 InventoryReply.InventoryData[0].CreationDate = Item.CreationDate;
1717
1718 InventoryReply.InventoryData[0].CRC =
1719 Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType,
1720 InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID,
1721 InventoryReply.InventoryData[0].GroupID, 100,
1722 InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID,
1723 InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID,
1724 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1725 FULL_MASK_PERMISSIONS);
1726 InventoryReply.Header.Zerocoded = true;
1727 OutPacket(InventoryReply, ThrottleOutPacketType.Asset);
1728 }
1729
1730 public void SendRemoveInventoryItem(LLUUID itemID)
1731 {
1732 RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem);
1733 // TODO: don't create new blocks if recycling an old packet
1734 remove.AgentData.AgentID = AgentId;
1735 remove.AgentData.SessionID = m_sessionId;
1736 remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1];
1737 remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock();
1738 remove.InventoryData[0].ItemID = itemID;
1739 remove.Header.Zerocoded = true;
1740 OutPacket(remove, ThrottleOutPacketType.Asset);
1741 }
1742
1743 public void SendTakeControls(int controls, bool passToAgent, bool TakeControls)
1744 {
1745 ScriptControlChangePacket scriptcontrol = (ScriptControlChangePacket)PacketPool.Instance.GetPacket(PacketType.ScriptControlChange);
1746 ScriptControlChangePacket.DataBlock[] data = new ScriptControlChangePacket.DataBlock[1];
1747 ScriptControlChangePacket.DataBlock ddata = new ScriptControlChangePacket.DataBlock();
1748 ddata.Controls = (uint)controls;
1749 ddata.PassToAgent = passToAgent;
1750 ddata.TakeControls = TakeControls;
1751 data[0] = ddata;
1752 scriptcontrol.Data = data;
1753 OutPacket(scriptcontrol, ThrottleOutPacketType.Task);
1754 }
1755
1756 public void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName)
1757 {
1758 ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory);
1759 replytask.InventoryData.TaskID = taskID;
1760 replytask.InventoryData.Serial = serial;
1761 replytask.InventoryData.Filename = fileName;
1762 OutPacket(replytask, ThrottleOutPacketType.Asset);
1763 }
1764
1765 public void SendXferPacket(ulong xferID, uint packet, byte[] data)
1766 {
1767 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
1768 sendXfer.XferID.ID = xferID;
1769 sendXfer.XferID.Packet = packet;
1770 sendXfer.DataPacket.Data = data;
1771 OutPacket(sendXfer, ThrottleOutPacketType.Task);
1772 }
1773
1774 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
1775 int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor,
1776 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
1777 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
1778 {
1779 EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData);
1780 economyData.Info.EnergyEfficiency = EnergyEfficiency;
1781 economyData.Info.ObjectCapacity = ObjectCapacity;
1782 economyData.Info.ObjectCount = ObjectCount;
1783 economyData.Info.PriceEnergyUnit = PriceEnergyUnit;
1784 economyData.Info.PriceGroupCreate = PriceGroupCreate;
1785 economyData.Info.PriceObjectClaim = PriceObjectClaim;
1786 economyData.Info.PriceObjectRent = PriceObjectRent;
1787 economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor;
1788 economyData.Info.PriceParcelClaim = PriceParcelClaim;
1789 economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor;
1790 economyData.Info.PriceParcelRent = PriceParcelRent;
1791 economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay;
1792 economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete;
1793 economyData.Info.PriceRentLight = PriceRentLight;
1794 economyData.Info.PriceUpload = PriceUpload;
1795 economyData.Info.TeleportMinPrice = TeleportMinPrice;
1796 economyData.Info.TeleportPriceExponent = TeleportPriceExponent;
1797 economyData.Header.Reliable = true;
1798 OutPacket(economyData, ThrottleOutPacketType.Unknown);
1799 }
1800
1801 public void SendAvatarPickerReply(AvatarPickerReplyAgentDataArgs AgentData, List<AvatarPickerReplyDataArgs> Data)
1802 {
1803 //construct the AvatarPickerReply packet.
1804 AvatarPickerReplyPacket replyPacket = new AvatarPickerReplyPacket();
1805 replyPacket.AgentData.AgentID = AgentData.AgentID;
1806 replyPacket.AgentData.QueryID = AgentData.QueryID;
1807 //int i = 0;
1808 List<AvatarPickerReplyPacket.DataBlock> data_block = new List<AvatarPickerReplyPacket.DataBlock>();
1809 foreach (AvatarPickerReplyDataArgs arg in Data)
1810 {
1811 AvatarPickerReplyPacket.DataBlock db = new AvatarPickerReplyPacket.DataBlock();
1812 db.AvatarID = arg.AvatarID;
1813 db.FirstName = arg.FirstName;
1814 db.LastName = arg.LastName;
1815 data_block.Add(db);
1816 }
1817 replyPacket.Data = data_block.ToArray();
1818 OutPacket(replyPacket, ThrottleOutPacketType.Task);
1819 }
1820
1821 public void SendAgentDataUpdate(LLUUID agentid, LLUUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
1822 {
1823
1824 m_activeGroupID = activegroupid;
1825 m_activeGroupName = groupname;
1826 m_activeGroupPowers = grouppowers;
1827
1828 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
1829 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
1830 sendAgentDataUpdate.AgentData.AgentID = agentid;
1831 sendAgentDataUpdate.AgentData.FirstName = Helpers.StringToField(firstname);
1832 sendAgentDataUpdate.AgentData.GroupName = Helpers.StringToField(groupname);
1833 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
1834 sendAgentDataUpdate.AgentData.GroupTitle = Helpers.StringToField(grouptitle);
1835 sendAgentDataUpdate.AgentData.LastName = Helpers.StringToField(lastname);
1836 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
1837 }
1838
1839 /// <summary>
1840 /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration
1841 /// blue information box in the bottom right hand corner.
1842 /// </summary>
1843 /// <param name="message"></param>
1844 public void SendAlertMessage(string message)
1845 {
1846 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
1847 alertPack.AlertData.Message = Helpers.StringToField(message);
1848 OutPacket(alertPack, ThrottleOutPacketType.Task);
1849 }
1850
1851 /// <summary>
1852 /// Send an agent alert message to the client.
1853 /// </summary>
1854 /// <param name="message"></param>
1855 /// <param name="modal">On the linden client, if this true then it displays a one button text box placed in the
1856 /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for
1857 /// the AlertMessage packet).</param>
1858 public void SendAgentAlertMessage(string message, bool modal)
1859 {
1860 OutPacket(BuildAgentAlertPacket(message, modal), ThrottleOutPacketType.Task);
1861 }
1862
1863 /// <summary>
1864 /// Construct an agent alert packet
1865 /// </summary>
1866 /// <param name="message"></param>
1867 /// <param name="modal"></param>
1868 /// <returns></returns>
1869 protected AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal)
1870 {
1871 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
1872 alertPack.AgentData.AgentID = AgentId;
1873 alertPack.AlertData.Message = Helpers.StringToField(message);
1874 alertPack.AlertData.Modal = modal;
1875
1876 return alertPack;
1877 }
1878
1879 public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message,
1880 string url)
1881 {
1882 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
1883 loadURL.Data.ObjectName = Helpers.StringToField(objectname);
1884 loadURL.Data.ObjectID = objectID;
1885 loadURL.Data.OwnerID = ownerID;
1886 loadURL.Data.OwnerIsGroup = groupOwned;
1887 loadURL.Data.Message = Helpers.StringToField(message);
1888 loadURL.Data.URL = Helpers.StringToField(url);
1889 OutPacket(loadURL, ThrottleOutPacketType.Task);
1890 }
1891
1892 public void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels)
1893 {
1894 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
1895 dialog.Data.ObjectID = objectID;
1896 dialog.Data.ObjectName = Helpers.StringToField(objectname);
1897 dialog.Data.FirstName = Helpers.StringToField(this.FirstName);
1898 dialog.Data.LastName = Helpers.StringToField(this.LastName);
1899 dialog.Data.Message = Helpers.StringToField(msg);
1900 dialog.Data.ImageID = textureID;
1901 dialog.Data.ChatChannel = ch;
1902 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
1903 for (int i = 0; i < buttonlabels.Length; i++)
1904 {
1905 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
1906 buttons[i].ButtonLabel = Helpers.StringToField(buttonlabels[i]);
1907 }
1908 dialog.Buttons = buttons;
1909 OutPacket(dialog, ThrottleOutPacketType.Task);
1910 }
1911
1912 public void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID)
1913 {
1914 PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound);
1915 // TODO: don't create new blocks if recycling an old packet
1916 preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1];
1917 preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock();
1918 preSound.DataBlock[0].ObjectID = objectID;
1919 preSound.DataBlock[0].OwnerID = ownerID;
1920 preSound.DataBlock[0].SoundID = soundID;
1921 preSound.Header.Zerocoded = true;
1922 OutPacket(preSound, ThrottleOutPacketType.Task);
1923 }
1924
1925 public void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags)
1926 {
1927 AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound);
1928 sound.DataBlock.SoundID = soundID;
1929 sound.DataBlock.ObjectID = objectID;
1930 sound.DataBlock.OwnerID = ownerID;
1931 sound.DataBlock.Gain = gain;
1932 sound.DataBlock.Flags = flags;
1933
1934 OutPacket(sound, ThrottleOutPacketType.Task);
1935 }
1936
1937 public void SendTriggeredSound(LLUUID soundID, LLUUID ownerID, LLUUID objectID, LLUUID parentID, ulong handle, LLVector3 position, float gain)
1938 {
1939 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
1940 sound.SoundData.SoundID = soundID;
1941 sound.SoundData.OwnerID = ownerID;
1942 sound.SoundData.ObjectID = objectID;
1943 sound.SoundData.ParentID = parentID;
1944 sound.SoundData.Handle = handle;
1945 sound.SoundData.Position = position;
1946 sound.SoundData.Gain = gain;
1947
1948 OutPacket(sound, ThrottleOutPacketType.Task);
1949 }
1950
1951 public void SendAttachedSoundGainChange(LLUUID objectID, float gain)
1952 {
1953 AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange);
1954 sound.DataBlock.ObjectID = objectID;
1955 sound.DataBlock.Gain = gain;
1956
1957 OutPacket(sound, ThrottleOutPacketType.Task);
1958 }
1959
1960 public void SendSunPos(LLVector3 Position, LLVector3 Velocity, ulong CurrentTime, uint SecondsPerSunCycle, uint SecondsPerYear, float OrbitalPosition)
1961 {
1962 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
1963 viewertime.TimeInfo.SunDirection = Position;
1964 viewertime.TimeInfo.SunAngVelocity = Velocity;
1965 viewertime.TimeInfo.UsecSinceStart = CurrentTime;
1966 viewertime.TimeInfo.SecPerDay = SecondsPerSunCycle;
1967 viewertime.TimeInfo.SecPerYear = SecondsPerYear;
1968 viewertime.TimeInfo.SunPhase = OrbitalPosition;
1969 viewertime.Header.Reliable = false;
1970 viewertime.Header.Zerocoded = true;
1971 OutPacket(viewertime, ThrottleOutPacketType.Task);
1972 }
1973
1974 // Currently Deprecated
1975 public void SendViewerTime(int phase)
1976 {
1977 /*
1978 Console.WriteLine("SunPhase: {0}", phase);
1979 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
1980 //viewertime.TimeInfo.SecPerDay = 86400;
1981 //viewertime.TimeInfo.SecPerYear = 31536000;
1982 viewertime.TimeInfo.SecPerDay = 1000;
1983 viewertime.TimeInfo.SecPerYear = 365000;
1984 viewertime.TimeInfo.SunPhase = 1;
1985 int sunPhase = (phase + 2) / 2;
1986 if ((sunPhase < 6) || (sunPhase > 36))
1987 {
1988 viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f);
1989 Console.WriteLine("sending night");
1990 }
1991 else
1992 {
1993 if (sunPhase < 12)
1994 {
1995 sunPhase = 12;
1996 }
1997 sunPhase = sunPhase - 12;
1998
1999 float yValue = 0.1f * (sunPhase);
2000 Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue);
2001 if (yValue > 1.2f)
2002 {
2003 yValue = yValue - 1.2f;
2004 }
2005
2006 yValue = Util.Clip(yValue, 0, 1);
2007
2008 if (sunPhase < 14)
2009 {
2010 yValue = 1 - yValue;
2011 }
2012 if (sunPhase < 12)
2013 {
2014 yValue *= -1;
2015 }
2016 viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f);
2017 Console.WriteLine("sending sun update " + yValue);
2018 }
2019 viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f);
2020 viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch();
2021 viewertime.Header.Reliable = false;
2022 OutPacket(viewertime, ThrottleOutPacketType.Task);
2023 */
2024 }
2025
2026 public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember,
2027 string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL,
2028 LLUUID partnerID)
2029 {
2030 AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply);
2031 avatarReply.AgentData.AgentID = AgentId;
2032 avatarReply.AgentData.AvatarID = avatarID;
2033 if (aboutText != null)
2034 avatarReply.PropertiesData.AboutText = Helpers.StringToField(aboutText);
2035 else
2036 avatarReply.PropertiesData.AboutText = Helpers.StringToField("");
2037 avatarReply.PropertiesData.BornOn = Helpers.StringToField(bornOn);
2038 avatarReply.PropertiesData.CharterMember = Helpers.StringToField(charterMember);
2039 if (flAbout != null)
2040 avatarReply.PropertiesData.FLAboutText = Helpers.StringToField(flAbout);
2041 else
2042 avatarReply.PropertiesData.FLAboutText = Helpers.StringToField("");
2043 avatarReply.PropertiesData.Flags = 0;
2044 avatarReply.PropertiesData.FLImageID = flImageID;
2045 avatarReply.PropertiesData.ImageID = imageID;
2046 avatarReply.PropertiesData.ProfileURL = Helpers.StringToField(profileURL);
2047 avatarReply.PropertiesData.PartnerID = partnerID;
2048 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2049 }
2050
2051 #endregion
2052
2053 #region Appearance/ Wearables Methods
2054
2055 /// <summary>
2056 ///
2057 /// </summary>
2058 /// <param name="wearables"></param>
2059 public void SendWearables(AvatarWearable[] wearables, int serial)
2060 {
2061 AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
2062 aw.AgentData.AgentID = AgentId;
2063 aw.AgentData.SerialNum = (uint)serial;
2064 aw.AgentData.SessionID = m_sessionId;
2065
2066 // TODO: don't create new blocks if recycling an old packet
2067 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
2068 AgentWearablesUpdatePacket.WearableDataBlock awb;
2069 for (int i = 0; i < wearables.Length; i++)
2070 {
2071 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
2072 awb.WearableType = (byte)i;
2073 awb.AssetID = wearables[i].AssetID;
2074 awb.ItemID = wearables[i].ItemID;
2075 aw.WearableData[i] = awb;
2076 }
2077
2078 OutPacket(aw, ThrottleOutPacketType.Task);
2079 }
2080
2081 /// <summary>
2082 ///
2083 /// </summary>
2084 /// <param name="agentID"></param>
2085 /// <param name="visualParams"></param>
2086 /// <param name="textureEntry"></param>
2087 public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry)
2088 {
2089 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
2090 // TODO: don't create new blocks if recycling an old packet
2091 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
2092 avp.ObjectData.TextureEntry = textureEntry;
2093
2094 AvatarAppearancePacket.VisualParamBlock avblock = null;
2095 for (int i = 0; i < visualParams.Length; i++)
2096 {
2097 avblock = new AvatarAppearancePacket.VisualParamBlock();
2098 avblock.ParamValue = visualParams[i];
2099 avp.VisualParam[i] = avblock;
2100 }
2101
2102 avp.Sender.IsTrial = false;
2103 avp.Sender.ID = agentID;
2104 OutPacket(avp, ThrottleOutPacketType.Task);
2105 }
2106
2107 public void SendAnimations(LLUUID[] animations, int[] seqs, LLUUID sourceAgentId)
2108 {
2109 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
2110 // TODO: don't create new blocks if recycling an old packet
2111 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1];
2112 ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock();
2113 ani.AnimationSourceList[0].ObjectID = sourceAgentId;
2114 ani.Sender = new AvatarAnimationPacket.SenderBlock();
2115 ani.Sender.ID = sourceAgentId;
2116 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
2117
2118 for (int i = 0; i < animations.Length; ++i)
2119 {
2120 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
2121 ani.AnimationList[i].AnimID = animations[i];
2122 ani.AnimationList[i].AnimSequenceID = seqs[i];
2123 }
2124 ani.Header.Reliable = false;
2125 OutPacket(ani, ThrottleOutPacketType.Task);
2126 }
2127
2128 #endregion
2129
2130 #region Avatar Packet/data sending Methods
2131
2132 /// <summary>
2133 /// send a objectupdate packet with information about the clients avatar
2134 /// </summary>
2135 /// <param name="regionInfo"></param>
2136 /// <param name="firstName"></param>
2137 /// <param name="lastName"></param>
2138 /// <param name="avatarID"></param>
2139 /// <param name="avatarLocalID"></param>
2140 /// <param name="Pos"></param>
2141 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID,
2142 uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID, LLQuaternion rotation)
2143 {
2144 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
2145 // TODO: don't create new blocks if recycling an old packet
2146 objupdate.RegionData.RegionHandle = regionHandle;
2147 objupdate.RegionData.TimeDilation = ushort.MaxValue;
2148 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
2149 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry);
2150
2151 //give this avatar object a local id and assign the user a name
2152 objupdate.ObjectData[0].ID = avatarLocalID;
2153 objupdate.ObjectData[0].FullID = avatarID;
2154 objupdate.ObjectData[0].ParentID = parentID;
2155 objupdate.ObjectData[0].NameValue =
2156 Helpers.StringToField("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName);
2157
2158 LLVector3 pos2 = new LLVector3((float)Pos.X, (float)Pos.Y, (float)Pos.Z);
2159 byte[] pb = pos2.GetBytes();
2160 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
2161
2162 byte[] rot = rotation.GetBytes();
2163 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length);
2164
2165 objupdate.Header.Zerocoded = true;
2166 OutPacket(objupdate, ThrottleOutPacketType.Task);
2167 }
2168
2169 /// <summary>
2170 ///
2171 /// </summary>
2172 /// <param name="regionHandle"></param>
2173 /// <param name="timeDilation"></param>
2174 /// <param name="localID"></param>
2175 /// <param name="position"></param>
2176 /// <param name="velocity"></param>
2177 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
2178 LLVector3 velocity, LLQuaternion rotation)
2179 {
2180 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
2181 rotation = LLQuaternion.Identity;
2182
2183 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock =
2184 CreateAvatarImprovedBlock(localID, position, velocity, rotation);
2185 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
2186 // TODO: don't create new blocks if recycling an old packet
2187 terse.RegionData.RegionHandle = regionHandle;
2188 terse.RegionData.TimeDilation = timeDilation;
2189 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
2190 terse.ObjectData[0] = terseBlock;
2191
2192 terse.Header.Reliable = false;
2193
2194 terse.Header.Zerocoded = true;
2195 OutPacket(terse, ThrottleOutPacketType.Task);
2196 }
2197
2198 public void SendCoarseLocationUpdate(List<LLVector3> CoarseLocations)
2199 {
2200 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
2201 // TODO: don't create new blocks if recycling an old packet
2202 int total = CoarseLocations.Count;
2203 CoarseLocationUpdatePacket.IndexBlock ib =
2204 new CoarseLocationUpdatePacket.IndexBlock();
2205 loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total];
2206 for (int i = 0; i < total; i++)
2207 {
2208 CoarseLocationUpdatePacket.LocationBlock lb =
2209 new CoarseLocationUpdatePacket.LocationBlock();
2210 lb.X = (byte)CoarseLocations[i].X;
2211 lb.Y = (byte)CoarseLocations[i].Y;
2212 lb.Z = (byte)(CoarseLocations[i].Z / 4);
2213 loc.Location[i] = lb;
2214 }
2215 ib.You = -1;
2216 ib.Prey = -1;
2217 loc.Index = ib;
2218 loc.Header.Reliable = false;
2219 loc.Header.Zerocoded = true;
2220 OutPacket(loc, ThrottleOutPacketType.Task);
2221 }
2222
2223 #endregion
2224
2225 #region Primitive Packet/data Sending Methods
2226
2227 /// <summary>
2228 ///
2229 /// </summary>
2230 /// <param name="localID"></param>
2231 /// <param name="rotation"></param>
2232 /// <param name="attachPoint"></param>
2233 public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint)
2234 {
2235
2236 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach);
2237 Console.WriteLine("Attach object!");
2238 // TODO: don't create new blocks if recycling an old packet
2239 attach.AgentData.AgentID = AgentId;
2240 attach.AgentData.SessionID = m_sessionId;
2241 attach.AgentData.AttachmentPoint = attachPoint;
2242 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
2243 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
2244 attach.ObjectData[0].ObjectLocalID = localID;
2245 attach.ObjectData[0].Rotation = rotation;
2246 attach.Header.Zerocoded = true;
2247 OutPacket(attach, ThrottleOutPacketType.Task);
2248 }
2249
2250 public void SendPrimitiveToClient(
2251 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
2252 LLVector3 pos, LLVector3 vel, LLVector3 acc, LLQuaternion rotation, LLVector3 rvel,
2253 uint flags, LLUUID objectID, LLUUID ownerID, string text, byte[] color,
2254 uint parentID, byte[] particleSystem, byte clickAction)
2255 {
2256 byte[] textureanim = new byte[0];
2257
2258 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel,
2259 acc, rotation, rvel, flags,
2260 objectID, ownerID, text, color, parentID, particleSystem,
2261 clickAction, textureanim, false, (uint)0, LLUUID.Zero, LLUUID.Zero, 0, 0, 0);
2262 }
2263
2264 public void SendPrimitiveToClient(
2265 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
2266 LLVector3 pos, LLVector3 velocity, LLVector3 acceleration, LLQuaternion rotation, LLVector3 rotational_velocity,
2267 uint flags,
2268 LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
2269 byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId, LLUUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
2270 {
2271
2272 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
2273 rotation = LLQuaternion.Identity;
2274
2275 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
2276
2277
2278
2279 // TODO: don't create new blocks if recycling an old packet
2280 outPacket.RegionData.RegionHandle = regionHandle;
2281 outPacket.RegionData.TimeDilation = timeDilation;
2282 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
2283
2284 outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags);
2285
2286 outPacket.ObjectData[0].ID = localID;
2287 outPacket.ObjectData[0].FullID = objectID;
2288 outPacket.ObjectData[0].OwnerID = ownerID;
2289
2290 // Anything more than 255 will cause libsecondlife to barf
2291 if (text.Length > 255)
2292 {
2293 text = text.Remove(255);
2294 }
2295
2296 outPacket.ObjectData[0].Text = Helpers.StringToField(text);
2297
2298 outPacket.ObjectData[0].TextColor[0] = color[0];
2299 outPacket.ObjectData[0].TextColor[1] = color[1];
2300 outPacket.ObjectData[0].TextColor[2] = color[2];
2301 outPacket.ObjectData[0].TextColor[3] = color[3];
2302 outPacket.ObjectData[0].ParentID = parentID;
2303 outPacket.ObjectData[0].PSBlock = particleSystem;
2304 outPacket.ObjectData[0].ClickAction = clickAction;
2305 outPacket.ObjectData[0].Flags = 0;
2306
2307 if (attachment)
2308 {
2309 // Necessary???
2310 outPacket.ObjectData[0].JointAxisOrAnchor = new LLVector3(0, 0, 2);
2311 outPacket.ObjectData[0].JointPivot = new LLVector3(0, 0, 0);
2312
2313 // Item from inventory???
2314 outPacket.ObjectData[0].NameValue =
2315 Helpers.StringToField("AttachItemID STRING RW SV " + AssetId.UUID);
2316 outPacket.ObjectData[0].State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
2317 }
2318
2319 // Xantor 20080528: Send sound info as well
2320 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again
2321 outPacket.ObjectData[0].Sound = SoundId;
2322 if (SoundId == LLUUID.Zero)
2323 {
2324 outPacket.ObjectData[0].OwnerID = LLUUID.Zero;
2325 outPacket.ObjectData[0].Gain = 0.0f;
2326 outPacket.ObjectData[0].Radius = 0.0f;
2327 outPacket.ObjectData[0].Flags = 0;
2328 }
2329 else
2330 {
2331 outPacket.ObjectData[0].OwnerID = ownerID;
2332 outPacket.ObjectData[0].Gain = (float)SoundGain;
2333 outPacket.ObjectData[0].Radius = (float)SoundRadius;
2334 outPacket.ObjectData[0].Flags = SoundFlags;
2335 }
2336
2337 byte[] pb = pos.GetBytes();
2338 Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length);
2339
2340 byte[] vel = velocity.GetBytes();
2341 Array.Copy(vel, 0, outPacket.ObjectData[0].ObjectData, pb.Length, vel.Length);
2342
2343 byte[] rot = rotation.GetBytes();
2344 Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length);
2345
2346 byte[] rvel = rotational_velocity.GetBytes();
2347 Array.Copy(rvel, 0, outPacket.ObjectData[0].ObjectData, 36 + rot.Length, rvel.Length);
2348
2349 if (textureanim.Length > 0)
2350 {
2351 outPacket.ObjectData[0].TextureAnim = textureanim;
2352 }
2353 outPacket.Header.Zerocoded = true;
2354
2355 OutPacket(outPacket, ThrottleOutPacketType.LowpriorityTask);
2356 }
2357
2358 /// <summary>
2359 ///
2360 /// </summary>
2361 /// <param name="regionHandle"></param>
2362 /// <param name="timeDilation"></param>
2363 /// <param name="localID"></param>
2364 /// <param name="position"></param>
2365 /// <param name="rotation"></param>
2366 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
2367 LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity, byte state, LLUUID AssetId)
2368 {
2369 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
2370 rotation = LLQuaternion.Identity;
2371 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
2372 // TODO: don't create new blocks if recycling an old packet
2373 terse.RegionData.RegionHandle = regionHandle;
2374 terse.RegionData.TimeDilation = timeDilation;
2375 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
2376 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow...
2377 terse.Header.Reliable = false;
2378 terse.Header.Zerocoded = true;
2379 OutPacket(terse, ThrottleOutPacketType.LowpriorityTask);
2380 }
2381
2382 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
2383 LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity)
2384 {
2385 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
2386 rotation = LLQuaternion.Identity;
2387 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
2388 // TODO: don't create new blocks if recycling an old packet
2389 terse.RegionData.RegionHandle = regionHandle;
2390 terse.RegionData.TimeDilation = timeDilation;
2391 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
2392 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, 0);
2393 terse.Header.Reliable = false;
2394 terse.Header.Zerocoded = true;
2395 OutPacket(terse, ThrottleOutPacketType.LowpriorityTask);
2396 }
2397
2398 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, LLUUID AssetFullID)
2399 {
2400 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
2401 newPack.AssetBlock.Type = AssetType;
2402 newPack.AssetBlock.Success = Success;
2403 newPack.AssetBlock.UUID = AssetFullID;
2404 newPack.Header.Zerocoded = true;
2405 OutPacket(newPack, ThrottleOutPacketType.Asset);
2406 }
2407
2408 public void SendXferRequest(ulong XferID, short AssetType, LLUUID vFileID, byte FilePath, byte[] FileName)
2409 {
2410 RequestXferPacket newPack = new RequestXferPacket();
2411 newPack.XferID.ID = XferID;
2412 newPack.XferID.VFileType = AssetType;
2413 newPack.XferID.VFileID = vFileID;
2414 newPack.XferID.FilePath = FilePath;
2415 newPack.XferID.Filename = FileName;
2416 newPack.Header.Zerocoded = true;
2417 OutPacket(newPack, ThrottleOutPacketType.Asset);
2418 }
2419
2420 public void SendConfirmXfer(ulong xferID, uint PacketID)
2421 {
2422 ConfirmXferPacketPacket newPack = new ConfirmXferPacketPacket();
2423 newPack.XferID.ID = xferID;
2424 newPack.XferID.Packet = PacketID;
2425 newPack.Header.Zerocoded = true;
2426 OutPacket(newPack, ThrottleOutPacketType.Asset);
2427 }
2428
2429 public void SendImagePart(ushort numParts, LLUUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
2430 {
2431 ImageDataPacket im = new ImageDataPacket();
2432 im.Header.Reliable = false;
2433 im.ImageID.Packets = numParts;
2434 im.ImageID.ID = ImageUUID;
2435
2436 if (ImageSize > 0)
2437 im.ImageID.Size = ImageSize;
2438
2439 im.ImageData.Data = ImageData;
2440 im.ImageID.Codec = imageCodec;
2441 im.Header.Zerocoded = true;
2442 OutPacket(im, ThrottleOutPacketType.Texture);
2443 }
2444
2445 public void SendShutdownConnectionNotice()
2446 {
2447 OutPacket(PacketPool.Instance.GetPacket(PacketType.DisableSimulator), ThrottleOutPacketType.Unknown);
2448 }
2449
2450 public void SendSimStats(Packet pack)
2451 {
2452 pack.Header.Reliable = false;
2453 OutPacket(pack, ThrottleOutPacketType.Task);
2454 }
2455
2456 public void SendObjectPropertiesFamilyData(uint RequestFlags, LLUUID ObjectUUID, LLUUID OwnerID, LLUUID GroupID,
2457 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask,
2458 uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category,
2459 LLUUID LastOwnerID, string ObjectName, string Description)
2460 {
2461 ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
2462 // TODO: don't create new blocks if recycling an old packet
2463
2464 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
2465 objPropDB.RequestFlags = RequestFlags;
2466 objPropDB.ObjectID = ObjectUUID;
2467 objPropDB.OwnerID = OwnerID;
2468 objPropDB.GroupID = GroupID;
2469 objPropDB.BaseMask = BaseMask;
2470 objPropDB.OwnerMask = OwnerMask;
2471 objPropDB.GroupMask = GroupMask;
2472 objPropDB.EveryoneMask = EveryoneMask;
2473 objPropDB.NextOwnerMask = NextOwnerMask;
2474
2475 // TODO: More properties are needed in SceneObjectPart!
2476 objPropDB.OwnershipCost = OwnershipCost;
2477 objPropDB.SaleType = SaleType;
2478 objPropDB.SalePrice = SalePrice;
2479 objPropDB.Category = Category;
2480 objPropDB.LastOwnerID = LastOwnerID;
2481 objPropDB.Name = Helpers.StringToField(ObjectName);
2482 objPropDB.Description = Helpers.StringToField(Description);
2483 objPropFamilyPack.ObjectData = objPropDB;
2484 objPropFamilyPack.Header.Zerocoded = true;
2485 OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
2486 }
2487
2488 public void SendObjectPropertiesReply(LLUUID ItemID, ulong CreationDate, LLUUID CreatorUUID, LLUUID FolderUUID, LLUUID FromTaskUUID,
2489 LLUUID GroupUUID, short InventorySerial, LLUUID LastOwnerUUID, LLUUID ObjectUUID,
2490 LLUUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
2491 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
2492 uint BaseMask)
2493 {
2494 ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
2495 // TODO: don't create new blocks if recycling an old packet
2496
2497 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1];
2498 proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock();
2499 proper.ObjectData[0].ItemID = ItemID;
2500 proper.ObjectData[0].CreationDate = CreationDate;
2501 proper.ObjectData[0].CreatorID = CreatorUUID;
2502 proper.ObjectData[0].FolderID = FolderUUID;
2503 proper.ObjectData[0].FromTaskID = FromTaskUUID;
2504 proper.ObjectData[0].GroupID = GroupUUID;
2505 proper.ObjectData[0].InventorySerial = InventorySerial;
2506
2507 proper.ObjectData[0].LastOwnerID = LastOwnerUUID;
2508 // proper.ObjectData[0].LastOwnerID = LLUUID.Zero;
2509
2510 proper.ObjectData[0].ObjectID = ObjectUUID;
2511 proper.ObjectData[0].OwnerID = OwnerUUID;
2512 proper.ObjectData[0].TouchName = Helpers.StringToField(TouchTitle);
2513 proper.ObjectData[0].TextureID = TextureID;
2514 proper.ObjectData[0].SitName = Helpers.StringToField(SitTitle);
2515 proper.ObjectData[0].Name = Helpers.StringToField(ItemName);
2516 proper.ObjectData[0].Description = Helpers.StringToField(ItemDescription);
2517 proper.ObjectData[0].OwnerMask = OwnerMask;
2518 proper.ObjectData[0].NextOwnerMask = NextOwnerMask;
2519 proper.ObjectData[0].GroupMask = GroupMask;
2520 proper.ObjectData[0].EveryoneMask = EveryoneMask;
2521 proper.ObjectData[0].BaseMask = BaseMask;
2522 // proper.ObjectData[0].AggregatePerms = 53;
2523 // proper.ObjectData[0].AggregatePermTextures = 0;
2524 // proper.ObjectData[0].AggregatePermTexturesOwner = 0;
2525 proper.Header.Zerocoded = true;
2526 OutPacket(proper, ThrottleOutPacketType.Task);
2527 }
2528
2529 #endregion
2530
2531 #region Estate Data Sending Methods
2532
2533 private bool convertParamStringToBool(byte[] field)
2534 {
2535 string s = Helpers.FieldToUTF8String(field);
2536 if (s == "1" || s.ToLower() == "y" || s.ToLower() == "yes" || s.ToLower() == "t" || s.ToLower() == "true")
2537 {
2538 return true;
2539 }
2540 return false;
2541 }
2542
2543 public void SendEstateManagersList(LLUUID invoice, LLUUID[] EstateManagers, uint estateID)
2544 {
2545 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
2546 packet.AgentData.TransactionID = LLUUID.Random();
2547 packet.AgentData.AgentID = this.AgentId;
2548 packet.AgentData.SessionID = this.SessionId;
2549 packet.MethodData.Invoice = invoice;
2550 packet.MethodData.Method = Helpers.StringToField("setaccess");
2551
2552 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + EstateManagers.Length];
2553
2554 for (int i = 0; i < (6 + EstateManagers.Length); i++)
2555 {
2556 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
2557 }
2558 int j = 0;
2559
2560 returnblock[j].Parameter = Helpers.StringToField(estateID.ToString()); j++;
2561 returnblock[j].Parameter = Helpers.StringToField(((int)Constants.EstateAccessCodex.EstateManagers).ToString()); j++;
2562 returnblock[j].Parameter = Helpers.StringToField("0"); j++;
2563 returnblock[j].Parameter = Helpers.StringToField("0"); j++;
2564 returnblock[j].Parameter = Helpers.StringToField("0"); j++;
2565 returnblock[j].Parameter = Helpers.StringToField(EstateManagers.Length.ToString()); j++;
2566 for (int i = 0; i < EstateManagers.Length; i++)
2567 {
2568 returnblock[j].Parameter = EstateManagers[i].GetBytes(); j++;
2569 }
2570 packet.ParamList = returnblock;
2571 packet.Header.Reliable = false;
2572 this.OutPacket(packet, ThrottleOutPacketType.Task);
2573 }
2574
2575 public void SendBannedUserList(LLUUID invoice, EstateBan[] bl, uint estateID)
2576 {
2577 List<LLUUID>BannedUsers = new List<LLUUID>();
2578
2579 for (int i = 0; i < bl.Length; i++)
2580 {
2581 if (bl[i] == null)
2582 continue;
2583 if (bl[i].bannedUUID == LLUUID.Zero)
2584 continue;
2585 BannedUsers.Add(bl[i].bannedUUID);
2586 }
2587
2588 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
2589 packet.AgentData.TransactionID = LLUUID.Random();
2590 packet.AgentData.AgentID = this.AgentId;
2591 packet.AgentData.SessionID = this.SessionId;
2592 packet.MethodData.Invoice = invoice;
2593 packet.MethodData.Method = Helpers.StringToField("setaccess");
2594
2595 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
2596
2597 for (int i = 0; i < (6 + BannedUsers.Count); i++)
2598 {
2599 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
2600 }
2601 int j = 0;
2602
2603 returnblock[j].Parameter = Helpers.StringToField(estateID.ToString()); j++;
2604 returnblock[j].Parameter = Helpers.StringToField(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
2605 returnblock[j].Parameter = Helpers.StringToField("0"); j++;
2606 returnblock[j].Parameter = Helpers.StringToField("0"); j++;
2607 returnblock[j].Parameter = Helpers.StringToField(BannedUsers.Count.ToString()); j++;
2608 returnblock[j].Parameter = Helpers.StringToField("0"); j++;
2609
2610 foreach (LLUUID banned in BannedUsers)
2611 {
2612 returnblock[j].Parameter = banned.GetBytes(); j++;
2613 }
2614 packet.ParamList = returnblock;
2615 packet.Header.Reliable = false;
2616 this.OutPacket(packet, ThrottleOutPacketType.Task);
2617 }
2618
2619 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
2620 {
2621 RegionInfoPacket rinfopack = new RegionInfoPacket();
2622 RegionInfoPacket.RegionInfoBlock rinfoblk = new RegionInfoPacket.RegionInfoBlock();
2623 rinfopack.AgentData.AgentID = this.AgentId;
2624 rinfopack.AgentData.SessionID = this.SessionId;
2625 rinfoblk.BillableFactor = args.billableFactor;
2626 rinfoblk.EstateID = args.estateID;
2627 rinfoblk.MaxAgents = args.maxAgents;
2628 rinfoblk.ObjectBonusFactor = args.objectBonusFactor;
2629 rinfoblk.ParentEstateID = args.parentEstateID;
2630 rinfoblk.PricePerMeter = args.pricePerMeter;
2631 rinfoblk.RedirectGridX = args.redirectGridX;
2632 rinfoblk.RedirectGridY = args.redirectGridY;
2633 rinfoblk.RegionFlags = args.regionFlags;
2634 rinfoblk.SimAccess = args.simAccess;
2635 rinfoblk.SunHour = args.sunHour;
2636 rinfoblk.TerrainLowerLimit = args.terrainLowerLimit;
2637 rinfoblk.TerrainRaiseLimit = args.terrainRaiseLimit;
2638 rinfoblk.UseEstateSun = args.useEstateSun;
2639 rinfoblk.WaterHeight = args.waterHeight;
2640 rinfoblk.SimName = Helpers.StringToField(args.simName);
2641
2642 rinfopack.RegionInfo = rinfoblk;
2643
2644 this.OutPacket(rinfopack, ThrottleOutPacketType.Task);
2645 }
2646
2647 public void SendEstateCovenantInformation(LLUUID covenant)
2648 {
2649 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket();
2650 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
2651 edata.CovenantID = covenant;
2652 edata.CovenantTimestamp = 0;
2653 edata.EstateOwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
2654 edata.EstateName =
2655 Helpers.StringToField(m_scene.RegionInfo.MasterAvatarFirstName + " " + m_scene.RegionInfo.MasterAvatarLastName);
2656 einfopack.Data = edata;
2657 this.OutPacket(einfopack, ThrottleOutPacketType.Task);
2658 }
2659
2660 public void SendDetailedEstateData(LLUUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, LLUUID covenant, string abuseEmail)
2661 {
2662 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
2663 packet.MethodData.Invoice = invoice;
2664 packet.AgentData.TransactionID = LLUUID.Random();
2665 packet.MethodData.Method = Helpers.StringToField("estateupdateinfo");
2666 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[10];
2667
2668 for (int i = 0; i < 10; i++)
2669 {
2670 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
2671 }
2672
2673 //Sending Estate Settings
2674 returnblock[0].Parameter = Helpers.StringToField(estateName);
2675 returnblock[1].Parameter = Helpers.StringToField(m_scene.RegionInfo.MasterAvatarAssignedUUID.ToString());
2676 returnblock[2].Parameter = Helpers.StringToField(estateID.ToString());
2677
2678 returnblock[3].Parameter = Helpers.StringToField(estateFlags.ToString());
2679 returnblock[4].Parameter = Helpers.StringToField(sunPosition.ToString());
2680 returnblock[5].Parameter = Helpers.StringToField(parentEstate.ToString());
2681 returnblock[6].Parameter = Helpers.StringToField(covenant.ToString());
2682 returnblock[7].Parameter = Helpers.StringToField("1160895077"); // what is this?
2683 returnblock[8].Parameter = Helpers.StringToField("1"); // what is this?
2684 returnblock[9].Parameter = Helpers.StringToField(abuseEmail);
2685
2686 packet.ParamList = returnblock;
2687 packet.Header.Reliable = false;
2688 //System.Console.WriteLine("[ESTATE]: SIM--->" + packet.ToString());
2689 this.OutPacket(packet, ThrottleOutPacketType.Task);
2690 }
2691
2692 #endregion
2693
2694 #region Land Data Sending Methods
2695
2696 public void SendLandParcelOverlay(byte[] data, int sequence_id)
2697 {
2698
2699 ParcelOverlayPacket packet;
2700 packet = (ParcelOverlayPacket)PacketPool.Instance.GetPacket(PacketType.ParcelOverlay);
2701 packet.ParcelData.Data = data;
2702 packet.ParcelData.SequenceID = sequence_id;
2703 packet.Header.Zerocoded = true;
2704 this.OutPacket(packet, ThrottleOutPacketType.Task);
2705 }
2706
2707 public void SendLandProperties(IClientAPI remote_client, int sequence_id, bool snap_selection, int request_result, LandData landData, float simObjectBonusFactor, int parcelObjectCapacity, int simObjectCapacity, uint regionFlags)
2708 {
2709 ParcelPropertiesPacket updatePacket = (ParcelPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ParcelProperties);
2710 // TODO: don't create new blocks if recycling an old packet
2711
2712 updatePacket.ParcelData.AABBMax = landData.AABBMax;
2713 updatePacket.ParcelData.AABBMin = landData.AABBMin;
2714 updatePacket.ParcelData.Area = landData.Area;
2715 updatePacket.ParcelData.AuctionID = landData.AuctionID;
2716 updatePacket.ParcelData.AuthBuyerID = landData.AuthBuyerID; //unemplemented
2717
2718 updatePacket.ParcelData.Bitmap = landData.Bitmap;
2719
2720 updatePacket.ParcelData.Desc = Helpers.StringToField(landData.Description);
2721 updatePacket.ParcelData.Category = (byte)landData.Category;
2722 updatePacket.ParcelData.ClaimDate = landData.ClaimDate;
2723 updatePacket.ParcelData.ClaimPrice = landData.ClaimPrice;
2724 updatePacket.ParcelData.GroupID = landData.GroupID;
2725 updatePacket.ParcelData.GroupPrims = landData.GroupPrims;
2726 updatePacket.ParcelData.IsGroupOwned = landData.IsGroupOwned;
2727 updatePacket.ParcelData.LandingType = (byte)landData.LandingType;
2728 updatePacket.ParcelData.LocalID = landData.LocalID;
2729 if (landData.Area > 0)
2730 {
2731 updatePacket.ParcelData.MaxPrims = parcelObjectCapacity;
2732 }
2733 else
2734 {
2735 updatePacket.ParcelData.MaxPrims = 0;
2736 }
2737 updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale;
2738 updatePacket.ParcelData.MediaID = landData.MediaID;
2739 updatePacket.ParcelData.MediaURL = Helpers.StringToField(landData.MediaURL);
2740 updatePacket.ParcelData.MusicURL = Helpers.StringToField(landData.MusicURL);
2741 updatePacket.ParcelData.Name = Helpers.StringToField(landData.Name);
2742 updatePacket.ParcelData.OtherCleanTime = 0; //unemplemented
2743 updatePacket.ParcelData.OtherCount = 0; //unemplemented
2744 updatePacket.ParcelData.OtherPrims = landData.OtherPrims;
2745 updatePacket.ParcelData.OwnerID = landData.OwnerID;
2746 updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims;
2747 updatePacket.ParcelData.ParcelFlags = landData.Flags;
2748 updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor;
2749 updatePacket.ParcelData.PassHours = landData.PassHours;
2750 updatePacket.ParcelData.PassPrice = landData.PassPrice;
2751 updatePacket.ParcelData.PublicCount = 0; //unemplemented
2752
2753 updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)Simulator.RegionFlags.DenyAnonymous) >
2754 0);
2755 updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)Simulator.RegionFlags.DenyIdentified) >
2756 0);
2757 updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)Simulator.RegionFlags.DenyTransacted) >
2758 0);
2759 updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)Simulator.RegionFlags.RestrictPushObject) >
2760 0);
2761
2762 updatePacket.ParcelData.RentPrice = 0;
2763 updatePacket.ParcelData.RequestResult = request_result;
2764 updatePacket.ParcelData.SalePrice = landData.SalePrice;
2765 updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims;
2766 updatePacket.ParcelData.SelfCount = 0; //unemplemented
2767 updatePacket.ParcelData.SequenceID = sequence_id;
2768 if (landData.SimwideArea > 0)
2769 {
2770 updatePacket.ParcelData.SimWideMaxPrims = parcelObjectCapacity;
2771 }
2772 else
2773 {
2774 updatePacket.ParcelData.SimWideMaxPrims = 0;
2775 }
2776 updatePacket.ParcelData.SimWideTotalPrims = landData.SimwidePrims;
2777 updatePacket.ParcelData.SnapSelection = snap_selection;
2778 updatePacket.ParcelData.SnapshotID = landData.SnapshotID;
2779 updatePacket.ParcelData.Status = (byte)landData.Status;
2780 updatePacket.ParcelData.TotalPrims = landData.OwnerPrims + landData.GroupPrims + landData.OtherPrims +
2781 landData.SelectedPrims;
2782 updatePacket.ParcelData.UserLocation = landData.UserLocation;
2783 updatePacket.ParcelData.UserLookAt = landData.UserLookAt;
2784 updatePacket.Header.Zerocoded = true;
2785 remote_client.OutPacket((Packet)updatePacket, ThrottleOutPacketType.Task);
2786 }
2787
2788 public void SendLandAccessListData(List<LLUUID> avatars, uint accessFlag, int localLandID)
2789 {
2790 ParcelAccessListReplyPacket replyPacket = (ParcelAccessListReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelAccessListReply);
2791 replyPacket.Data.AgentID = this.AgentId;
2792 replyPacket.Data.Flags = accessFlag;
2793 replyPacket.Data.LocalID = localLandID;
2794 replyPacket.Data.SequenceID = 0;
2795
2796 List<ParcelAccessListReplyPacket.ListBlock> list = new List<ParcelAccessListReplyPacket.ListBlock>();
2797 foreach (LLUUID avatar in avatars)
2798 {
2799 ParcelAccessListReplyPacket.ListBlock block = new ParcelAccessListReplyPacket.ListBlock();
2800 block.Flags = accessFlag;
2801 block.ID = avatar;
2802 block.Time = 0;
2803 }
2804
2805 replyPacket.List = list.ToArray();
2806 replyPacket.Header.Zerocoded = true;
2807 this.OutPacket((Packet)replyPacket, ThrottleOutPacketType.Task);
2808 }
2809
2810 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
2811 {
2812 bool firstCall = true;
2813 int MAX_OBJECTS_PER_PACKET = 251;
2814 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
2815 ForceObjectSelectPacket.DataBlock[] data;
2816 while (ObjectIDs.Count > 0)
2817 {
2818 if (firstCall)
2819 {
2820 pack._Header.ResetList = true;
2821 firstCall = false;
2822 }
2823 else
2824 {
2825 pack._Header.ResetList = false;
2826 }
2827
2828 if (ObjectIDs.Count > MAX_OBJECTS_PER_PACKET)
2829 {
2830 data = new ForceObjectSelectPacket.DataBlock[MAX_OBJECTS_PER_PACKET];
2831 }
2832 else
2833 {
2834 data = new ForceObjectSelectPacket.DataBlock[ObjectIDs.Count];
2835 }
2836
2837 int i;
2838 for (i = 0; i < MAX_OBJECTS_PER_PACKET && ObjectIDs.Count > 0; i++)
2839 {
2840 data[i] = new ForceObjectSelectPacket.DataBlock();
2841 data[i].LocalID = Convert.ToUInt32(ObjectIDs[0]);
2842 ObjectIDs.RemoveAt(0);
2843 }
2844 pack.Data = data;
2845 pack.Header.Zerocoded = true;
2846 this.OutPacket((Packet)pack, ThrottleOutPacketType.Task);
2847 }
2848 }
2849
2850 public void SendLandObjectOwners(Dictionary<LLUUID, int> ownersAndCount)
2851 {
2852 int notifyCount = ownersAndCount.Count;
2853 ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
2854
2855 if (notifyCount > 0)
2856 {
2857 if (notifyCount > 32)
2858 {
2859 m_log.InfoFormat(
2860 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
2861 + " - a developer might want to investigate whether this is a hard limit", 32);
2862
2863 notifyCount = 32;
2864 }
2865
2866 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
2867 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
2868
2869 int num = 0;
2870 foreach (LLUUID owner in ownersAndCount.Keys)
2871 {
2872 dataBlock[num] = new ParcelObjectOwnersReplyPacket.DataBlock();
2873 dataBlock[num].Count = ownersAndCount[owner];
2874 dataBlock[num].IsGroupOwned = false; //TODO: fix me when group support is added
2875 dataBlock[num].OnlineStatus = true; //TODO: fix me later
2876 dataBlock[num].OwnerID = owner;
2877
2878 num++;
2879
2880 if (num >= notifyCount)
2881 {
2882 break;
2883 }
2884 }
2885
2886 pack.Data = dataBlock;
2887 }
2888 pack.Header.Zerocoded = true;
2889 this.OutPacket(pack, ThrottleOutPacketType.Task);
2890 }
2891
2892 #endregion
2893
2894 #region Helper Methods
2895
2896 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, LLVector3 pos,
2897 LLVector3 velocity,
2898 LLQuaternion rotation)
2899 {
2900 byte[] bytes = new byte[60];
2901 int i = 0;
2902 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
2903
2904 dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry;
2905
2906 uint ID = localID;
2907
2908 bytes[i++] = (byte)(ID % 256);
2909 bytes[i++] = (byte)((ID >> 8) % 256);
2910 bytes[i++] = (byte)((ID >> 16) % 256);
2911 bytes[i++] = (byte)((ID >> 24) % 256);
2912 bytes[i++] = 0;
2913 bytes[i++] = 1;
2914 i += 14;
2915 bytes[i++] = 128;
2916 bytes[i++] = 63;
2917
2918 byte[] pb = pos.GetBytes();
2919 Array.Copy(pb, 0, bytes, i, pb.Length);
2920 i += 12;
2921 ushort InternVelocityX;
2922 ushort InternVelocityY;
2923 ushort InternVelocityZ;
2924 Vector3 internDirec = new Vector3(0, 0, 0);
2925
2926 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z);
2927
2928 internDirec = internDirec / 128.0f;
2929 internDirec.x += 1;
2930 internDirec.y += 1;
2931 internDirec.z += 1;
2932
2933 InternVelocityX = (ushort)(32768 * internDirec.x);
2934 InternVelocityY = (ushort)(32768 * internDirec.y);
2935 InternVelocityZ = (ushort)(32768 * internDirec.z);
2936
2937 ushort ac = 32767;
2938 bytes[i++] = (byte)(InternVelocityX % 256);
2939 bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
2940 bytes[i++] = (byte)(InternVelocityY % 256);
2941 bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
2942 bytes[i++] = (byte)(InternVelocityZ % 256);
2943 bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
2944
2945 //accel
2946 bytes[i++] = (byte)(ac % 256);
2947 bytes[i++] = (byte)((ac >> 8) % 256);
2948 bytes[i++] = (byte)(ac % 256);
2949 bytes[i++] = (byte)((ac >> 8) % 256);
2950 bytes[i++] = (byte)(ac % 256);
2951 bytes[i++] = (byte)((ac >> 8) % 256);
2952
2953 //rotation
2954 ushort rw, rx, ry, rz;
2955 rw = (ushort)(32768 * (rotation.W + 1));
2956 rx = (ushort)(32768 * (rotation.X + 1));
2957 ry = (ushort)(32768 * (rotation.Y + 1));
2958 rz = (ushort)(32768 * (rotation.Z + 1));
2959
2960 //rot
2961 bytes[i++] = (byte)(rx % 256);
2962 bytes[i++] = (byte)((rx >> 8) % 256);
2963 bytes[i++] = (byte)(ry % 256);
2964 bytes[i++] = (byte)((ry >> 8) % 256);
2965 bytes[i++] = (byte)(rz % 256);
2966 bytes[i++] = (byte)((rz >> 8) % 256);
2967 bytes[i++] = (byte)(rw % 256);
2968 bytes[i++] = (byte)((rw >> 8) % 256);
2969
2970 //rotation vel
2971 bytes[i++] = (byte)(ac % 256);
2972 bytes[i++] = (byte)((ac >> 8) % 256);
2973 bytes[i++] = (byte)(ac % 256);
2974 bytes[i++] = (byte)((ac >> 8) % 256);
2975 bytes[i++] = (byte)(ac % 256);
2976 bytes[i++] = (byte)((ac >> 8) % 256);
2977
2978 dat.Data = bytes;
2979
2980 return (dat);
2981 }
2982
2983 /// <summary>
2984 ///
2985 /// </summary>
2986 /// <param name="localID"></param>
2987 /// <param name="position"></param>
2988 /// <param name="rotation"></param>
2989 /// <returns></returns>
2990 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID,
2991 LLVector3 position,
2992 LLQuaternion rotation,
2993 LLVector3 velocity,
2994 LLVector3 rotationalvelocity,
2995 byte state)
2996 {
2997 uint ID = localID;
2998 byte[] bytes = new byte[60];
2999
3000 int i = 0;
3001 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
3002 dat.TextureEntry = new byte[0];
3003 bytes[i++] = (byte)(ID % 256);
3004 bytes[i++] = (byte)((ID >> 8) % 256);
3005 bytes[i++] = (byte)((ID >> 16) % 256);
3006 bytes[i++] = (byte)((ID >> 24) % 256);
3007 bytes[i++] = state;
3008 bytes[i++] = 0;
3009
3010 byte[] pb = position.GetBytes();
3011 Array.Copy(pb, 0, bytes, i, pb.Length);
3012 i += 12;
3013 ushort ac = 32767;
3014
3015 ushort velx, vely, velz;
3016 Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z);
3017
3018 vel = vel / 128.0f;
3019 vel.x += 1;
3020 vel.y += 1;
3021 vel.z += 1;
3022 //vel
3023 velx = (ushort)(32768 * (vel.x));
3024 vely = (ushort)(32768 * (vel.y));
3025 velz = (ushort)(32768 * (vel.z));
3026
3027 bytes[i++] = (byte)(velx % 256);
3028 bytes[i++] = (byte)((velx >> 8) % 256);
3029 bytes[i++] = (byte)(vely % 256);
3030 bytes[i++] = (byte)((vely >> 8) % 256);
3031 bytes[i++] = (byte)(velz % 256);
3032 bytes[i++] = (byte)((velz >> 8) % 256);
3033
3034 //accel
3035 bytes[i++] = (byte)(ac % 256);
3036 bytes[i++] = (byte)((ac >> 8) % 256);
3037 bytes[i++] = (byte)(ac % 256);
3038 bytes[i++] = (byte)((ac >> 8) % 256);
3039 bytes[i++] = (byte)(ac % 256);
3040 bytes[i++] = (byte)((ac >> 8) % 256);
3041
3042 ushort rw, rx, ry, rz;
3043 rw = (ushort)(32768 * (rotation.W + 1));
3044 rx = (ushort)(32768 * (rotation.X + 1));
3045 ry = (ushort)(32768 * (rotation.Y + 1));
3046 rz = (ushort)(32768 * (rotation.Z + 1));
3047
3048 //rot
3049 bytes[i++] = (byte)(rx % 256);
3050 bytes[i++] = (byte)((rx >> 8) % 256);
3051 bytes[i++] = (byte)(ry % 256);
3052 bytes[i++] = (byte)((ry >> 8) % 256);
3053 bytes[i++] = (byte)(rz % 256);
3054 bytes[i++] = (byte)((rz >> 8) % 256);
3055 bytes[i++] = (byte)(rw % 256);
3056 bytes[i++] = (byte)((rw >> 8) % 256);
3057
3058 //rotation vel
3059 ushort rvelx, rvely, rvelz;
3060 Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z);
3061
3062 rvel = rvel / 128.0f;
3063 rvel.x += 1;
3064 rvel.y += 1;
3065 rvel.z += 1;
3066 //vel
3067 rvelx = (ushort)(32768 * (rvel.x));
3068 rvely = (ushort)(32768 * (rvel.y));
3069 rvelz = (ushort)(32768 * (rvel.z));
3070
3071 bytes[i++] = (byte)(rvelx % 256);
3072 bytes[i++] = (byte)((rvelx >> 8) % 256);
3073 bytes[i++] = (byte)(rvely % 256);
3074 bytes[i++] = (byte)((rvely >> 8) % 256);
3075 bytes[i++] = (byte)(rvelz % 256);
3076 bytes[i++] = (byte)((rvelz >> 8) % 256);
3077 dat.Data = bytes;
3078
3079 return dat;
3080 }
3081
3082 /// <summary>
3083 /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive)
3084 /// </summary>
3085 /// <param name="primData"></param>
3086 /// <returns></returns>
3087 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags)
3088 {
3089 ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock();
3090 SetDefaultPrimPacketValues(objupdate);
3091 objupdate.UpdateFlags = flags;
3092 SetPrimPacketShapeData(objupdate, primShape);
3093
3094 if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass))
3095 {
3096 objupdate.Data = new byte[1];
3097 objupdate.Data[0] = primShape.State;
3098 }
3099 return objupdate;
3100 }
3101
3102 protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData)
3103 {
3104 objectData.TextureEntry = primData.TextureEntry;
3105 objectData.PCode = primData.PCode;
3106 objectData.State = primData.State;
3107 objectData.PathBegin = primData.PathBegin;
3108 objectData.PathEnd = primData.PathEnd;
3109 objectData.PathScaleX = primData.PathScaleX;
3110 objectData.PathScaleY = primData.PathScaleY;
3111 objectData.PathShearX = primData.PathShearX;
3112 objectData.PathShearY = primData.PathShearY;
3113 objectData.PathSkew = primData.PathSkew;
3114 objectData.ProfileBegin = primData.ProfileBegin;
3115 objectData.ProfileEnd = primData.ProfileEnd;
3116 objectData.Scale = primData.Scale;
3117 objectData.PathCurve = primData.PathCurve;
3118 objectData.ProfileCurve = primData.ProfileCurve;
3119 objectData.ProfileHollow = primData.ProfileHollow;
3120 objectData.PathRadiusOffset = primData.PathRadiusOffset;
3121 objectData.PathRevolutions = primData.PathRevolutions;
3122 objectData.PathTaperX = primData.PathTaperX;
3123 objectData.PathTaperY = primData.PathTaperY;
3124 objectData.PathTwist = primData.PathTwist;
3125 objectData.PathTwistBegin = primData.PathTwistBegin;
3126 objectData.ExtraParams = primData.ExtraParams;
3127 }
3128
3129 /// <summary>
3130 /// Set some default values in a ObjectUpdatePacket
3131 /// </summary>
3132 /// <param name="objdata"></param>
3133 protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata)
3134 {
3135 objdata.PSBlock = new byte[0];
3136 objdata.ExtraParams = new byte[1];
3137 objdata.MediaURL = new byte[0];
3138 objdata.NameValue = new byte[0];
3139 objdata.Text = new byte[0];
3140 objdata.TextColor = new byte[4];
3141 objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0);
3142 objdata.JointPivot = new LLVector3(0, 0, 0);
3143 objdata.Material = 3;
3144 objdata.TextureAnim = new byte[0];
3145 objdata.Sound = LLUUID.Zero;
3146 objdata.State = 0;
3147 objdata.Data = new byte[0];
3148
3149 objdata.ObjectData = new byte[60];
3150 objdata.ObjectData[46] = 128;
3151 objdata.ObjectData[47] = 63;
3152 }
3153
3154 /// <summary>
3155 ///
3156 /// </summary>
3157 /// <returns></returns>
3158 public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry)
3159 {
3160 ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock();
3161 // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i);
3162
3163 SetDefaultAvatarPacketValues(ref objdata);
3164 objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24);
3165 objdata.PathCurve = 16;
3166 objdata.ProfileCurve = 1;
3167 objdata.PathScaleX = 100;
3168 objdata.PathScaleY = 100;
3169 objdata.ParentID = 0;
3170 objdata.OwnerID = LLUUID.Zero;
3171 objdata.Scale = new LLVector3(1, 1, 1);
3172 objdata.PCode = (byte)PCode.Avatar;
3173 if (textureEntry != null)
3174 {
3175 objdata.TextureEntry = textureEntry;
3176 }
3177 LLVector3 pos = new LLVector3(objdata.ObjectData, 16);
3178 pos.X = 100f;
3179 objdata.ID = 8880000;
3180 objdata.NameValue = Helpers.StringToField("FirstName STRING RW SV Test \nLastName STRING RW SV User ");
3181 //LLVector3 pos2 = new LLVector3(100f, 100f, 23f);
3182 //objdata.FullID=user.AgentId;
3183 byte[] pb = pos.GetBytes();
3184 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
3185
3186 return objdata;
3187 }
3188
3189 /// <summary>
3190 ///
3191 /// </summary>
3192 /// <param name="objdata"></param>
3193 protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata)
3194 {
3195 objdata.PSBlock = new byte[0];
3196 objdata.ExtraParams = new byte[1];
3197 objdata.MediaURL = new byte[0];
3198 objdata.NameValue = new byte[0];
3199 objdata.Text = new byte[0];
3200 objdata.TextColor = new byte[4];
3201 objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0);
3202 objdata.JointPivot = new LLVector3(0, 0, 0);
3203 objdata.Material = 4;
3204 objdata.TextureAnim = new byte[0];
3205 objdata.Sound = LLUUID.Zero;
3206 LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005"));
3207 objdata.TextureEntry = ntex.ToBytes();
3208
3209 objdata.State = 0;
3210 objdata.Data = new byte[0];
3211
3212 objdata.ObjectData = new byte[76];
3213 objdata.ObjectData[15] = 128;
3214 objdata.ObjectData[16] = 63;
3215 objdata.ObjectData[56] = 128;
3216 objdata.ObjectData[61] = 102;
3217 objdata.ObjectData[62] = 40;
3218 objdata.ObjectData[63] = 61;
3219 objdata.ObjectData[64] = 189;
3220 }
3221
3222 public void SendNameReply(LLUUID profileId, string firstname, string lastname)
3223 {
3224 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
3225 // TODO: don't create new blocks if recycling an old packet
3226 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
3227 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
3228 packet.UUIDNameBlock[0].ID = profileId;
3229 packet.UUIDNameBlock[0].FirstName = Helpers.StringToField(firstname);
3230 packet.UUIDNameBlock[0].LastName = Helpers.StringToField(lastname);
3231
3232 OutPacket(packet, ThrottleOutPacketType.Task);
3233 }
3234
3235 #endregion
3236
3237 /// <summary>
3238 /// This is a different way of processing packets then ProcessInPacket
3239 /// </summary>
3240 protected virtual void RegisterLocalPacketHandlers()
3241 {
3242 AddLocalPacketHandler(PacketType.LogoutRequest, Logout);
3243 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect);
3244 AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached);
3245 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate);
3246 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest);
3247 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest);
3248 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
3249 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
3250 }
3251
3252 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
3253 {
3254 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
3255 // validate the agent owns the agentID and sessionID
3256 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && money.AgentData.SessionID == sender.SessionId)
3257 {
3258 handlerMoneyTransferRequest = OnMoneyTransferRequest;
3259 if (handlerMoneyTransferRequest != null)
3260 {
3261 handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID,
3262 money.MoneyData.Amount, money.MoneyData.TransactionType,
3263 Util.FieldToString(money.MoneyData.Description));
3264 }
3265
3266 return true;
3267 }
3268 else
3269 {
3270 return false;
3271 }
3272 }
3273
3274 private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack)
3275 {
3276 ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
3277 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == this.SessionId)
3278 {
3279 handlerParcelBuy = OnParcelBuy;
3280 if (handlerParcelBuy != null)
3281 {
3282 handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, parcel.Data.IsGroupOwned,
3283 parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, parcel.ParcelData.Price,
3284 false);
3285 }
3286 return true;
3287 }
3288 else
3289 {
3290 return false;
3291 }
3292 }
3293
3294 private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack)
3295 {
3296 UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack;
3297
3298 for (int i = 0; i < upack.UUIDNameBlock.Length; i++)
3299 {
3300 handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest;
3301 if (handlerUUIDGroupNameRequest != null)
3302 {
3303 handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this);
3304 }
3305 }
3306
3307 return true;
3308 }
3309
3310 public bool HandleObjectGroupRequest(IClientAPI sender, Packet Pack)
3311 {
3312
3313 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
3314 handlerObjectGroupRequest = OnObjectGroupRequest;
3315 if (handlerObjectGroupRequest != null)
3316 {
3317 for (int i = 0; i < ogpack.ObjectData.Length; i++)
3318 {
3319 handlerObjectGroupRequest(this, ogpack.AgentData.GroupID, ogpack.ObjectData[i].ObjectLocalID, LLUUID.Zero);
3320 }
3321 }
3322 return true;
3323 }
3324
3325 private bool HandleViewerEffect(IClientAPI sender, Packet Pack)
3326 {
3327 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
3328 handlerViewerEffect = OnViewerEffect;
3329 if (handlerViewerEffect != null)
3330 {
3331 int length = viewer.Effect.Length;
3332 List<ViewerEffectEventHandlerArg> args = new List<ViewerEffectEventHandlerArg>(length);
3333 for (int i = 0; i < length; i++)
3334 {
3335 //copy the effects block arguments into the event handler arg.
3336 ViewerEffectEventHandlerArg argument = new ViewerEffectEventHandlerArg();
3337 argument.AgentID = viewer.Effect[i].AgentID;
3338 argument.Color = viewer.Effect[i].Color;
3339 argument.Duration = viewer.Effect[i].Duration;
3340 argument.ID = viewer.Effect[i].ID;
3341 argument.Type = viewer.Effect[i].Type;
3342 argument.TypeData = viewer.Effect[i].TypeData;
3343 args.Add(argument);
3344 }
3345
3346 handlerViewerEffect(sender, args);
3347 }
3348
3349 return true;
3350 }
3351
3352 public void SendScriptQuestion(LLUUID taskID, string taskName, string ownerName, LLUUID itemID, int question)
3353 {
3354 ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
3355 scriptQuestion.Data = new ScriptQuestionPacket.DataBlock();
3356 // TODO: don't create new blocks if recycling an old packet
3357 scriptQuestion.Data.TaskID = taskID;
3358 scriptQuestion.Data.ItemID = itemID;
3359 scriptQuestion.Data.Questions = question;
3360 scriptQuestion.Data.ObjectName = Helpers.StringToField(taskName);
3361 scriptQuestion.Data.ObjectOwner = Helpers.StringToField(ownerName);
3362
3363 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
3364 }
3365
3366 private void InitDefaultAnimations()
3367 {
3368 }
3369
3370 public LLUUID GetDefaultAnimation(string name)
3371 {
3372 if (m_defaultAnimations.ContainsKey(name))
3373 return m_defaultAnimations[name];
3374 return LLUUID.Zero;
3375 }
3376
3377 /// <summary>
3378 /// Handler called when we receive a logout packet.
3379 /// </summary>
3380 /// <param name="client"></param>
3381 /// <param name="packet"></param>
3382 /// <returns></returns>
3383 protected virtual bool Logout(IClientAPI client, Packet packet)
3384 {
3385 return Logout(client);
3386 }
3387
3388 /// <summary>
3389 ///
3390 /// </summary>
3391 /// <param name="client">
3392 /// A <see cref="IClientAPI"/>
3393 /// </param>
3394 /// <returns>
3395 /// A <see cref="System.Boolean"/>
3396 /// </returns>
3397 protected virtual bool Logout(IClientAPI client)
3398 {
3399 m_log.Info("[CLIENT]: Got a logout request");
3400
3401 handlerLogout = OnLogout;
3402
3403 if (handlerLogout != null)
3404 {
3405 handlerLogout(client);
3406 }
3407
3408 return true;
3409 }
3410
3411 /// <summary>
3412 /// Send a response back to a client when it asks the asset server (via the region server) if it has
3413 /// its appearance texture cached.
3414 ///
3415 /// At the moment, we always reply that there is no cached texture.
3416 /// </summary>
3417 /// <param name="simclient"></param>
3418 /// <param name="packet"></param>
3419 /// <returns></returns>
3420 protected bool AgentTextureCached(IClientAPI simclient, Packet packet)
3421 {
3422 //Console.WriteLine("texture cached: " + packet.ToString());
3423 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
3424 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
3425 // TODO: don't create new blocks if recycling an old packet
3426 cachedresp.AgentData.AgentID = AgentId;
3427 cachedresp.AgentData.SessionID = m_sessionId;
3428 cachedresp.AgentData.SerialNum = m_cachedTextureSerial;
3429 m_cachedTextureSerial++;
3430 cachedresp.WearableData =
3431 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
3432
3433 for (int i = 0; i < cachedtex.WearableData.Length; i++)
3434 {
3435 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
3436 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
3437 cachedresp.WearableData[i].TextureID = LLUUID.Zero;
3438 cachedresp.WearableData[i].HostName = new byte[0];
3439 }
3440
3441 // Temporarily throw these packets on to the wind queue, so we can identify whether these
3442 // are somehow the source of the packet bloat.
3443 cachedresp.Header.Zerocoded = true;
3444 OutPacket(cachedresp, ThrottleOutPacketType.Wind);
3445 return true;
3446 }
3447
3448 protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet)
3449 {
3450 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
3451 // Console.WriteLine("new multi update packet " + multipleupdate.ToString());
3452 Scene tScene = (Scene)m_scene;
3453
3454 for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
3455 {
3456 MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i];
3457
3458 // Can't act on Null Data
3459 if (block.Data != null)
3460 {
3461 uint localId = block.ObjectLocalID;
3462 SceneObjectPart part = tScene.GetSceneObjectPart(localId);
3463
3464 if (part == null)
3465 {
3466 // It's a ghost! tell the client to delete it from view.
3467 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
3468 localId);
3469 }
3470 else
3471 {
3472 // LLUUID partId = part.UUID;
3473 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
3474 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
3475
3476 switch (block.Type)
3477 {
3478 case 1:
3479 LLVector3 pos1 = new LLVector3(block.Data, 0);
3480
3481 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
3482 if (handlerUpdatePrimSinglePosition != null)
3483 {
3484 // Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
3485 handlerUpdatePrimSinglePosition(localId, pos1, this);
3486 }
3487 break;
3488 case 2:
3489 LLQuaternion rot1 = new LLQuaternion(block.Data, 0, true);
3490
3491 handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
3492 if (handlerUpdatePrimSingleRotation != null)
3493 {
3494 //Console.WriteLine("new tab rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
3495 handlerUpdatePrimSingleRotation(localId, rot1, this);
3496 }
3497 break;
3498 case 3:
3499
3500 LLQuaternion rot2 = new LLQuaternion(block.Data, 12, true);
3501 handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
3502 if (handlerUpdatePrimSingleRotation != null)
3503 {
3504 //Console.WriteLine("new mouse rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
3505 handlerUpdatePrimSingleRotation(localId, rot2, this);
3506 }
3507 break;
3508 case 5:
3509
3510 LLVector3 scale1 = new LLVector3(block.Data, 12);
3511 LLVector3 pos11 = new LLVector3(block.Data, 0);
3512
3513 handlerUpdatePrimScale = OnUpdatePrimScale;
3514 if (handlerUpdatePrimScale != null)
3515 {
3516 // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
3517 handlerUpdatePrimScale(localId, scale1, this);
3518
3519 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
3520 if (handlerUpdatePrimSinglePosition != null)
3521 {
3522 handlerUpdatePrimSinglePosition(localId, pos11, this);
3523 }
3524 }
3525 break;
3526 case 9:
3527 LLVector3 pos2 = new LLVector3(block.Data, 0);
3528
3529 handlerUpdateVector = OnUpdatePrimGroupPosition;
3530
3531 if (handlerUpdateVector != null)
3532 {
3533
3534 handlerUpdateVector(localId, pos2, this);
3535 }
3536 break;
3537 case 10:
3538 LLQuaternion rot3 = new LLQuaternion(block.Data, 0, true);
3539
3540 handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
3541 if (handlerUpdatePrimRotation != null)
3542 {
3543 // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
3544 handlerUpdatePrimRotation(localId, rot3, this);
3545 }
3546 break;
3547 case 11:
3548 LLVector3 pos3 = new LLVector3(block.Data, 0);
3549 LLQuaternion rot4 = new LLQuaternion(block.Data, 12, true);
3550
3551 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
3552 if (handlerUpdatePrimGroupRotation != null)
3553 {
3554 //Console.WriteLine("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
3555 // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
3556 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
3557 }
3558 break;
3559 case 13:
3560 LLVector3 scale2 = new LLVector3(block.Data, 12);
3561 LLVector3 pos4 = new LLVector3(block.Data, 0);
3562
3563 handlerUpdatePrimScale = OnUpdatePrimScale;
3564 if (handlerUpdatePrimScale != null)
3565 {
3566 //Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
3567 handlerUpdatePrimScale(localId, scale2, this);
3568
3569 // Change the position based on scale (for bug number 246)
3570 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
3571 // Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
3572 if (handlerUpdatePrimSinglePosition != null)
3573 {
3574 handlerUpdatePrimSinglePosition(localId, pos4, this);
3575 }
3576 }
3577 break;
3578 case 29:
3579 LLVector3 scale5 = new LLVector3(block.Data, 12);
3580 LLVector3 pos5 = new LLVector3(block.Data, 0);
3581
3582 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
3583 if (handlerUpdatePrimGroupScale != null)
3584 {
3585 // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
3586 handlerUpdatePrimGroupScale(localId, scale5, this);
3587 handlerUpdateVector = OnUpdatePrimGroupPosition;
3588
3589 if (handlerUpdateVector != null)
3590 {
3591 handlerUpdateVector(localId, pos5, this);
3592 }
3593 }
3594 break;
3595 case 21:
3596 LLVector3 scale6 = new LLVector3(block.Data, 12);
3597 LLVector3 pos6 = new LLVector3(block.Data, 0);
3598
3599 handlerUpdatePrimScale = OnUpdatePrimScale;
3600 if (handlerUpdatePrimScale != null)
3601 {
3602 // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
3603 handlerUpdatePrimScale(localId, scale6, this);
3604 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
3605 if (handlerUpdatePrimSinglePosition != null)
3606 {
3607 handlerUpdatePrimSinglePosition(localId, pos6, this);
3608 }
3609 }
3610 break;
3611 }
3612 }
3613 }
3614 }
3615 return true;
3616 }
3617
3618 public void RequestMapLayer()
3619 {
3620 //should be getting the map layer from the grid server
3621 //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area)
3622 MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply);
3623 // TODO: don't create new blocks if recycling an old packet
3624 mapReply.AgentData.AgentID = AgentId;
3625 mapReply.AgentData.Flags = 0;
3626 mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1];
3627 mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock();
3628 mapReply.LayerData[0].Bottom = 0;
3629 mapReply.LayerData[0].Left = 0;
3630 mapReply.LayerData[0].Top = 30000;
3631 mapReply.LayerData[0].Right = 30000;
3632 mapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-1111-9999-000000000006");
3633 mapReply.Header.Zerocoded = true;
3634 OutPacket(mapReply, ThrottleOutPacketType.Land);
3635 }
3636
3637 public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY)
3638 {
3639 /*
3640 IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY);
3641 MapBlockReplyPacket mbReply = new MapBlockReplyPacket();
3642 mbReply.AgentData.AgentId = this.AgentId;
3643 int len;
3644 if (simMapProfiles == null)
3645 len = 0;
3646 else
3647 len = simMapProfiles.Count;
3648
3649 mbReply.Data = new MapBlockReplyPacket.DataBlock[len];
3650 int iii;
3651 for (iii = 0; iii < len; iii++)
3652 {
3653 Hashtable mp = (Hashtable)simMapProfiles[iii];
3654 mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock();
3655 mbReply.Data[iii].Name = System.Text.Encoding.UTF8.GetBytes((string)mp["name"]);
3656 mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]);
3657 mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]);
3658 mbReply.Data[iii].MapImageID = new LLUUID((string)mp["map-image-id"]);
3659 mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]);
3660 mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]);
3661 mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]);
3662 mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]);
3663 }
3664 this.OutPacket(mbReply, ThrottleOutPacketType.Land);
3665 */
3666 }
3667
3668 /// <summary>
3669 /// returns a byte array of the client set throttles Gets multiplied by the multiplier
3670 ///
3671 /// </summary>
3672 /// <param name="multiplier">non 1 multiplier for subdividing the throttles between individual regions</param>
3673 /// <returns></returns>
3674 public byte[] GetThrottlesPacked(float multiplier)
3675 {
3676 return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier);
3677 }
3678 /// <summary>
3679 /// sets the throttles from values supplied by the client
3680 /// </summary>
3681 /// <param name="throttles"></param>
3682 public void SetChildAgentThrottle(byte[] throttles)
3683 {
3684 m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles);
3685 }
3686
3687 // Previously ClientView.m_packetQueue
3688
3689 /// <summary>
3690 /// Helper routine to prepare the packet for sending to UDP client
3691 /// This converts it to bytes and puts it on the outgoing buffer
3692 /// </summary>
3693 /// <param name="Pack"></param>
3694 protected virtual void ProcessOutPacket(Packet Pack)
3695 {
3696 // Keep track of when this packet was sent out
3697 Pack.TickCount = System.Environment.TickCount;
3698
3699 // Actually make the byte array and send it
3700 try
3701 {
3702 byte[] sendbuffer = Pack.ToBytes();
3703 PacketPool.Instance.ReturnPacket(Pack);
3704
3705 if (Pack.Header.Zerocoded)
3706 {
3707 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
3708 m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode);
3709 }
3710 else
3711 {
3712 //Need some extra space in case we need to add proxy information to the message later
3713 Buffer.BlockCopy(sendbuffer, 0, ZeroOutBuffer, 0, sendbuffer.Length);
3714 m_networkServer.SendPacketTo(ZeroOutBuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode);
3715 }
3716 }
3717 catch (Exception e)
3718 {
3719 m_log.Warn("[client]: " +
3720 "ClientView.m_packetQueue.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " +
3721 m_userEndPoint.ToString() + " - killing thread");
3722 m_log.Error(e.ToString());
3723 Close(true);
3724 }
3725 }
3726
3727 /// <summary>
3728 /// method gets called when a new packet has arrived from the UDP server. This happens after it's been decoded into a libsl object
3729 /// </summary>
3730 /// <param name="NewPack"></param>
3731 public virtual void InPacket(Packet NewPack)
3732 {
3733 m_PacketHandler.InPacket(NewPack);
3734 }
3735
3736 /// <summary>
3737 /// The dreaded OutPacket. This should only be called from within
3738 /// the ClientStack itself right now
3739 /// This is the entry point for simulator packets to go out to
3740 /// the client.
3741 /// </summary>
3742 /// <param name="NewPack"></param>
3743 /// <param name="throttlePacketType">Corresponds to the type of data that is going out. Enum</param>
3744 public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType)
3745 {
3746 m_PacketHandler.OutPacket(NewPack, throttlePacketType);
3747 }
3748
3749 public bool AddMoney(int debit)
3750 {
3751 if (m_moneyBalance + debit >= 0)
3752 {
3753 m_moneyBalance += debit;
3754 SendMoneyBalance(LLUUID.Zero, true, Helpers.StringToField("Poof Poof!"), m_moneyBalance);
3755 return true;
3756 }
3757 else
3758 {
3759 return false;
3760 }
3761 }
3762
3763 /// <summary>
3764 /// Breaks down the genericMessagePacket into specific events
3765 /// </summary>
3766 /// <param name="gmMethod"></param>
3767 /// <param name="gmInvoice"></param>
3768 /// <param name="gmParams"></param>
3769 public void DecipherGenericMessage(string gmMethod, LLUUID gmInvoice, GenericMessagePacket.ParamListBlock[] gmParams)
3770 {
3771 switch (gmMethod)
3772 {
3773 case "autopilot":
3774 float locx = 0f;
3775 float locy = 0f;
3776 float locz = 0f;
3777 uint regionX = 0;
3778 uint regionY = 0;
3779 try
3780 {
3781 Helpers.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
3782 locx = Convert.ToSingle(Helpers.FieldToUTF8String(gmParams[0].Parameter)) - (float)regionX;
3783 locy = Convert.ToSingle(Helpers.FieldToUTF8String(gmParams[1].Parameter)) - (float)regionY;
3784 locz = Convert.ToSingle(Helpers.FieldToUTF8String(gmParams[2].Parameter));
3785 }
3786 catch (InvalidCastException)
3787 {
3788 m_log.Error("[CLIENT]: Invalid autopilot request");
3789 return;
3790 }
3791
3792 handlerAutoPilotGo = OnAutoPilotGo;
3793 if (handlerAutoPilotGo != null)
3794 {
3795 handlerAutoPilotGo(0, new LLVector3(locx, locy, locz), this);
3796 }
3797 m_log.InfoFormat("[CLIENT]: Client Requests autopilot to position <{0},{1},{2}>", locx, locy, locz);
3798
3799
3800 break;
3801 default:
3802 m_log.Debug("[CLIENT]: Unknown Generic Message, Method: " + gmMethod + ". Invoice: " + gmInvoice.ToString() + ". Dumping Params:");
3803 for (int hi = 0; hi < gmParams.Length; hi++)
3804 {
3805 System.Console.WriteLine(gmParams[hi].ToString());
3806 }
3807 //gmpack.MethodData.
3808 break;
3809
3810 }
3811 }
3812
3813 /// <summary>
3814 /// Entryway from the client to the simulator
3815 /// all UDP packets from the client will end up here
3816 /// </summary>
3817 /// <param name="Pack">libsecondlife.packet</param>
3818 public void ProcessInPacket(Packet Pack)
3819 {
3820 // check if we've got a local packet handler for this packet.type. See RegisterLocalPacketHandlers()
3821 if (ProcessPacketMethod(Pack))
3822 {
3823 //there is a handler registered that handled this packet type
3824 return;
3825 }
3826 else
3827 {
3828 // Main packet processing conditional
3829 switch (Pack.Type)
3830 {
3831 #region Scene/Avatar
3832
3833 case PacketType.GenericMessage:
3834 GenericMessagePacket gmpack = (GenericMessagePacket)Pack;
3835
3836 DecipherGenericMessage(Helpers.FieldToUTF8String(gmpack.MethodData.Method), gmpack.MethodData.Invoice, gmpack.ParamList);
3837
3838 break;
3839 case PacketType.AvatarPropertiesRequest:
3840 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
3841
3842 handlerRequestAvatarProperties = OnRequestAvatarProperties;
3843 if (handlerRequestAvatarProperties != null)
3844 {
3845 handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID);
3846 }
3847
3848 break;
3849 case PacketType.ChatFromViewer:
3850 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
3851
3852 string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname;
3853 byte[] message = inchatpack.ChatData.Message;
3854 byte type = inchatpack.ChatData.Type;
3855 LLVector3 fromPos = new LLVector3(); // ClientAvatar.Pos;
3856 // LLUUID fromAgentID = AgentId;
3857
3858 int channel = inchatpack.ChatData.Channel;
3859
3860 if (OnChatFromViewer != null)
3861 {
3862 OSChatMessage args = new OSChatMessage();
3863 args.Channel = channel;
3864 args.From = fromName;
3865 args.Message = Helpers.FieldToUTF8String(message);
3866 args.Type = (ChatTypeEnum)type;
3867 args.Position = fromPos;
3868
3869 args.Scene = Scene;
3870 args.Sender = this;
3871
3872 handlerChatFromViewer = OnChatFromViewer;
3873 if (handlerChatFromViewer != null)
3874 handlerChatFromViewer(this, args);
3875 }
3876 break;
3877 case PacketType.AvatarPropertiesUpdate:
3878 AvatarPropertiesUpdatePacket Packet = (AvatarPropertiesUpdatePacket)Pack;
3879
3880 handlerUpdateAvatarProperties = OnUpdateAvatarProperties;
3881 if (handlerUpdateAvatarProperties != null)
3882 {
3883 AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = Packet.PropertiesData;
3884 UserProfileData UserProfile = new UserProfileData();
3885 UserProfile.ID = AgentId;
3886 UserProfile.AboutText = Helpers.FieldToUTF8String(Properties.AboutText);
3887 UserProfile.FirstLifeAboutText = Helpers.FieldToUTF8String(Properties.FLAboutText);
3888 UserProfile.FirstLifeImage = Properties.FLImageID;
3889 UserProfile.Image = Properties.ImageID;
3890
3891 handlerUpdateAvatarProperties(this, UserProfile);
3892 }
3893 break;
3894
3895 case PacketType.ScriptDialogReply:
3896 ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack;
3897 int ch = rdialog.Data.ChatChannel;
3898 byte[] msg = rdialog.Data.ButtonLabel;
3899 if (OnChatFromViewer != null)
3900 {
3901 OSChatMessage args = new OSChatMessage();
3902 args.Channel = ch;
3903 args.From = String.Empty;
3904 args.Message = Helpers.FieldToUTF8String(msg);
3905 args.Type = ChatTypeEnum.Shout;
3906 args.Position = new LLVector3();
3907 args.Scene = Scene;
3908 args.Sender = this;
3909 handlerChatFromViewer2 = OnChatFromViewer;
3910 if (handlerChatFromViewer2 != null)
3911 handlerChatFromViewer2(this, args);
3912 }
3913
3914 break;
3915 case PacketType.ImprovedInstantMessage:
3916 ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack;
3917 string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName);
3918 string IMmessage = Helpers.FieldToUTF8String(msgpack.MessageBlock.Message);
3919 handlerInstantMessage = OnInstantMessage;
3920
3921 if (handlerInstantMessage != null)
3922 {
3923 handlerInstantMessage(this, msgpack.AgentData.AgentID, msgpack.AgentData.SessionID,
3924 msgpack.MessageBlock.ToAgentID, msgpack.MessageBlock.ID,
3925 msgpack.MessageBlock.Timestamp, IMfromName, IMmessage,
3926 msgpack.MessageBlock.Dialog, msgpack.MessageBlock.FromGroup,
3927 msgpack.MessageBlock.Offline, msgpack.MessageBlock.ParentEstateID,
3928 msgpack.MessageBlock.Position, msgpack.MessageBlock.RegionID,
3929 msgpack.MessageBlock.BinaryBucket);
3930 }
3931 break;
3932
3933 case PacketType.AcceptFriendship:
3934 AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack;
3935
3936 // My guess is this is the folder to stick the calling card into
3937 List<LLUUID> callingCardFolders = new List<LLUUID>();
3938
3939 LLUUID agentID = afriendpack.AgentData.AgentID;
3940 LLUUID transactionID = afriendpack.TransactionBlock.TransactionID;
3941
3942 for (int fi = 0; fi < afriendpack.FolderData.Length; fi++)
3943 {
3944 callingCardFolders.Add(afriendpack.FolderData[fi].FolderID);
3945 }
3946
3947 handlerApproveFriendRequest = OnApproveFriendRequest;
3948 if (handlerApproveFriendRequest != null)
3949 {
3950 handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders);
3951 }
3952 break;
3953 case PacketType.TerminateFriendship:
3954 TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack;
3955 LLUUID listOwnerAgentID = tfriendpack.AgentData.AgentID;
3956 LLUUID exFriendID = tfriendpack.ExBlock.OtherID;
3957
3958 handlerTerminateFriendship = OnTerminateFriendship;
3959 if (handlerTerminateFriendship != null)
3960 {
3961 handlerTerminateFriendship(this, listOwnerAgentID, exFriendID);
3962 }
3963 break;
3964 case PacketType.RezObject:
3965 RezObjectPacket rezPacket = (RezObjectPacket)Pack;
3966
3967 handlerRezObject = OnRezObject;
3968 if (handlerRezObject != null)
3969 {
3970 //rezPacket.RezData.BypassRaycast;
3971 //rezPacket.RezData.RayEnd;
3972 //rezPacket.RezData.RayEndIsIntersection;
3973 //rezPacket.RezData.RayStart;
3974 //rezPacket.RezData.RayTargetID;
3975 //rezPacket.RezData.RemoveItem;
3976 //rezPacket.RezData.RezSelected;
3977 //rezPacket.RezData.FromTaskID;
3978 //m_log.Info("[REZData]: " + rezPacket.ToString());
3979
3980 handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd,
3981 rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID,
3982 rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection,
3983 rezPacket.RezData.EveryoneMask, rezPacket.RezData.GroupMask,
3984 rezPacket.RezData.NextOwnerMask, rezPacket.RezData.ItemFlags,
3985 rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem,
3986 rezPacket.RezData.FromTaskID);
3987 }
3988 break;
3989 case PacketType.DeRezObject:
3990 handlerDeRezObject = OnDeRezObject;
3991 if (handlerDeRezObject != null)
3992 {
3993 handlerDeRezObject(Pack, this);
3994 }
3995 break;
3996 case PacketType.ModifyLand:
3997 ModifyLandPacket modify = (ModifyLandPacket)Pack;
3998 //m_log.Info("[LAND]: LAND:" + modify.ToString());
3999 if (modify.ParcelData.Length > 0)
4000 {
4001 if (OnModifyTerrain != null)
4002 {
4003 for (int i = 0; i < modify.ParcelData.Length; i++)
4004 {
4005 handlerModifyTerrain = OnModifyTerrain;
4006 if (handlerModifyTerrain != null)
4007 {
4008 handlerModifyTerrain(modify.ModifyBlock.Height, modify.ModifyBlock.Seconds,
4009 modify.ModifyBlock.BrushSize,
4010 modify.ModifyBlock.Action, modify.ParcelData[i].North,
4011 modify.ParcelData[i].West, modify.ParcelData[i].South,
4012 modify.ParcelData[i].East, this);
4013 }
4014 }
4015 }
4016 }
4017
4018 break;
4019 case PacketType.RegionHandshakeReply:
4020
4021 handlerRegionHandShakeReply = OnRegionHandShakeReply;
4022 if (handlerRegionHandShakeReply != null)
4023 {
4024 handlerRegionHandShakeReply(this);
4025 }
4026
4027 break;
4028 case PacketType.AgentWearablesRequest:
4029 handlerRequestWearables = OnRequestWearables;
4030
4031 if (handlerRequestWearables != null)
4032 {
4033 handlerRequestWearables();
4034 }
4035
4036 handlerRequestAvatarsData = OnRequestAvatarsData;
4037
4038 if (handlerRequestAvatarsData != null)
4039 {
4040 handlerRequestAvatarsData(this);
4041 }
4042
4043 break;
4044 case PacketType.AgentSetAppearance:
4045 AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
4046
4047 handlerSetAppearance = OnSetAppearance;
4048 if (handlerSetAppearance != null)
4049 {
4050 // Temporarily protect ourselves from the mantis #951 failure.
4051 // However, we could do this for several other handlers where a failure isn't terminal
4052 // for the client session anyway, in order to protect ourselves against bad code in plugins
4053 try
4054 {
4055 List<byte> visualparams = new List<byte>();
4056 foreach (AgentSetAppearancePacket.VisualParamBlock x in appear.VisualParam)
4057 {
4058 visualparams.Add(x.ParamValue);
4059 }
4060
4061 handlerSetAppearance(appear.ObjectData.TextureEntry, visualparams);
4062 }
4063 catch (Exception e)
4064 {
4065 m_log.ErrorFormat(
4066 "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}",
4067 e);
4068 }
4069 }
4070
4071 break;
4072 case PacketType.AgentIsNowWearing:
4073 if (OnAvatarNowWearing != null)
4074 {
4075 AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack;
4076 AvatarWearingArgs wearingArgs = new AvatarWearingArgs();
4077 for (int i = 0; i < nowWearing.WearableData.Length; i++)
4078 {
4079 AvatarWearingArgs.Wearable wearable =
4080 new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID,
4081 nowWearing.WearableData[i].WearableType);
4082 wearingArgs.NowWearing.Add(wearable);
4083 }
4084
4085 handlerAvatarNowWearing = OnAvatarNowWearing;
4086 if (handlerAvatarNowWearing != null)
4087 {
4088 handlerAvatarNowWearing(this, wearingArgs);
4089 }
4090 }
4091 break;
4092 case PacketType.RezSingleAttachmentFromInv:
4093 handlerRezSingleAttachment = OnRezSingleAttachmentFromInv;
4094 if (handlerRezSingleAttachment != null)
4095 {
4096 RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
4097 handlerRezSingleAttachment(this, rez.ObjectData.ItemID,
4098 rez.ObjectData.AttachmentPt, rez.ObjectData.ItemFlags, rez.ObjectData.NextOwnerMask);
4099 }
4100
4101 break;
4102 case PacketType.DetachAttachmentIntoInv:
4103 handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv;
4104 if (handlerDetachAttachmentIntoInv != null)
4105 {
4106 DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack;
4107
4108 LLUUID itemID = detachtoInv.ObjectData.ItemID;
4109 // LLUUID ATTACH_agentID = detachtoInv.ObjectData.AgentID;
4110
4111 handlerDetachAttachmentIntoInv(itemID, this);
4112 }
4113 break;
4114 case PacketType.ObjectAttach:
4115 if (OnObjectAttach != null)
4116 {
4117 ObjectAttachPacket att = (ObjectAttachPacket)Pack;
4118
4119 handlerObjectAttach = OnObjectAttach;
4120
4121 if (handlerObjectAttach != null)
4122 {
4123 if (att.ObjectData.Length > 0)
4124 {
4125 handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation);
4126 }
4127 }
4128 }
4129
4130 break;
4131 case PacketType.ObjectDetach:
4132
4133 ObjectDetachPacket dett = (ObjectDetachPacket)Pack;
4134 for (int j = 0; j < dett.ObjectData.Length; j++)
4135 {
4136 uint obj = dett.ObjectData[j].ObjectLocalID;
4137 handlerObjectDetach = OnObjectDetach;
4138 if (handlerObjectDetach != null)
4139 {
4140 handlerObjectDetach(obj, this);
4141 }
4142
4143 }
4144
4145 break;
4146 case PacketType.SetAlwaysRun:
4147 SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack;
4148
4149 handlerSetAlwaysRun = OnSetAlwaysRun;
4150 if (handlerSetAlwaysRun != null)
4151 handlerSetAlwaysRun(this, run.AgentData.AlwaysRun);
4152
4153 break;
4154 case PacketType.CompleteAgentMovement:
4155 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
4156 if (handlerCompleteMovementToRegion != null)
4157 {
4158 handlerCompleteMovementToRegion();
4159 }
4160 handlerCompleteMovementToRegion = null;
4161
4162 break;
4163 case PacketType.AgentUpdate:
4164 if (OnAgentUpdate != null)
4165 {
4166 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
4167
4168 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
4169 AgentUpdateArgs arg = new AgentUpdateArgs();
4170 arg.AgentID = x.AgentID;
4171 arg.BodyRotation = x.BodyRotation;
4172 arg.CameraAtAxis = x.CameraAtAxis;
4173 arg.CameraCenter = x.CameraCenter;
4174 arg.CameraLeftAxis = x.CameraLeftAxis;
4175 arg.CameraUpAxis = x.CameraUpAxis;
4176 arg.ControlFlags = x.ControlFlags;
4177 arg.Far = x.Far;
4178 arg.Flags = x.Flags;
4179 arg.HeadRotation = x.HeadRotation;
4180 arg.SessionID = x.SessionID;
4181 arg.State = x.State;
4182
4183 handlerAgentUpdate = OnAgentUpdate;
4184 if (handlerAgentUpdate != null)
4185 OnAgentUpdate(this, arg);
4186
4187 handlerAgentUpdate = null;
4188 //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa);
4189 }
4190 break;
4191 case PacketType.AgentAnimation:
4192 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
4193
4194 handlerStartAnim = null;
4195 handlerStopAnim = null;
4196
4197 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
4198 {
4199 if (AgentAni.AnimationList[i].StartAnim)
4200 {
4201 handlerStartAnim = OnStartAnim;
4202 if (handlerStartAnim != null)
4203 {
4204 handlerStartAnim(this, AgentAni.AnimationList[i].AnimID);
4205 }
4206 }
4207 else
4208 {
4209 handlerStopAnim = OnStopAnim;
4210 if (handlerStopAnim != null)
4211 {
4212 handlerStopAnim(this, AgentAni.AnimationList[i].AnimID);
4213 }
4214 }
4215 }
4216 break;
4217 case PacketType.AgentRequestSit:
4218 if (OnAgentRequestSit != null)
4219 {
4220 AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack;
4221
4222 handlerAgentRequestSit = OnAgentRequestSit;
4223 if (handlerAgentRequestSit != null)
4224 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
4225 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
4226 }
4227 break;
4228 case PacketType.AgentSit:
4229 if (OnAgentSit != null)
4230 {
4231 AgentSitPacket agentSit = (AgentSitPacket)Pack;
4232
4233 handlerAgentSit = OnAgentSit;
4234 if (handlerAgentSit != null)
4235 {
4236 OnAgentSit(this, agentSit.AgentData.AgentID);
4237 }
4238 }
4239 break;
4240 case PacketType.AvatarPickerRequest:
4241 AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack;
4242 AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData;
4243 AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data;
4244 //Console.WriteLine("Agent Sends:" + Helpers.FieldToUTF8String(querydata.Name));
4245
4246 handlerAvatarPickerRequest = OnAvatarPickerRequest;
4247 if (handlerAvatarPickerRequest != null)
4248 {
4249 handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID,
4250 Helpers.FieldToUTF8String(querydata.Name));
4251 }
4252 break;
4253 case PacketType.AgentDataUpdateRequest:
4254 AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack;
4255
4256 handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest;
4257
4258 if (handlerAgentDataUpdateRequest != null)
4259 {
4260 handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID);
4261 }
4262
4263 break;
4264 case PacketType.UserInfoRequest:
4265 UserInfoRequestPacket avUserInfoRequestPacket = (UserInfoRequestPacket)Pack;
4266
4267 handlerUserInfoRequest = OnUserInfoRequest;
4268 if (handlerUserInfoRequest != null)
4269 {
4270 handlerUserInfoRequest(this, avUserInfoRequestPacket.AgentData.AgentID, avUserInfoRequestPacket.AgentData.SessionID);
4271 }
4272 break;
4273
4274 case PacketType.SetStartLocationRequest:
4275 SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
4276
4277 if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId)
4278 {
4279 handlerSetStartLocationRequest = OnSetStartLocationRequest;
4280 if (handlerSetStartLocationRequest != null)
4281 {
4282 handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos,
4283 avSetStartLocationRequestPacket.StartLocationData.LocationLookAt,
4284 avSetStartLocationRequestPacket.StartLocationData.LocationID);
4285 }
4286 }
4287 break;
4288
4289 case PacketType.AgentThrottle:
4290 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
4291 m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles);
4292 break;
4293
4294 case PacketType.AgentPause:
4295 m_probesWithNoIngressPackets = 0;
4296 m_clientBlocked = true;
4297 break;
4298
4299 case PacketType.AgentResume:
4300 m_probesWithNoIngressPackets = 0;
4301 m_clientBlocked = false;
4302 SendStartPingCheck(0);
4303
4304 break;
4305
4306 case PacketType.ForceScriptControlRelease:
4307 handlerForceReleaseControls = OnForceReleaseControls;
4308 if (handlerForceReleaseControls != null)
4309 {
4310 handlerForceReleaseControls(this, AgentId);
4311 }
4312 break;
4313
4314 #endregion
4315
4316 #region Objects/m_sceneObjects
4317
4318 case PacketType.ObjectLink:
4319 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
4320 uint parentprimid = 0;
4321 List<uint> childrenprims = new List<uint>();
4322 if (link.ObjectData.Length > 1)
4323 {
4324 parentprimid = link.ObjectData[0].ObjectLocalID;
4325
4326 for (int i = 1; i < link.ObjectData.Length; i++)
4327 {
4328 childrenprims.Add(link.ObjectData[i].ObjectLocalID);
4329 }
4330 }
4331 handlerLinkObjects = OnLinkObjects;
4332 if (handlerLinkObjects != null)
4333 {
4334 handlerLinkObjects(this, parentprimid, childrenprims);
4335 }
4336 break;
4337 case PacketType.ObjectDelink:
4338 ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack;
4339
4340 // It appears the prim at index 0 is not always the root prim (for
4341 // instance, when one prim of a link set has been edited independently
4342 // of the others). Therefore, we'll pass all the ids onto the delink
4343 // method for it to decide which is the root.
4344 List<uint> prims = new List<uint>();
4345 for (int i = 0; i < delink.ObjectData.Length; i++)
4346 {
4347 prims.Add(delink.ObjectData[i].ObjectLocalID);
4348 }
4349 handlerDelinkObjects = OnDelinkObjects;
4350 if (handlerDelinkObjects != null)
4351 {
4352 handlerDelinkObjects(prims);
4353 }
4354
4355 break;
4356 case PacketType.ObjectAdd:
4357 if (OnAddPrim != null)
4358 {
4359 ObjectAddPacket addPacket = (ObjectAddPacket)Pack;
4360 PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket);
4361 // m_log.Info("[REZData]: " + addPacket.ToString());
4362 //BypassRaycast: 1
4363 //RayStart: <69.79469, 158.2652, 98.40343>
4364 //RayEnd: <61.97724, 141.995, 92.58341>
4365 //RayTargetID: 00000000-0000-0000-0000-000000000000
4366
4367 //Check to see if adding the prim is allowed; useful for any module wanting to restrict the
4368 //object from rezing initially
4369
4370 handlerAddPrim = OnAddPrim;
4371 if (handlerAddPrim != null)
4372 handlerAddPrim(AgentId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection);
4373 }
4374 break;
4375 case PacketType.ObjectShape:
4376 ObjectShapePacket shapePacket = (ObjectShapePacket)Pack;
4377 handlerUpdatePrimShape = null;
4378 for (int i = 0; i < shapePacket.ObjectData.Length; i++)
4379 {
4380 handlerUpdatePrimShape = OnUpdatePrimShape;
4381 if (handlerUpdatePrimShape != null)
4382 {
4383 UpdateShapeArgs shapeData = new UpdateShapeArgs();
4384 shapeData.ObjectLocalID = shapePacket.ObjectData[i].ObjectLocalID;
4385 shapeData.PathBegin = shapePacket.ObjectData[i].PathBegin;
4386 shapeData.PathCurve = shapePacket.ObjectData[i].PathCurve;
4387 shapeData.PathEnd = shapePacket.ObjectData[i].PathEnd;
4388 shapeData.PathRadiusOffset = shapePacket.ObjectData[i].PathRadiusOffset;
4389 shapeData.PathRevolutions = shapePacket.ObjectData[i].PathRevolutions;
4390 shapeData.PathScaleX = shapePacket.ObjectData[i].PathScaleX;
4391 shapeData.PathScaleY = shapePacket.ObjectData[i].PathScaleY;
4392 shapeData.PathShearX = shapePacket.ObjectData[i].PathShearX;
4393 shapeData.PathShearY = shapePacket.ObjectData[i].PathShearY;
4394 shapeData.PathSkew = shapePacket.ObjectData[i].PathSkew;
4395 shapeData.PathTaperX = shapePacket.ObjectData[i].PathTaperX;
4396 shapeData.PathTaperY = shapePacket.ObjectData[i].PathTaperY;
4397 shapeData.PathTwist = shapePacket.ObjectData[i].PathTwist;
4398 shapeData.PathTwistBegin = shapePacket.ObjectData[i].PathTwistBegin;
4399 shapeData.ProfileBegin = shapePacket.ObjectData[i].ProfileBegin;
4400 shapeData.ProfileCurve = shapePacket.ObjectData[i].ProfileCurve;
4401 shapeData.ProfileEnd = shapePacket.ObjectData[i].ProfileEnd;
4402 shapeData.ProfileHollow = shapePacket.ObjectData[i].ProfileHollow;
4403
4404 handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID,
4405 shapeData);
4406 }
4407 }
4408 break;
4409 case PacketType.ObjectExtraParams:
4410 ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack;
4411
4412 handlerUpdateExtraParams = OnUpdateExtraParams;
4413 if (handlerUpdateExtraParams != null)
4414 {
4415 handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[0].ObjectLocalID,
4416 extraPar.ObjectData[0].ParamType,
4417 extraPar.ObjectData[0].ParamInUse, extraPar.ObjectData[0].ParamData);
4418 }
4419 break;
4420 case PacketType.ObjectDuplicate:
4421 ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack;
4422 ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData;
4423
4424 handlerObjectDuplicate = null;
4425
4426 for (int i = 0; i < dupe.ObjectData.Length; i++)
4427 {
4428 handlerObjectDuplicate = OnObjectDuplicate;
4429 if (handlerObjectDuplicate != null)
4430 {
4431 handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset,
4432 dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID,
4433 AgentandGroupData.GroupID);
4434 }
4435 }
4436
4437 break;
4438
4439 case PacketType.ObjectSelect:
4440 ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
4441
4442 handlerObjectSelect = null;
4443
4444 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
4445 {
4446 handlerObjectSelect = OnObjectSelect;
4447 if (handlerObjectSelect != null)
4448 {
4449 handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this);
4450 }
4451 }
4452 break;
4453 case PacketType.ObjectDeselect:
4454 ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack;
4455
4456 handlerObjectDeselect = null;
4457
4458 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
4459 {
4460 handlerObjectDeselect = OnObjectDeselect;
4461 if (handlerObjectDeselect != null)
4462 {
4463 OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this);
4464 }
4465 }
4466 break;
4467 case PacketType.ObjectPosition:
4468 // DEPRECATED: but till libsecondlife removes it, people will use it
4469 ObjectPositionPacket position = (ObjectPositionPacket)Pack;
4470
4471 for (int i = 0; i < position.ObjectData.Length; i++)
4472 {
4473 handlerUpdateVector = OnUpdatePrimGroupPosition;
4474 if (handlerUpdateVector != null)
4475 handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this);
4476 }
4477
4478 break;
4479 case PacketType.ObjectScale:
4480 // DEPRECATED: but till libsecondlife removes it, people will use it
4481 ObjectScalePacket scale = (ObjectScalePacket)Pack;
4482
4483 for (int i = 0; i < scale.ObjectData.Length; i++)
4484 {
4485 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
4486 if (handlerUpdatePrimGroupScale != null)
4487 handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this);
4488 }
4489
4490 break;
4491 case PacketType.ObjectRotation:
4492 // DEPRECATED: but till libsecondlife removes it, people will use it
4493 ObjectRotationPacket rotation = (ObjectRotationPacket)Pack;
4494
4495 for (int i = 0; i < rotation.ObjectData.Length; i++)
4496 {
4497 handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
4498 if (handlerUpdatePrimRotation != null)
4499 handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this);
4500 }
4501
4502 break;
4503 case PacketType.ObjectFlagUpdate:
4504 ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
4505
4506 handlerUpdatePrimFlags = OnUpdatePrimFlags;
4507
4508 if (handlerUpdatePrimFlags != null)
4509 {
4510 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, Pack, this);
4511 }
4512 break;
4513 case PacketType.ObjectImage:
4514 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
4515
4516 handlerUpdatePrimTexture = null;
4517 for (int i = 0; i < imagePack.ObjectData.Length; i++)
4518 {
4519 handlerUpdatePrimTexture = OnUpdatePrimTexture;
4520 if (handlerUpdatePrimTexture != null)
4521 {
4522 handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID,
4523 imagePack.ObjectData[i].TextureEntry, this);
4524 }
4525 }
4526 break;
4527 case PacketType.ObjectGrab:
4528 ObjectGrabPacket grab = (ObjectGrabPacket)Pack;
4529
4530 handlerGrabObject = OnGrabObject;
4531
4532 if (handlerGrabObject != null)
4533 {
4534 handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this);
4535 }
4536 break;
4537 case PacketType.ObjectGrabUpdate:
4538 ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack;
4539
4540 handlerGrabUpdate = OnGrabUpdate;
4541
4542 if (handlerGrabUpdate != null)
4543 {
4544 handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial,
4545 grabUpdate.ObjectData.GrabPosition, this);
4546 }
4547 break;
4548 case PacketType.ObjectDeGrab:
4549 ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack;
4550
4551 handlerDeGrabObject = OnDeGrabObject;
4552 if (handlerDeGrabObject != null)
4553 {
4554 handlerDeGrabObject(deGrab.ObjectData.LocalID, this);
4555 }
4556 break;
4557 case PacketType.ObjectDescription:
4558 ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack;
4559
4560 handlerObjectDescription = null;
4561
4562 for (int i = 0; i < objDes.ObjectData.Length; i++)
4563 {
4564 handlerObjectDescription = OnObjectDescription;
4565 if (handlerObjectDescription != null)
4566 {
4567 handlerObjectDescription(this, objDes.ObjectData[i].LocalID,
4568 Util.FieldToString(objDes.ObjectData[i].Description));
4569 }
4570 }
4571 break;
4572 case PacketType.ObjectName:
4573 ObjectNamePacket objName = (ObjectNamePacket)Pack;
4574
4575 handlerObjectName = null;
4576 for (int i = 0; i < objName.ObjectData.Length; i++)
4577 {
4578 handlerObjectName = OnObjectName;
4579 if (handlerObjectName != null)
4580 {
4581 handlerObjectName(this, objName.ObjectData[i].LocalID,
4582 Util.FieldToString(objName.ObjectData[i].Name));
4583 }
4584 }
4585 break;
4586 case PacketType.ObjectPermissions:
4587 if (OnObjectPermissions != null)
4588 {
4589 ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack;
4590
4591 LLUUID AgentID = newobjPerms.AgentData.AgentID;
4592 LLUUID SessionID = newobjPerms.AgentData.SessionID;
4593
4594 handlerObjectPermissions = null;
4595
4596 for (int i = 0; i < newobjPerms.ObjectData.Length; i++)
4597 {
4598 ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i];
4599
4600 byte field = permChanges.Field;
4601 uint localID = permChanges.ObjectLocalID;
4602 uint mask = permChanges.Mask;
4603 byte set = permChanges.Set;
4604
4605 handlerObjectPermissions = OnObjectPermissions;
4606
4607 if (handlerObjectPermissions != null)
4608 handlerObjectPermissions(this, AgentID, SessionID, field, localID, mask, set);
4609 }
4610 }
4611
4612 // Here's our data,
4613 // PermField contains the field the info goes into
4614 // PermField determines which mask we're changing
4615 //
4616 // chmask is the mask of the change
4617 // setTF is whether we're adding it or taking it away
4618 //
4619 // objLocalID is the localID of the object.
4620
4621 // Unfortunately, we have to pass the event the packet because objData is an array
4622 // That means multiple object perms may be updated in a single packet.
4623
4624 break;
4625
4626 case PacketType.Undo:
4627 UndoPacket undoitem = (UndoPacket)Pack;
4628 if (undoitem.ObjectData.Length > 0)
4629 {
4630 for (int i = 0; i < undoitem.ObjectData.Length; i++)
4631 {
4632 LLUUID objiD = undoitem.ObjectData[i].ObjectID;
4633 handlerOnUndo = OnUndo;
4634 if (handlerOnUndo != null)
4635 {
4636 handlerOnUndo(this, objiD);
4637 }
4638
4639 }
4640 }
4641 break;
4642 case PacketType.ObjectDuplicateOnRay:
4643 ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
4644
4645 handlerObjectDuplicateOnRay = null;
4646
4647
4648 for (int i = 0; i < dupeOnRay.ObjectData.Length; i++)
4649 {
4650 handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay;
4651 if (handlerObjectDuplicateOnRay != null)
4652 {
4653 handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags,
4654 dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd,
4655 dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection,
4656 dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates);
4657 }
4658 }
4659
4660 break;
4661 case PacketType.RequestObjectPropertiesFamily:
4662 //This powers the little tooltip that appears when you move your mouse over an object
4663 RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack;
4664
4665 RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData;
4666
4667 handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily;
4668
4669 if (handlerRequestObjectPropertiesFamily != null)
4670 {
4671 handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags,
4672 packObjBlock.ObjectID);
4673 }
4674
4675 break;
4676 case PacketType.ObjectIncludeInSearch:
4677 //This lets us set objects to appear in search (stuff like DataSnapshot, etc)
4678 ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack;
4679 handlerObjectIncludeInSearch = null;
4680
4681 foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData)
4682 {
4683 bool inSearch = objData.IncludeInSearch;
4684 uint localID = objData.ObjectLocalID;
4685
4686 handlerObjectIncludeInSearch = OnObjectIncludeInSearch;
4687
4688 if (handlerObjectIncludeInSearch != null)
4689 {
4690 handlerObjectIncludeInSearch(this, inSearch, localID);
4691 }
4692 }
4693 break;
4694
4695 case PacketType.ScriptAnswerYes:
4696 ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack;
4697
4698 handlerScriptAnswer = OnScriptAnswer;
4699 if (handlerScriptAnswer != null)
4700 {
4701 handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions);
4702 }
4703 break;
4704
4705 #endregion
4706
4707 #region Inventory/Asset/Other related packets
4708
4709 case PacketType.RequestImage:
4710 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
4711 //Console.WriteLine("image request: " + Pack.ToString());
4712
4713 handlerTextureRequest = null;
4714
4715 for (int i = 0; i < imageRequest.RequestImage.Length; i++)
4716 {
4717 if (OnRequestTexture != null)
4718 {
4719 TextureRequestArgs args = new TextureRequestArgs();
4720 args.RequestedAssetID = imageRequest.RequestImage[i].Image;
4721 args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel;
4722 args.PacketNumber = imageRequest.RequestImage[i].Packet;
4723 args.Priority = imageRequest.RequestImage[i].DownloadPriority;
4724
4725 handlerTextureRequest = OnRequestTexture;
4726
4727 if (handlerTextureRequest != null)
4728 OnRequestTexture(this, args);
4729 }
4730 }
4731 break;
4732 case PacketType.TransferRequest:
4733 //Console.WriteLine("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
4734 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
4735 // Validate inventory transfers
4736 // Has to be done here, because AssetCache can't do it
4737 //
4738 if (transfer.TransferInfo.SourceType == 3)
4739 {
4740 LLUUID taskID = null;
4741 LLUUID itemID = null;
4742 LLUUID requestID = null;
4743 taskID = new LLUUID(transfer.TransferInfo.Params, 48);
4744 itemID = new LLUUID(transfer.TransferInfo.Params, 64);
4745 requestID = new LLUUID(transfer.TransferInfo.Params, 80);
4746 if (!(((Scene)m_scene).ExternalChecks.ExternalChecksBypassPermissions()))
4747 {
4748 if (taskID != LLUUID.Zero) // Prim
4749 {
4750 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
4751 if (part == null)
4752 break;
4753
4754 if (part.OwnerID != AgentId)
4755 break;
4756
4757 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
4758 break;
4759
4760 TaskInventoryItem ti = part.GetInventoryItem(itemID);
4761 if (ti == null)
4762 break;
4763
4764 if (ti.OwnerID != AgentId)
4765 break;
4766
4767 if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
4768 break;
4769
4770 if (ti.AssetID != requestID)
4771 break;
4772 }
4773 else // Agent
4774 {
4775 CachedUserInfo userInfo = ((Scene)m_scene).CommsManager.UserProfileCacheService.GetUserDetails(AgentId);
4776 if (userInfo == null)
4777 break;
4778
4779 if (userInfo.RootFolder == null)
4780 break;
4781
4782 InventoryItemBase assetRequestItem = userInfo.RootFolder.FindItem(itemID);
4783 if (assetRequestItem == null)
4784 {
4785 assetRequestItem = ((Scene)m_scene).CommsManager.UserProfileCacheService.libraryRoot.FindItem(itemID);
4786 if (assetRequestItem == null)
4787 return;
4788 }
4789
4790 if ((assetRequestItem.CurrentPermissions & ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify| (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
4791 break;
4792 if (assetRequestItem.AssetID != requestID)
4793 break;
4794 }
4795 }
4796 }
4797
4798 m_assetCache.AddAssetRequest(this, transfer);
4799 /* RequestAsset = OnRequestAsset;
4800 if (RequestAsset != null)
4801 {
4802 RequestAsset(this, transfer);
4803 }*/
4804 break;
4805 case PacketType.AssetUploadRequest:
4806 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
4807 // Console.WriteLine("upload request " + Pack.ToString());
4808 // Console.WriteLine("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
4809 LLUUID temp = LLUUID.Combine(request.AssetBlock.TransactionID, SecureSessionId);
4810
4811 handlerAssetUploadRequest = OnAssetUploadRequest;
4812
4813 if (handlerAssetUploadRequest != null)
4814 {
4815 handlerAssetUploadRequest(this, temp,
4816 request.AssetBlock.TransactionID, request.AssetBlock.Type,
4817 request.AssetBlock.AssetData, request.AssetBlock.StoreLocal,
4818 request.AssetBlock.Tempfile);
4819 }
4820 break;
4821 case PacketType.RequestXfer:
4822 RequestXferPacket xferReq = (RequestXferPacket)Pack;
4823
4824 handlerRequestXfer = OnRequestXfer;
4825
4826 if (handlerRequestXfer != null)
4827 {
4828 handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename));
4829 }
4830 break;
4831 case PacketType.SendXferPacket:
4832 SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack;
4833
4834 handlerXferReceive = OnXferReceive;
4835 if (handlerXferReceive != null)
4836 {
4837 handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data);
4838 }
4839 break;
4840 case PacketType.ConfirmXferPacket:
4841 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
4842
4843 handlerConfirmXfer = OnConfirmXfer;
4844 if (handlerConfirmXfer != null)
4845 {
4846 handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
4847 }
4848 break;
4849 case PacketType.CreateInventoryFolder:
4850 CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
4851
4852 handlerCreateInventoryFolder = OnCreateNewInventoryFolder;
4853 if (handlerCreateInventoryFolder != null)
4854 {
4855 handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID,
4856 (ushort)invFolder.FolderData.Type,
4857 Util.FieldToString(invFolder.FolderData.Name),
4858 invFolder.FolderData.ParentID);
4859 }
4860 break;
4861 case PacketType.UpdateInventoryFolder:
4862 if (OnUpdateInventoryFolder != null)
4863 {
4864 UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack;
4865
4866 handlerUpdateInventoryFolder = null;
4867
4868 for (int i = 0; i < invFolderx.FolderData.Length; i++)
4869 {
4870 handlerUpdateInventoryFolder = OnUpdateInventoryFolder;
4871 if (handlerUpdateInventoryFolder != null)
4872 {
4873 OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID,
4874 (ushort)invFolderx.FolderData[i].Type,
4875 Util.FieldToString(invFolderx.FolderData[i].Name),
4876 invFolderx.FolderData[i].ParentID);
4877 }
4878 }
4879 }
4880 break;
4881 case PacketType.MoveInventoryFolder:
4882 if (OnMoveInventoryFolder != null)
4883 {
4884 MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack;
4885
4886 handlerMoveInventoryFolder = null;
4887
4888 for (int i = 0; i < invFoldery.InventoryData.Length; i++)
4889 {
4890 handlerMoveInventoryFolder = OnMoveInventoryFolder;
4891 if (handlerMoveInventoryFolder != null)
4892 {
4893 OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID,
4894 invFoldery.InventoryData[i].ParentID);
4895 }
4896 }
4897 }
4898 break;
4899 case PacketType.CreateInventoryItem:
4900 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
4901
4902 handlerCreateNewInventoryItem = OnCreateNewInventoryItem;
4903 if (handlerCreateNewInventoryItem != null)
4904 {
4905 handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID,
4906 createItem.InventoryBlock.FolderID,
4907 createItem.InventoryBlock.CallbackID,
4908 Util.FieldToString(createItem.InventoryBlock.Description),
4909 Util.FieldToString(createItem.InventoryBlock.Name),
4910 createItem.InventoryBlock.InvType,
4911 createItem.InventoryBlock.Type,
4912 createItem.InventoryBlock.WearableType,
4913 createItem.InventoryBlock.NextOwnerMask,
4914 Util.UnixTimeSinceEpoch());
4915 }
4916 break;
4917 case PacketType.FetchInventory:
4918 if (OnFetchInventory != null)
4919 {
4920 FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack;
4921
4922 handlerFetchInventory = null;
4923
4924 for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++)
4925 {
4926 handlerFetchInventory = OnFetchInventory;
4927
4928 if (handlerFetchInventory != null)
4929 {
4930 OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID,
4931 FetchInventoryx.InventoryData[i].OwnerID);
4932 }
4933 }
4934 }
4935 break;
4936 case PacketType.FetchInventoryDescendents:
4937 FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
4938
4939 handlerFetchInventoryDescendents = OnFetchInventoryDescendents;
4940 if (handlerFetchInventoryDescendents != null)
4941 {
4942 handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID,
4943 Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems,
4944 Fetch.InventoryData.SortOrder);
4945 }
4946 break;
4947 case PacketType.PurgeInventoryDescendents:
4948 PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack;
4949
4950 handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents;
4951 if (handlerPurgeInventoryDescendents != null)
4952 {
4953 handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID);
4954 }
4955 break;
4956 case PacketType.UpdateInventoryItem:
4957 UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack;
4958 if (OnUpdateInventoryItem != null)
4959 {
4960 handlerUpdateInventoryItem = null;
4961 for (int i = 0; i < update.InventoryData.Length; i++)
4962 {
4963 handlerUpdateInventoryItem = OnUpdateInventoryItem;
4964
4965 if (handlerUpdateInventoryItem != null)
4966 {
4967 InventoryItemBase itemUpd = new InventoryItemBase();
4968 itemUpd.ID = update.InventoryData[i].ItemID;
4969 itemUpd.Name = Util.FieldToString(update.InventoryData[i].Name);
4970 itemUpd.Description = Util.FieldToString(update.InventoryData[i].Description);
4971 itemUpd.GroupID = update.InventoryData[i].GroupID;
4972 itemUpd.GroupOwned = update.InventoryData[i].GroupOwned;
4973 itemUpd.NextPermissions = update.InventoryData[i].NextOwnerMask;
4974 itemUpd.EveryOnePermissions = update.InventoryData[i].EveryoneMask;
4975 itemUpd.CreationDate = update.InventoryData[i].CreationDate;
4976 itemUpd.Folder = update.InventoryData[i].FolderID;
4977 itemUpd.InvType = update.InventoryData[i].InvType;
4978 itemUpd.SalePrice = update.InventoryData[i].SalePrice;
4979 itemUpd.SaleType = update.InventoryData[i].SaleType;
4980 itemUpd.Flags = update.InventoryData[i].Flags;
4981 /*
4982 OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID,
4983 update.InventoryData[i].ItemID,
4984 Util.FieldToString(update.InventoryData[i].Name),
4985 Util.FieldToString(update.InventoryData[i].Description),
4986 update.InventoryData[i].NextOwnerMask);
4987 */
4988 OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID,
4989 update.InventoryData[i].ItemID,
4990 itemUpd);
4991 }
4992 }
4993 }
4994 //Console.WriteLine(Pack.ToString());
4995 /*for (int i = 0; i < update.InventoryData.Length; i++)
4996 {
4997 if (update.InventoryData[i].TransactionID != LLUUID.Zero)
4998 {
4999 AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionId));
5000 if (asset != null)
5001 {
5002 // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache");
5003 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
5004 }
5005 else
5006 {
5007 asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID);
5008 if (asset != null)
5009 {
5010 //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache");
5011 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
5012 }
5013 else
5014 {
5015 //Console.WriteLine("trying to update inventory item, but asset is null");
5016 }
5017 }
5018 }
5019 else
5020 {
5021 m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ;
5022 }
5023 }*/
5024 break;
5025 case PacketType.CopyInventoryItem:
5026 CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack;
5027
5028 handlerCopyInventoryItem = null;
5029 if (OnCopyInventoryItem != null)
5030 {
5031 foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData)
5032 {
5033 handlerCopyInventoryItem = OnCopyInventoryItem;
5034 if (handlerCopyInventoryItem != null)
5035 {
5036 handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID,
5037 datablock.OldItemID, datablock.NewFolderID,
5038 Util.FieldToString(datablock.NewName));
5039 }
5040 }
5041 }
5042 break;
5043 case PacketType.MoveInventoryItem:
5044 MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack;
5045 if (OnMoveInventoryItem != null)
5046 {
5047 handlerMoveInventoryItem = null;
5048 foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData)
5049 {
5050 handlerMoveInventoryItem = OnMoveInventoryItem;
5051 if (handlerMoveInventoryItem != null)
5052 {
5053 handlerMoveInventoryItem(this, datablock.FolderID, datablock.ItemID, datablock.Length,
5054 Util.FieldToString(datablock.NewName));
5055 }
5056 }
5057 }
5058 break;
5059 case PacketType.RemoveInventoryItem:
5060 RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack;
5061 if (OnRemoveInventoryItem != null)
5062 {
5063 handlerRemoveInventoryItem = null;
5064 foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData)
5065 {
5066 handlerRemoveInventoryItem = OnRemoveInventoryItem;
5067 if (handlerRemoveInventoryItem != null)
5068 {
5069 handlerRemoveInventoryItem(this, datablock.ItemID);
5070 }
5071 }
5072 }
5073 break;
5074 case PacketType.RemoveInventoryFolder:
5075 RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack;
5076 if (OnRemoveInventoryFolder != null)
5077 {
5078 handlerRemoveInventoryFolder = null;
5079 foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData)
5080 {
5081 handlerRemoveInventoryFolder = OnRemoveInventoryFolder;
5082
5083 if (handlerRemoveInventoryFolder != null)
5084 {
5085 handlerRemoveInventoryFolder(this, datablock.FolderID);
5086 }
5087 }
5088 }
5089 break;
5090 case PacketType.RequestTaskInventory:
5091 RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
5092
5093 handlerRequestTaskInventory = OnRequestTaskInventory;
5094 if (handlerRequestTaskInventory != null)
5095 {
5096 handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID);
5097 }
5098 break;
5099 case PacketType.UpdateTaskInventory:
5100 UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
5101 if (OnUpdateTaskInventory != null)
5102 {
5103 if (updatetask.UpdateData.Key == 0)
5104 {
5105 handlerUpdateTaskInventory = OnUpdateTaskInventory;
5106 if (handlerUpdateTaskInventory != null)
5107 {
5108 TaskInventoryItem newTaskItem = new TaskInventoryItem();
5109 newTaskItem.ItemID = updatetask.InventoryData.ItemID;
5110 newTaskItem.ParentID = updatetask.InventoryData.FolderID;
5111 newTaskItem.CreatorID = updatetask.InventoryData.CreatorID;
5112 newTaskItem.OwnerID = updatetask.InventoryData.OwnerID;
5113 newTaskItem.GroupID = updatetask.InventoryData.GroupID;
5114 newTaskItem.BasePermissions = updatetask.InventoryData.BaseMask;
5115 newTaskItem.CurrentPermissions = updatetask.InventoryData.OwnerMask;
5116 newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask;
5117 newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask;
5118 newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask;
5119 //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned;
5120 newTaskItem.Type = updatetask.InventoryData.Type;
5121 newTaskItem.InvType = updatetask.InventoryData.InvType;
5122 newTaskItem.Flags = updatetask.InventoryData.Flags;
5123 //newTaskItem.SaleType=updatetask.InventoryData.SaleType;
5124 //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;;
5125 newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name);
5126 newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description);
5127 newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate;
5128 handlerUpdateTaskInventory(this, updatetask.InventoryData.TransactionID,
5129 newTaskItem, updatetask.UpdateData.LocalID);
5130 }
5131 }
5132 }
5133
5134 break;
5135
5136 case PacketType.RemoveTaskInventory:
5137
5138 RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack;
5139
5140 handlerRemoveTaskItem = OnRemoveTaskItem;
5141
5142 if (handlerRemoveTaskItem != null)
5143 {
5144 handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID);
5145 }
5146
5147 break;
5148
5149 case PacketType.MoveTaskInventory:
5150
5151 MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack;
5152
5153 handlerMoveTaskItem = OnMoveTaskItem;
5154
5155 if (handlerMoveTaskItem != null)
5156 {
5157 handlerMoveTaskItem(
5158 this, moveTaskInventoryPacket.AgentData.FolderID,
5159 moveTaskInventoryPacket.InventoryData.LocalID,
5160 moveTaskInventoryPacket.InventoryData.ItemID);
5161 }
5162
5163 break;
5164
5165 case PacketType.RezScript:
5166
5167 //Console.WriteLine(Pack.ToString());
5168 RezScriptPacket rezScriptx = (RezScriptPacket)Pack;
5169
5170 handlerRezScript = OnRezScript;
5171 InventoryItemBase item = new InventoryItemBase();
5172 item.ID = rezScriptx.InventoryBlock.ItemID;
5173 item.Folder = rezScriptx.InventoryBlock.FolderID;
5174 item.Creator = rezScriptx.InventoryBlock.CreatorID;
5175 item.Owner = rezScriptx.InventoryBlock.OwnerID;
5176 item.BasePermissions = rezScriptx.InventoryBlock.BaseMask;
5177 item.CurrentPermissions = rezScriptx.InventoryBlock.OwnerMask;
5178 item.EveryOnePermissions = rezScriptx.InventoryBlock.EveryoneMask;
5179 item.NextPermissions = rezScriptx.InventoryBlock.NextOwnerMask;
5180 item.GroupOwned = rezScriptx.InventoryBlock.GroupOwned;
5181 item.GroupID = rezScriptx.InventoryBlock.GroupID;
5182 item.AssetType = rezScriptx.InventoryBlock.Type;
5183 item.InvType = rezScriptx.InventoryBlock.InvType;
5184 item.Flags = rezScriptx.InventoryBlock.Flags;
5185 item.SaleType = rezScriptx.InventoryBlock.SaleType;
5186 item.SalePrice = rezScriptx.InventoryBlock.SalePrice;
5187 item.Name = Util.FieldToString(rezScriptx.InventoryBlock.Name);
5188 item.Description = Util.FieldToString(rezScriptx.InventoryBlock.Description);
5189 item.CreationDate = (int)rezScriptx.InventoryBlock.CreationDate;
5190
5191 if (handlerRezScript != null)
5192 {
5193 handlerRezScript(this, item, rezScriptx.InventoryBlock.TransactionID, rezScriptx.UpdateBlock.ObjectLocalID);
5194 }
5195 break;
5196
5197 case PacketType.MapLayerRequest:
5198 RequestMapLayer();
5199 break;
5200 case PacketType.MapBlockRequest:
5201 MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack;
5202
5203 handlerRequestMapBlocks = OnRequestMapBlocks;
5204 if (handlerRequestMapBlocks != null)
5205 {
5206 handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY,
5207 MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY, MapRequest.AgentData.Flags);
5208 }
5209 break;
5210 case PacketType.MapNameRequest:
5211 MapNameRequestPacket map = (MapNameRequestPacket)Pack;
5212 string mapName = UTF8Encoding.UTF8.GetString(map.NameData.Name, 0,
5213 map.NameData.Name.Length - 1);
5214 handlerMapNameRequest = OnMapNameRequest;
5215 if (handlerMapNameRequest != null)
5216 {
5217 handlerMapNameRequest(this, mapName);
5218 }
5219 break;
5220 case PacketType.TeleportLandmarkRequest:
5221 TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
5222 LLUUID lmid = tpReq.Info.LandmarkID;
5223 AssetLandmark lm;
5224 if (lmid != LLUUID.Zero)
5225 {
5226 AssetBase lma = m_assetCache.GetAsset(lmid, false);
5227
5228 if (lma == null)
5229 {
5230 // Failed to find landmark
5231 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
5232 tpCancel.Info.SessionID = tpReq.Info.SessionID;
5233 tpCancel.Info.AgentID = tpReq.Info.AgentID;
5234 OutPacket(tpCancel, ThrottleOutPacketType.Task);
5235 }
5236
5237 try
5238 {
5239 lm = new AssetLandmark(lma);
5240 }
5241 catch (NullReferenceException)
5242 {
5243 // asset not found generates null ref inside the assetlandmark constructor.
5244 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
5245 tpCancel.Info.SessionID = tpReq.Info.SessionID;
5246 tpCancel.Info.AgentID = tpReq.Info.AgentID;
5247 OutPacket(tpCancel, ThrottleOutPacketType.Task);
5248 break;
5249 }
5250 }
5251 else
5252 {
5253 // Teleport home request
5254 handlerTeleportHomeRequest = OnTeleportHomeRequest;
5255 if (handlerTeleportHomeRequest != null)
5256 {
5257 handlerTeleportHomeRequest(this.AgentId, this);
5258 }
5259 break;
5260 }
5261
5262 handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest;
5263 if (handlerTeleportLandmarkRequest != null)
5264 {
5265 handlerTeleportLandmarkRequest(this, lm.RegionHandle, lm.Position);
5266 }
5267 else
5268 {
5269 //no event handler so cancel request
5270
5271
5272 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
5273 tpCancel.Info.AgentID = tpReq.Info.AgentID;
5274 tpCancel.Info.SessionID = tpReq.Info.SessionID;
5275 OutPacket(tpCancel, ThrottleOutPacketType.Task);
5276
5277 }
5278 break;
5279 case PacketType.TeleportLocationRequest:
5280 TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
5281 // Console.WriteLine(tpLocReq.ToString());
5282
5283 handlerTeleportLocationRequest = OnTeleportLocationRequest;
5284 if (handlerTeleportLocationRequest != null)
5285 {
5286 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
5287 tpLocReq.Info.LookAt, 16);
5288 }
5289 else
5290 {
5291 //no event handler so cancel request
5292 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
5293 tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID;
5294 tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID;
5295 OutPacket(tpCancel, ThrottleOutPacketType.Task);
5296 }
5297 break;
5298
5299 #endregion
5300
5301 case PacketType.UUIDNameRequest:
5302 UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack;
5303 foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock)
5304 {
5305 handlerNameRequest = OnNameFromUUIDRequest;
5306 if (handlerNameRequest != null)
5307 {
5308 handlerNameRequest(UUIDBlock.ID, this);
5309 }
5310 }
5311 break;
5312
5313 #region Parcel related packets
5314
5315 case PacketType.ParcelAccessListRequest:
5316 ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack;
5317
5318 handlerParcelAccessListRequest = OnParcelAccessListRequest;
5319
5320 if (handlerParcelAccessListRequest != null)
5321 {
5322 handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID,
5323 requestPacket.Data.Flags, requestPacket.Data.SequenceID,
5324 requestPacket.Data.LocalID, this);
5325 }
5326 break;
5327
5328 case PacketType.ParcelAccessListUpdate:
5329 ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack;
5330 List<ParcelManager.ParcelAccessEntry> entries = new List<ParcelManager.ParcelAccessEntry>();
5331 foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List)
5332 {
5333 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
5334 entry.AgentID = block.ID;
5335 entry.Flags = (ParcelManager.AccessList)block.Flags;
5336 entry.Time = new DateTime();
5337 entries.Add(entry);
5338 }
5339
5340 handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest;
5341 if (handlerParcelAccessListUpdateRequest != null)
5342 {
5343 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID,
5344 updatePacket.AgentData.SessionID, updatePacket.Data.Flags,
5345 updatePacket.Data.LocalID, entries, this);
5346 }
5347 break;
5348 case PacketType.ParcelPropertiesRequest:
5349
5350 ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack;
5351
5352 handlerParcelPropertiesRequest = OnParcelPropertiesRequest;
5353 if (handlerParcelPropertiesRequest != null)
5354 {
5355 handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West),
5356 (int)Math.Round(propertiesRequest.ParcelData.South),
5357 (int)Math.Round(propertiesRequest.ParcelData.East),
5358 (int)Math.Round(propertiesRequest.ParcelData.North),
5359 propertiesRequest.ParcelData.SequenceID,
5360 propertiesRequest.ParcelData.SnapSelection, this);
5361 }
5362 break;
5363 case PacketType.ParcelDivide:
5364 ParcelDividePacket landDivide = (ParcelDividePacket)Pack;
5365
5366 handlerParcelDivideRequest = OnParcelDivideRequest;
5367 if (handlerParcelDivideRequest != null)
5368 {
5369 handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West),
5370 (int)Math.Round(landDivide.ParcelData.South),
5371 (int)Math.Round(landDivide.ParcelData.East),
5372 (int)Math.Round(landDivide.ParcelData.North), this);
5373 }
5374 break;
5375 case PacketType.ParcelJoin:
5376 ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack;
5377
5378 handlerParcelJoinRequest = OnParcelJoinRequest;
5379
5380 if (handlerParcelJoinRequest != null)
5381 {
5382 handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West),
5383 (int)Math.Round(landJoin.ParcelData.South),
5384 (int)Math.Round(landJoin.ParcelData.East),
5385 (int)Math.Round(landJoin.ParcelData.North), this);
5386 }
5387 break;
5388 case PacketType.ParcelPropertiesUpdate:
5389 ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack;
5390
5391 handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest;
5392
5393 if (handlerParcelPropertiesUpdateRequest != null)
5394 {
5395 LandUpdateArgs args = new LandUpdateArgs();
5396
5397 args.AuthBuyerID = parcelPropertiesPacket.ParcelData.AuthBuyerID;
5398 args.Category = (Parcel.ParcelCategory)parcelPropertiesPacket.ParcelData.Category;
5399 args.Desc = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.Desc);
5400 args.GroupID = parcelPropertiesPacket.ParcelData.GroupID;
5401 args.LandingType = parcelPropertiesPacket.ParcelData.LandingType;
5402 args.MediaAutoScale = parcelPropertiesPacket.ParcelData.MediaAutoScale;
5403 args.MediaID = parcelPropertiesPacket.ParcelData.MediaID;
5404 args.MediaURL = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.MediaURL);
5405 args.MusicURL = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.MusicURL);
5406 args.Name = Helpers.FieldToUTF8String(parcelPropertiesPacket.ParcelData.Name);
5407 args.ParcelFlags = parcelPropertiesPacket.ParcelData.ParcelFlags;
5408 args.PassHours = parcelPropertiesPacket.ParcelData.PassHours;
5409 args.PassPrice = parcelPropertiesPacket.ParcelData.PassPrice;
5410 args.SalePrice = parcelPropertiesPacket.ParcelData.SalePrice;
5411 args.SnapshotID = parcelPropertiesPacket.ParcelData.SnapshotID;
5412 args.UserLocation = parcelPropertiesPacket.ParcelData.UserLocation;
5413 args.UserLookAt = parcelPropertiesPacket.ParcelData.UserLookAt;
5414 handlerParcelPropertiesUpdateRequest(args, parcelPropertiesPacket.ParcelData.LocalID, this);
5415 }
5416 break;
5417 case PacketType.ParcelSelectObjects:
5418 ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack;
5419
5420 handlerParcelSelectObjects = OnParcelSelectObjects;
5421
5422 if (handlerParcelSelectObjects != null)
5423 {
5424 handlerParcelSelectObjects(selectPacket.ParcelData.LocalID,
5425 Convert.ToInt32(selectPacket.ParcelData.ReturnType), this);
5426 }
5427 break;
5428 case PacketType.ParcelObjectOwnersRequest:
5429 //Console.WriteLine(Pack.ToString());
5430 ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack;
5431
5432 handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest;
5433
5434 if (handlerParcelObjectOwnerRequest != null)
5435 {
5436 handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this);
5437 }
5438 break;
5439 case PacketType.ParcelRelease:
5440 ParcelReleasePacket releasePacket = (ParcelReleasePacket)Pack;
5441
5442 handlerParcelAbandonRequest = OnParcelAbandonRequest;
5443 if (handlerParcelAbandonRequest != null)
5444 {
5445 handlerParcelAbandonRequest(releasePacket.Data.LocalID, this);
5446 }
5447 break;
5448 case PacketType.ParcelReclaim:
5449 ParcelReclaimPacket reclaimPacket = (ParcelReclaimPacket)Pack;
5450
5451 handlerParcelReclaim = OnParcelReclaim;
5452 if (handlerParcelReclaim != null)
5453 {
5454 handlerParcelReclaim(reclaimPacket.Data.LocalID, this);
5455 }
5456 break;
5457 case PacketType.ParcelReturnObjects:
5458
5459
5460 ParcelReturnObjectsPacket parcelReturnObjects = (ParcelReturnObjectsPacket)Pack;
5461
5462 LLUUID[] puserselectedOwnerIDs = new LLUUID[parcelReturnObjects.OwnerIDs.Length];
5463 for (int parceliterator = 0; parceliterator < parcelReturnObjects.OwnerIDs.Length; parceliterator++)
5464 puserselectedOwnerIDs[parceliterator] = parcelReturnObjects.OwnerIDs[parceliterator].OwnerID;
5465
5466 LLUUID[] puserselectedTaskIDs = new LLUUID[parcelReturnObjects.TaskIDs.Length];
5467
5468 for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++)
5469 puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID;
5470
5471 handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest;
5472 if (handlerParcelReturnObjectsRequest != null)
5473 {
5474 handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this);
5475
5476 }
5477 break;
5478
5479 #endregion
5480
5481 #region Estate Packets
5482
5483 case PacketType.EstateOwnerMessage:
5484 EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack;
5485
5486 switch (Helpers.FieldToUTF8String(messagePacket.MethodData.Method))
5487 {
5488 case "getinfo":
5489
5490 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5491 {
5492 OnDetailedEstateDataRequest(this, messagePacket.MethodData.Invoice);
5493 }
5494 break;
5495 case "setregioninfo":
5496 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5497 {
5498 OnSetEstateFlagsRequest(convertParamStringToBool(messagePacket.ParamList[0].Parameter), convertParamStringToBool(messagePacket.ParamList[1].Parameter),
5499 convertParamStringToBool(messagePacket.ParamList[2].Parameter), !convertParamStringToBool(messagePacket.ParamList[3].Parameter),
5500 Convert.ToInt16(Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[4].Parameter))),
5501 (float)Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[5].Parameter)),
5502 Convert.ToInt16(Helpers.FieldToUTF8String(messagePacket.ParamList[6].Parameter)),
5503 convertParamStringToBool(messagePacket.ParamList[7].Parameter), convertParamStringToBool(messagePacket.ParamList[8].Parameter));
5504
5505 }
5506
5507 break;
5508// case "texturebase":
5509// if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5510// {
5511// foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
5512// {
5513// string s = Helpers.FieldToUTF8String(block.Parameter);
5514// string[] splitField = s.Split(' ');
5515// if (splitField.Length == 2)
5516// {
5517// LLUUID tempUUID = new LLUUID(splitField[1]);
5518// OnSetEstateTerrainBaseTexture(this, Convert.ToInt16(splitField[0]), tempUUID);
5519// }
5520// }
5521// }
5522// break;
5523 case "texturedetail":
5524 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5525 {
5526 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
5527 {
5528 string s = Helpers.FieldToUTF8String(block.Parameter);
5529 string[] splitField = s.Split(' ');
5530 if (splitField.Length == 2)
5531 {
5532 Int16 corner = Convert.ToInt16(splitField[0]);
5533 LLUUID textureUUID = new LLUUID(splitField[1]);
5534
5535 OnSetEstateTerrainDetailTexture(this, corner, textureUUID);
5536 }
5537 }
5538 }
5539
5540 break;
5541 case "textureheights":
5542 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5543 {
5544 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
5545 {
5546 string s = Helpers.FieldToUTF8String(block.Parameter);
5547 string[] splitField = s.Split(' ');
5548 if (splitField.Length == 3)
5549 {
5550 Int16 corner = Convert.ToInt16(splitField[0]);
5551 float lowValue = (float)Convert.ToDecimal(splitField[1]);
5552 float highValue = (float)Convert.ToDecimal(splitField[2]);
5553
5554 OnSetEstateTerrainTextureHeights(this, corner, lowValue, highValue);
5555 }
5556 }
5557 }
5558 break;
5559 case "texturecommit":
5560 OnCommitEstateTerrainTextureRequest(this);
5561 break;
5562 case "setregionterrain":
5563 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5564 {
5565 if (messagePacket.ParamList.Length != 9)
5566 {
5567 m_log.Error("EstateOwnerMessage: SetRegionTerrain method has a ParamList of invalid length");
5568 }
5569 else
5570 {
5571 try
5572 {
5573 string tmp;
5574 tmp = Helpers.FieldToUTF8String(messagePacket.ParamList[0].Parameter);
5575 if (!tmp.Contains(".")) tmp += ".00";
5576 float WaterHeight = (float)Convert.ToDecimal(tmp);
5577 tmp = Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter);
5578 if (!tmp.Contains(".")) tmp += ".00";
5579 float TerrainRaiseLimit = (float)Convert.ToDecimal(tmp);
5580 tmp = Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter);
5581 if (!tmp.Contains(".")) tmp += ".00";
5582 float TerrainLowerLimit = (float)Convert.ToDecimal(tmp);
5583 bool UseEstateSun = convertParamStringToBool(messagePacket.ParamList[3].Parameter);
5584 bool UseFixedSun = convertParamStringToBool(messagePacket.ParamList[4].Parameter);
5585 float SunHour = (float)Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[5].Parameter));
5586 bool UseGlobal = convertParamStringToBool(messagePacket.ParamList[6].Parameter);
5587 bool EstateFixedSun = convertParamStringToBool(messagePacket.ParamList[7].Parameter);
5588 float EstateSunHour = (float)Convert.ToDecimal(Helpers.FieldToUTF8String(messagePacket.ParamList[8].Parameter));
5589
5590 OnSetRegionTerrainSettings(WaterHeight, TerrainRaiseLimit, TerrainLowerLimit, UseEstateSun, UseFixedSun, SunHour, UseGlobal, EstateFixedSun, EstateSunHour);
5591
5592 }
5593 catch (Exception ex)
5594 {
5595 m_log.Error("EstateOwnerMessage: Exception while setting terrain settings: \n" + messagePacket.ToString() + "\n" + ex.ToString());
5596 }
5597 }
5598 }
5599
5600 break;
5601 case "restart":
5602 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5603 {
5604 // There's only 1 block in the estateResetSim.. and that's the number of seconds till restart.
5605 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
5606 {
5607 float timeSeconds = 0;
5608 Helpers.TryParse(Helpers.FieldToUTF8String(block.Parameter), out timeSeconds);
5609 timeSeconds = (int)timeSeconds;
5610 OnEstateRestartSimRequest(this, (int)timeSeconds);
5611
5612 }
5613 }
5614 break;
5615 case "estatechangecovenantid":
5616 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5617 {
5618 foreach (EstateOwnerMessagePacket.ParamListBlock block in messagePacket.ParamList)
5619 {
5620 LLUUID newCovenantID = new LLUUID(Helpers.FieldToUTF8String(block.Parameter));
5621 OnEstateChangeCovenantRequest(this, newCovenantID);
5622 }
5623 }
5624 break;
5625 case "estateaccessdelta": // Estate access delta manages the banlist and allow list too.
5626 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5627 {
5628 int estateAccessType = Convert.ToInt16(Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter));
5629 OnUpdateEstateAccessDeltaRequest(this, messagePacket.MethodData.Invoice, estateAccessType, new LLUUID(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter)));
5630
5631 }
5632 break;
5633 case "simulatormessage":
5634 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5635 {
5636 LLUUID invoice = messagePacket.MethodData.Invoice;
5637 LLUUID SenderID = new LLUUID(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter));
5638 string SenderName = Helpers.FieldToUTF8String(messagePacket.ParamList[3].Parameter);
5639 string Message = Helpers.FieldToUTF8String(messagePacket.ParamList[4].Parameter);
5640 LLUUID sessionID = messagePacket.AgentData.SessionID;
5641 OnSimulatorBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
5642 }
5643 break;
5644 case "instantmessage":
5645 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5646 {
5647 if (messagePacket.ParamList.Length < 5)
5648 break;
5649 LLUUID invoice = messagePacket.MethodData.Invoice;
5650 LLUUID SenderID = new LLUUID(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter));
5651 string SenderName = Helpers.FieldToUTF8String(messagePacket.ParamList[3].Parameter);
5652 string Message = Helpers.FieldToUTF8String(messagePacket.ParamList[4].Parameter);
5653 LLUUID sessionID = messagePacket.AgentData.SessionID;
5654 OnEstateBlueBoxMessageRequest(this, invoice, SenderID, sessionID, SenderName, Message);
5655 }
5656 break;
5657 case "setregiondebug":
5658 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5659 {
5660 LLUUID invoice = messagePacket.MethodData.Invoice;
5661 LLUUID SenderID = messagePacket.AgentData.AgentID;
5662 bool scripted = convertParamStringToBool(messagePacket.ParamList[0].Parameter);
5663 bool collisionEvents = convertParamStringToBool(messagePacket.ParamList[1].Parameter);
5664 bool physics = convertParamStringToBool(messagePacket.ParamList[2].Parameter);
5665
5666 OnEstateDebugRegionRequest(this, invoice, SenderID, scripted, collisionEvents, physics);
5667 }
5668 break;
5669 case "teleporthomeuser":
5670 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5671 {
5672 LLUUID invoice = messagePacket.MethodData.Invoice;
5673 LLUUID SenderID = messagePacket.AgentData.AgentID;
5674 LLUUID Prey = LLUUID.Zero;
5675
5676 Helpers.TryParse(Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter), out Prey);
5677
5678 OnEstateTeleportOneUserHomeRequest(this, invoice, SenderID, Prey);
5679 }
5680 break;
5681 case "colliders":
5682 handlerLandStatRequest = OnLandStatRequest;
5683 if (handlerLandStatRequest != null)
5684 {
5685 handlerLandStatRequest(0, 1, 0, "", this);
5686 }
5687 break;
5688 case "scripts":
5689 handlerLandStatRequest = OnLandStatRequest;
5690 if (handlerLandStatRequest != null)
5691 {
5692 handlerLandStatRequest(0, 0, 0, "", this);
5693 }
5694 break;
5695 case "terrain":
5696 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5697 {
5698 handlerBakeTerrain = OnBakeTerrain;
5699 if (handlerBakeTerrain != null)
5700 {
5701 handlerBakeTerrain(this);
5702 }
5703 }
5704 break;
5705
5706 case "estatechangeinfo":
5707 if (((Scene)m_scene).ExternalChecks.ExternalChecksCanIssueEstateCommand(this.AgentId))
5708 {
5709 LLUUID invoice = messagePacket.MethodData.Invoice;
5710 LLUUID SenderID = messagePacket.AgentData.AgentID;
5711 UInt32 param1 = Convert.ToUInt32(Helpers.FieldToUTF8String(messagePacket.ParamList[1].Parameter));
5712 UInt32 param2 = Convert.ToUInt32(Helpers.FieldToUTF8String(messagePacket.ParamList[2].Parameter));
5713
5714 handlerEstateChangeInfo = OnEstateChangeInfo;
5715 if (handlerEstateChangeInfo != null)
5716 {
5717 handlerEstateChangeInfo(this, invoice, SenderID, param1, param2);
5718 }
5719 }
5720 break;
5721
5722 default:
5723 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket.ToString());
5724 break;
5725 }
5726 break;
5727 case PacketType.LandStatRequest:
5728 LandStatRequestPacket lsrp = (LandStatRequestPacket)Pack;
5729
5730 handlerLandStatRequest = OnLandStatRequest;
5731 if (handlerLandStatRequest != null)
5732 {
5733 handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Helpers.FieldToUTF8String(lsrp.RequestData.Filter), this);
5734 }
5735 //int parcelID, uint reportType, uint requestflags, string filter
5736
5737 //lsrp.RequestData.ParcelLocalID;
5738 //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts
5739 //lsrp.RequestData.RequestFlags;
5740 //lsrp.RequestData.Filter;
5741
5742 break;
5743
5744 case PacketType.RequestRegionInfo:
5745 // RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData;
5746
5747 handlerRegionInfoRequest = OnRegionInfoRequest;
5748 if (handlerRegionInfoRequest != null)
5749 {
5750 handlerRegionInfoRequest(this);
5751 }
5752 break;
5753 case PacketType.EstateCovenantRequest:
5754
5755 // EstateCovenantRequestPacket.AgentDataBlock epack =
5756 // ((EstateCovenantRequestPacket)Pack).AgentData;
5757
5758 handlerEstateCovenantRequest = OnEstateCovenantRequest;
5759 if (handlerEstateCovenantRequest != null)
5760 {
5761 handlerEstateCovenantRequest(this);
5762 }
5763 break;
5764
5765 #endregion
5766
5767 #region GodPackets
5768
5769 case PacketType.RequestGodlikePowers:
5770 RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack;
5771 RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock;
5772 LLUUID token = rblock.Token;
5773
5774 RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData;
5775
5776 handlerReqGodlikePowers = OnRequestGodlikePowers;
5777
5778 if (handlerReqGodlikePowers != null)
5779 {
5780 handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this);
5781 }
5782
5783 break;
5784 case PacketType.GodKickUser:
5785 m_log.Warn("[CLIENT]: unhandled GodKickUser packet");
5786
5787 GodKickUserPacket gkupack = (GodKickUserPacket)Pack;
5788
5789 if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID)
5790 {
5791 handlerGodKickUser = OnGodKickUser;
5792 if (handlerGodKickUser != null)
5793 {
5794 handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID,
5795 gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason);
5796 }
5797 }
5798 else
5799 {
5800 SendAgentAlertMessage("Kick request denied", false);
5801 }
5802 //KickUserPacket kupack = new KickUserPacket();
5803 //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo;
5804
5805 //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID;
5806 //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID;
5807
5808 //kupack.TargetBlock.TargetIP = (uint)0;
5809 //kupack.TargetBlock.TargetPort = (ushort)0;
5810 //kupack.UserInfo.Reason = gkupack.UserInfo.Reason;
5811
5812 //OutPacket(kupack, ThrottleOutPacketType.Task);
5813 break;
5814
5815 #endregion
5816
5817 #region Economy/Transaction Packets
5818
5819 case PacketType.MoneyBalanceRequest:
5820 MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack;
5821
5822 handlerMoneyBalanceRequest = OnMoneyBalanceRequest;
5823
5824 if (handlerMoneyBalanceRequest != null)
5825 {
5826 handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID);
5827 }
5828
5829 break;
5830 case PacketType.EconomyDataRequest:
5831
5832 handlerEconomoyDataRequest = OnEconomyDataRequest;
5833 if (handlerEconomoyDataRequest != null)
5834 {
5835 handlerEconomoyDataRequest(AgentId);
5836 }
5837 // TODO: handle this packet
5838 //m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet");
5839 break;
5840 case PacketType.RequestPayPrice:
5841 RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack;
5842 handlerRequestPayPrice = OnRequestPayPrice;
5843 if (handlerRequestPayPrice != null)
5844 {
5845 handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID);
5846 }
5847 break;
5848
5849 #endregion
5850
5851 #region Script Packets
5852
5853 case PacketType.GetScriptRunning:
5854 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack;
5855 handlerGetScriptRunning = OnGetScriptRunning;
5856 if (handlerGetScriptRunning != null)
5857 {
5858 handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID);
5859 }
5860 break;
5861
5862 case PacketType.SetScriptRunning:
5863 SetScriptRunningPacket setScriptRunning = (SetScriptRunningPacket)Pack;
5864 handlerSetScriptRunning = OnSetScriptRunning;
5865 if (handlerSetScriptRunning != null)
5866 {
5867 handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running);
5868 }
5869 break;
5870
5871 case PacketType.ScriptReset:
5872 ScriptResetPacket scriptResetPacket = (ScriptResetPacket)Pack;
5873 handlerScriptReset = OnScriptReset;
5874 if (handlerScriptReset != null)
5875 {
5876 handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID);
5877 }
5878 break;
5879
5880 #endregion
5881
5882 #region unimplemented handlers
5883
5884 case PacketType.StartPingCheck:
5885 // Send the client the ping response back
5886 // Pass the same PingID in the matching packet
5887 // Handled In the packet processing
5888 //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet");
5889 break;
5890 case PacketType.CompletePingCheck:
5891 // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client
5892 //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet");
5893 break;
5894
5895 case PacketType.ViewerStats:
5896 // TODO: handle this packet
5897 m_log.Warn("[CLIENT]: unhandled ViewerStats packet");
5898 break;
5899
5900 case PacketType.CreateGroupRequest:
5901 // TODO: handle this packet
5902 m_log.Warn("[CLIENT]: unhandled CreateGroupRequest packet");
5903 break;
5904 //case PacketType.GenericMessage:
5905 // TODO: handle this packet
5906 //m_log.Warn("[CLIENT]: unhandled GenericMessage packet");
5907 //break;
5908 case PacketType.MapItemRequest:
5909 // TODO: handle this packet
5910 m_log.Warn("[CLIENT]: unhandled MapItemRequest packet");
5911 break;
5912 case PacketType.TransferAbort:
5913 // TODO: handle this packet
5914 m_log.Warn("[CLIENT]: unhandled TransferAbort packet");
5915 break;
5916 case PacketType.MuteListRequest:
5917 // TODO: handle this packet
5918 m_log.Warn("[CLIENT]: unhandled MuteListRequest packet");
5919 break;
5920 case PacketType.ParcelDwellRequest:
5921 // TODO: handle this packet
5922 m_log.Warn("[CLIENT]: unhandled ParcelDwellRequest packet");
5923 break;
5924 case PacketType.UseCircuitCode:
5925 // TODO: Don't display this one, we handle it at a lower level
5926 //m_log.Warn("[CLIENT]: unhandled UseCircuitCode packet");
5927 break;
5928
5929 case PacketType.AgentHeightWidth:
5930 // TODO: handle this packet
5931 m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet");
5932 break;
5933 case PacketType.ObjectSpinStop:
5934 // TODO: handle this packet
5935 m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet");
5936 break;
5937 case PacketType.SoundTrigger:
5938 // TODO: handle this packet
5939 m_log.Warn("[CLIENT]: unhandled SoundTrigger packet");
5940 break;
5941 case PacketType.InventoryDescendents:
5942 // TODO: handle this packet
5943 m_log.Warn("[CLIENT]: unhandled InventoryDescent packet");
5944 break;
5945 default:
5946 m_log.Warn("[CLIENT]: unhandled packet " + Pack.ToString());
5947 break;
5948
5949 #endregion
5950 }
5951 }
5952
5953 PacketPool.Instance.ReturnPacket(Pack);
5954 }
5955
5956 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
5957 {
5958 PrimitiveBaseShape shape = new PrimitiveBaseShape();
5959
5960 shape.PCode = addPacket.ObjectData.PCode;
5961 shape.State = addPacket.ObjectData.State;
5962 shape.PathBegin = addPacket.ObjectData.PathBegin;
5963 shape.PathEnd = addPacket.ObjectData.PathEnd;
5964 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
5965 shape.PathScaleY = addPacket.ObjectData.PathScaleY;
5966 shape.PathShearX = addPacket.ObjectData.PathShearX;
5967 shape.PathShearY = addPacket.ObjectData.PathShearY;
5968 shape.PathSkew = addPacket.ObjectData.PathSkew;
5969 shape.ProfileBegin = addPacket.ObjectData.ProfileBegin;
5970 shape.ProfileEnd = addPacket.ObjectData.ProfileEnd;
5971 shape.Scale = addPacket.ObjectData.Scale;
5972 shape.PathCurve = addPacket.ObjectData.PathCurve;
5973 shape.ProfileCurve = addPacket.ObjectData.ProfileCurve;
5974 shape.ProfileHollow = addPacket.ObjectData.ProfileHollow;
5975 shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset;
5976 shape.PathRevolutions = addPacket.ObjectData.PathRevolutions;
5977 shape.PathTaperX = addPacket.ObjectData.PathTaperX;
5978 shape.PathTaperY = addPacket.ObjectData.PathTaperY;
5979 shape.PathTwist = addPacket.ObjectData.PathTwist;
5980 shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin;
5981 LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("89556747-24cb-43ed-920b-47caed15465f"));
5982 shape.TextureEntry = ntex.ToBytes();
5983 //shape.Textures = ntex;
5984 return shape;
5985 }
5986
5987 /// <summary>
5988 /// Send the client an Estate message blue box pop-down with a single OK button
5989 /// </summary>
5990 /// <param name="FromAvatarID"></param>
5991 /// <param name="fromSessionID"></param>
5992 /// <param name="FromAvatarName"></param>
5993 /// <param name="Message"></param>
5994 public void SendBlueBoxMessage(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message)
5995 {
5996 if (!ChildAgentStatus())
5997 SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)1, (uint)Util.UnixTimeSinceEpoch());
5998
5999 //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
6000 }
6001
6002 public void SendLogoutPacket()
6003 {
6004 LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
6005 // TODO: don't create new blocks if recycling an old packet
6006 logReply.AgentData.AgentID = AgentId;
6007 logReply.AgentData.SessionID = SessionId;
6008 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
6009 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
6010 logReply.InventoryData[0].ItemID = LLUUID.Zero;
6011
6012 OutPacket(logReply, ThrottleOutPacketType.Task);
6013 }
6014
6015 public void SendHealth(float health)
6016 {
6017 HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage);
6018 healthpacket.HealthData.Health = health;
6019 OutPacket(healthpacket, ThrottleOutPacketType.Task);
6020 }
6021
6022 public void SendAgentOnline(LLUUID[] agentIDs)
6023 {
6024 OnlineNotificationPacket onp = new OnlineNotificationPacket();
6025 OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length];
6026 for (int i = 0; i < agentIDs.Length; i++)
6027 {
6028 OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
6029 onpbl.AgentID = agentIDs[i];
6030 onpb[i] = onpbl;
6031 }
6032 onp.AgentBlock = onpb;
6033 onp.Header.Reliable = true;
6034 OutPacket(onp, ThrottleOutPacketType.Task);
6035 }
6036
6037 public void SendAgentOffline(LLUUID[] agentIDs)
6038 {
6039 OfflineNotificationPacket offp = new OfflineNotificationPacket();
6040 OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length];
6041 for (int i = 0; i < agentIDs.Length; i++)
6042 {
6043 OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
6044 onpbl.AgentID = agentIDs[i];
6045 offpb[i] = onpbl;
6046 }
6047 offp.AgentBlock = offpb;
6048 offp.Header.Reliable = true;
6049 OutPacket(offp, ThrottleOutPacketType.Task);
6050 }
6051
6052 public void SendSitResponse(LLUUID TargetID, LLVector3 OffsetPos, LLQuaternion SitOrientation, bool autopilot,
6053 LLVector3 CameraAtOffset, LLVector3 CameraEyeOffset, bool ForceMouseLook)
6054 {
6055 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
6056 avatarSitResponse.SitObject.ID = TargetID;
6057 if (CameraAtOffset != LLVector3.Zero)
6058 {
6059 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
6060 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
6061 }
6062 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
6063 avatarSitResponse.SitTransform.AutoPilot = autopilot;
6064 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
6065 avatarSitResponse.SitTransform.SitRotation = SitOrientation;
6066
6067 OutPacket(avatarSitResponse, ThrottleOutPacketType.Task);
6068 }
6069
6070 public void SendAdminResponse(LLUUID Token, uint AdminLevel)
6071 {
6072 GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket();
6073 GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock();
6074 GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock();
6075
6076 adb.AgentID = AgentId;
6077 adb.SessionID = SessionId; // More security
6078 gdb.GodLevel = (byte)AdminLevel;
6079 gdb.Token = Token;
6080 //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock;
6081 respondPacket.GrantData = gdb;
6082 respondPacket.AgentData = adb;
6083 OutPacket(respondPacket, ThrottleOutPacketType.Task);
6084 }
6085
6086 public void SendGroupMembership(GroupData[] GroupMembership)
6087 {
6088 AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket();
6089 AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length];
6090 for (int i = 0; i < GroupMembership.Length; i++)
6091 {
6092 AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock();
6093 Group.AcceptNotices = GroupMembership[i].AcceptNotices;
6094 Group.Contribution = GroupMembership[i].contribution;
6095 Group.GroupID = GroupMembership[i].GroupID;
6096 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
6097 Group.GroupName = Helpers.StringToField(GroupMembership[i].groupName);
6098 Group.GroupPowers = GroupMembership[i].groupPowers;
6099 Groups[i] = Group;
6100 Groupupdate.GroupData = Groups;
6101
6102 }
6103 Groupupdate.AgentData.AgentID = AgentId;
6104 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
6105
6106 }
6107 public void SendGroupNameReply(LLUUID groupLLUID, string GroupName)
6108 {
6109 UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket();
6110 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
6111 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
6112 uidnamebloc.ID = groupLLUID;
6113 uidnamebloc.GroupName = Helpers.StringToField(GroupName);
6114 uidnameblock[0] = uidnamebloc;
6115 pack.UUIDNameBlock = uidnameblock;
6116 OutPacket(pack, ThrottleOutPacketType.Task);
6117 }
6118
6119 public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
6120 {
6121 LandStatReplyPacket lsrp = new LandStatReplyPacket();
6122 // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock();
6123 LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length];
6124 //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
6125 // lsrepdb.
6126 lsrp.RequestData.ReportType = reportType;
6127 lsrp.RequestData.RequestFlags = requestFlags;
6128 lsrp.RequestData.TotalObjectCount = resultCount;
6129 for (int i = 0; i < lsrpia.Length; i++)
6130 {
6131 LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
6132 lsrepdb.LocationX = lsrpia[i].LocationX;
6133 lsrepdb.LocationY = lsrpia[i].LocationY;
6134 lsrepdb.LocationZ = lsrpia[i].LocationZ;
6135 lsrepdb.Score = lsrpia[i].Score;
6136 lsrepdb.TaskID = lsrpia[i].TaskID;
6137 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
6138 lsrepdb.TaskName = Helpers.StringToField(lsrpia[i].TaskName);
6139 lsrepdb.OwnerName = Helpers.StringToField(lsrpia[i].OwnerName);
6140 lsrepdba[i] = lsrepdb;
6141 }
6142 lsrp.ReportData = lsrepdba;
6143 OutPacket(lsrp, ThrottleOutPacketType.Task);
6144 }
6145
6146 public void SendScriptRunningReply(LLUUID objectID, LLUUID itemID, bool running)
6147 {
6148 ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket();
6149 scriptRunningReply.Script.ObjectID = objectID;
6150 scriptRunningReply.Script.ItemID = itemID;
6151 scriptRunningReply.Script.Running = running;
6152
6153 OutPacket(scriptRunningReply, ThrottleOutPacketType.Task);
6154 }
6155
6156 public void SendAsset(AssetRequestToClient req)
6157 {
6158
6159 //Console.WriteLine("sending asset " + req.RequestAssetID);
6160 TransferInfoPacket Transfer = new TransferInfoPacket();
6161 Transfer.TransferInfo.ChannelType = 2;
6162 Transfer.TransferInfo.Status = 0;
6163 Transfer.TransferInfo.TargetType = 0;
6164 if (req.AssetRequestSource == 2)
6165 {
6166 Transfer.TransferInfo.Params = new byte[20];
6167 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
6168 int assType = (int)req.AssetInf.Type;
6169 Array.Copy(Helpers.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
6170 }
6171 else if (req.AssetRequestSource == 3)
6172 {
6173 Transfer.TransferInfo.Params = req.Params;
6174 // Transfer.TransferInfo.Params = new byte[100];
6175 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
6176 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
6177 }
6178 Transfer.TransferInfo.Size = (int)req.AssetInf.Data.Length;
6179 Transfer.TransferInfo.TransferID = req.TransferRequestID;
6180 Transfer.Header.Zerocoded = true;
6181 OutPacket(Transfer, ThrottleOutPacketType.Asset);
6182
6183 if (req.NumPackets == 1)
6184 {
6185 TransferPacketPacket TransferPacket = new TransferPacketPacket();
6186 TransferPacket.TransferData.Packet = 0;
6187 TransferPacket.TransferData.ChannelType = 2;
6188 TransferPacket.TransferData.TransferID = req.TransferRequestID;
6189 TransferPacket.TransferData.Data = req.AssetInf.Data;
6190 TransferPacket.TransferData.Status = 1;
6191 TransferPacket.Header.Zerocoded = true;
6192 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
6193 }
6194 else
6195 {
6196 int processedLength = 0;
6197 // libsecondlife hardcodes 1500 as the maximum data chunk size
6198 int maxChunkSize = 1250;
6199 int packetNumber = 0;
6200
6201 while (processedLength < req.AssetInf.Data.Length)
6202 {
6203 TransferPacketPacket TransferPacket = new TransferPacketPacket();
6204 TransferPacket.TransferData.Packet = packetNumber;
6205 TransferPacket.TransferData.ChannelType = 2;
6206 TransferPacket.TransferData.TransferID = req.TransferRequestID;
6207
6208 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
6209 byte[] chunk = new byte[chunkSize];
6210 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
6211
6212 TransferPacket.TransferData.Data = chunk;
6213
6214 // 0 indicates more packets to come, 1 indicates last packet
6215 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
6216 {
6217 TransferPacket.TransferData.Status = 0;
6218 }
6219 else
6220 {
6221 TransferPacket.TransferData.Status = 1;
6222 }
6223 TransferPacket.Header.Zerocoded = true;
6224 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
6225
6226 processedLength += chunkSize;
6227 packetNumber++;
6228 }
6229 }
6230 }
6231
6232 public void SendTexture(AssetBase TextureAsset)
6233 {
6234
6235 }
6236
6237 public ClientInfo GetClientInfo()
6238 {
6239 ClientInfo info = m_PacketHandler.GetClientInfo();
6240
6241 info.userEP = this.m_userEndPoint;
6242 info.proxyEP = this.m_proxyEndPoint;
6243 info.agentcircuit = new sAgentCircuitData(RequestClientInfo());
6244
6245 return info;
6246 }
6247
6248 public void SetClientInfo(ClientInfo info)
6249 {
6250 m_PacketHandler.SetClientInfo(info);
6251 }
6252
6253 #region Media Parcel Members
6254
6255 public void SendParcelMediaCommand(uint flags, ParcelMediaCommandEnum command, float time)
6256 {
6257 ParcelMediaCommandMessagePacket commandMessagePacket = new ParcelMediaCommandMessagePacket();
6258 commandMessagePacket.CommandBlock.Flags = (uint) flags;
6259 commandMessagePacket.CommandBlock.Command =(uint) command;
6260 commandMessagePacket.CommandBlock.Time = time;
6261
6262 OutPacket(commandMessagePacket, ThrottleOutPacketType.Unknown);
6263 }
6264
6265 public void SendParcelMediaUpdate(string mediaUrl, LLUUID mediaTextureID,
6266 byte autoScale, string mediaType, string mediaDesc, int mediaWidth, int mediaHeight,
6267 byte mediaLoop)
6268 {
6269 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket();
6270 updatePacket.DataBlock.MediaURL = Helpers.StringToField(mediaUrl);
6271 updatePacket.DataBlock.MediaID = mediaTextureID;
6272 updatePacket.DataBlock.MediaAutoScale = autoScale;
6273
6274 updatePacket.DataBlockExtended.MediaType = Helpers.StringToField(mediaType);
6275 updatePacket.DataBlockExtended.MediaDesc = Helpers.StringToField(mediaDesc);
6276 updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
6277 updatePacket.DataBlockExtended.MediaWidth = mediaHeight;
6278 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
6279
6280 OutPacket(updatePacket, ThrottleOutPacketType.Unknown);
6281 }
6282
6283 #endregion
6284
6285
6286 #region Camera
6287
6288 public void SendSetFollowCamProperties (LLUUID objectID, SortedDictionary<int, float> parameters)
6289 {
6290 SetFollowCamPropertiesPacket packet = (SetFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.SetFollowCamProperties);
6291 packet.ObjectData.ObjectID = objectID;
6292 SetFollowCamPropertiesPacket.CameraPropertyBlock[] camPropBlock = new SetFollowCamPropertiesPacket.CameraPropertyBlock[parameters.Count];
6293 uint idx = 0;
6294 foreach(KeyValuePair<int, float> pair in parameters)
6295 {
6296 SetFollowCamPropertiesPacket.CameraPropertyBlock block = new SetFollowCamPropertiesPacket.CameraPropertyBlock();
6297 block.Type = pair.Key;
6298 block.Value = pair.Value;
6299
6300 camPropBlock[idx++] = block;
6301 }
6302 packet.CameraProperty = camPropBlock;
6303 OutPacket(packet, ThrottleOutPacketType.Task);
6304 }
6305
6306 public void SendClearFollowCamProperties (LLUUID objectID)
6307 {
6308 ClearFollowCamPropertiesPacket packet = (ClearFollowCamPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ClearFollowCamProperties);
6309 packet.ObjectData.ObjectID = objectID;
6310 OutPacket(packet, ThrottleOutPacketType.Task);
6311 }
6312
6313 #endregion
6314 }
6315}
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs
new file mode 100644
index 0000000..e1a9678
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketHandler.cs
@@ -0,0 +1,702 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Timers;
34using libsecondlife;
35using libsecondlife.Packets;
36using Timer = System.Timers.Timer;
37using OpenSim.Framework;
38
39namespace OpenSim.Region.ClientStack.LindenUDP
40{
41 public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes);
42 public delegate void PacketDrop(Packet pack, Object id);
43 public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, LLUUID agentID, ThrottleOutPacketType throttlePacketType);
44
45 public interface IPacketHandler
46 {
47 event PacketStats OnPacketStats;
48 event PacketDrop OnPacketDrop;
49 SynchronizeClientHandler SynchronizeClient { set; }
50
51 int PacketsReceived { get; }
52 int PacketsReceivedReported { get; }
53 uint SilenceLimit { get; set; }
54 uint DiscardTimeout { get; set; }
55 uint ResendTimeout { get; set; }
56
57 void InPacket(Packet packet);
58 void ProcessInPacket(Packet packet);
59 void OutPacket(Packet NewPack,
60 ThrottleOutPacketType throttlePacketType);
61 void OutPacket(Packet NewPack,
62 ThrottleOutPacketType throttlePacketType, Object id);
63 LLPacketQueue PacketQueue { get; }
64 void Stop();
65 void Flush();
66 void Clear();
67 ClientInfo GetClientInfo();
68 void SetClientInfo(ClientInfo info);
69 void AddImportantPacket(PacketType type);
70 void RemoveImportantPacket(PacketType type);
71 }
72
73 public class LLPacketHandler : IPacketHandler
74 {
75 // Packet queues
76 //
77 LLPacketQueue m_PacketQueue;
78
79 public LLPacketQueue PacketQueue
80 {
81 get { return m_PacketQueue; }
82 }
83
84 // Timer to run stats and acks on
85 //
86 private Timer m_AckTimer = new Timer(250);
87
88 // A list of the packets we haven't acked yet
89 //
90 private Dictionary<uint,uint> m_PendingAcks = new Dictionary<uint,uint>();
91 // Dictionary of the packets that need acks from the client.
92 //
93 private class AckData
94 {
95 public AckData(Packet packet, Object identifier)
96 {
97 Packet = packet;
98 Identifier = identifier;
99 }
100
101 public Packet Packet;
102 public Object Identifier;
103 }
104 private Dictionary<uint, AckData> m_NeedAck =
105 new Dictionary<uint, AckData>();
106
107 private uint m_ResendTimeout = 1000;
108
109 public uint ResendTimeout
110 {
111 get { return m_ResendTimeout; }
112 set { m_ResendTimeout = value; }
113 }
114
115 private uint m_DiscardTimeout = 8000;
116
117 public uint DiscardTimeout
118 {
119 get { return m_DiscardTimeout; }
120 set { m_DiscardTimeout = value; }
121 }
122
123 private uint m_SilenceLimit = 250;
124
125 public uint SilenceLimit
126 {
127 get { return m_SilenceLimit; }
128 set { m_SilenceLimit = value; }
129 }
130
131 private int m_LastAck = 0;
132
133 // Track duplicated packets. This uses a Dictionary. Both insertion
134 // and lookup are common operations and need to take advantage of
135 // the hashing. Expiration is less common and can be allowed the
136 // time for a linear scan.
137 //
138 private Dictionary<uint, int> m_DupeTracker =
139 new Dictionary<uint, int>();
140 //private uint m_DupeTrackerWindow = 30;
141
142 // Values for the SimStatsReporter
143 //
144 private int m_PacketsReceived = 0;
145 private int m_PacketsReceivedReported = 0;
146 private int m_PacketsSent = 0;
147 private int m_PacketsSentReported = 0;
148 private int m_UnackedBytes = 0;
149
150 public int PacketsReceived
151 {
152 get { return m_PacketsReceived; }
153 }
154
155 public int PacketsReceivedReported
156 {
157 get { return m_PacketsReceivedReported; }
158 }
159
160 // The client we are working for
161 //
162 private IClientAPI m_Client;
163
164 // Some events
165 //
166 public event PacketStats OnPacketStats;
167 public event PacketDrop OnPacketDrop;
168
169 private SynchronizeClientHandler m_SynchronizeClient = null;
170
171 public SynchronizeClientHandler SynchronizeClient
172 {
173 set { m_SynchronizeClient = value; }
174 }
175
176 // Packet sequencing
177 //
178 private uint m_Sequence = 0;
179 private object m_SequenceLock = new object();
180 private const int MAX_SEQUENCE = 0xFFFFFF;
181
182 List<PacketType> m_ImportantPackets = new List<PacketType>();
183
184 ////////////////////////////////////////////////////////////////////
185
186 // Constructors
187 //
188 public LLPacketHandler(IClientAPI client)
189 {
190 m_Client = client;
191
192 m_PacketQueue = new LLPacketQueue(client.AgentId);
193
194 m_AckTimer.Elapsed += AckTimerElapsed;
195 m_AckTimer.Start();
196 }
197
198 public void Stop()
199 {
200 m_AckTimer.Stop();
201
202 m_PacketQueue.Enqueue(null);
203 }
204
205 // Send one packet. This actually doesn't send anything, it queues
206 // it. Designed to be fire-and-forget, but there is an optional
207 // notifier.
208 //
209 public void OutPacket(
210 Packet packet, ThrottleOutPacketType throttlePacketType)
211 {
212 OutPacket(packet, throttlePacketType, null);
213 }
214
215 public void OutPacket(
216 Packet packet, ThrottleOutPacketType throttlePacketType,
217 Object id)
218 {
219 // Call the load balancer's hook. If this is not active here
220 // we defer to the sim server this client is actually connected
221 // to. Packet drop notifies will not be triggered in this
222 // configuration!
223 //
224 if ((m_SynchronizeClient != null) && (!m_Client.IsActive))
225 {
226 if (m_SynchronizeClient(m_Client.Scene, packet,
227 m_Client.AgentId, throttlePacketType))
228 return;
229 }
230
231 packet.Header.Sequence = NextPacketSequenceNumber();
232
233 lock (m_NeedAck)
234 {
235 DropResend(id);
236
237 AddAcks(ref packet);
238 QueuePacket(packet, throttlePacketType, id);
239
240 // We want to see that packet arrive if it's reliable
241 if (packet.Header.Reliable)
242 {
243 m_UnackedBytes += packet.ToBytes().Length;
244 m_NeedAck[packet.Header.Sequence] = new AckData(packet, id);
245 }
246 }
247 }
248
249 private void AddAcks(ref Packet packet)
250 {
251 // This packet type has shown to have issues with
252 // acks being appended to the payload, just don't send
253 // any with this packet type until libsl is fixed.
254 //
255 if(packet is libsecondlife.Packets.ViewerEffectPacket)
256 return;
257
258 // Add acks to outgoing packets
259 //
260 if (m_PendingAcks.Count > 0)
261 {
262 int count = m_PendingAcks.Count;
263 if (count > 10)
264 count = 10;
265 packet.Header.AckList = new uint[count];
266 packet.Header.AppendedAcks = true;
267
268 int i = 0;
269
270 foreach (uint ack in new List<uint>(m_PendingAcks.Keys))
271 {
272 packet.Header.AckList[i] = ack;
273 i++;
274 m_PendingAcks.Remove(ack);
275 if (i >= count) // That is how much space there is
276 break;
277 }
278 }
279 }
280
281 private void QueuePacket(
282 Packet packet, ThrottleOutPacketType throttlePacketType,
283 Object id)
284 {
285 packet.TickCount = System.Environment.TickCount;
286
287 LLQueItem item = new LLQueItem();
288 item.Packet = packet;
289 item.Incoming = false;
290 item.throttleType = throttlePacketType;
291 item.Identifier = id;
292
293 m_PacketQueue.Enqueue(item);
294 m_PacketsSent++;
295 }
296
297 private void ResendUnacked()
298 {
299 int now = System.Environment.TickCount;
300 int lastAck = m_LastAck;
301
302 // Unless we have received at least one ack, don't bother resending
303 // anything. There may not be a client there, don't clog up the
304 // pipes.
305 //
306 if (lastAck == 0)
307 return;
308
309 lock (m_NeedAck)
310 {
311 // Nothing to do
312 //
313 if (m_NeedAck.Count == 0)
314 return;
315
316 // If we have seen no acks in <SilenceLimit> s but are
317 // waiting for acks, then there may be no one listening.
318 // No need to resend anything. Keep it until it gets stale,
319 // then it will be dropped.
320 //
321 if ((((now - lastAck) > m_SilenceLimit) &&
322 m_NeedAck.Count > 0) || m_NeedAck.Count == 0)
323 {
324 return;
325 }
326
327 foreach (AckData data in new List<AckData>(m_NeedAck.Values))
328 {
329 Packet packet = data.Packet;
330
331 // Packets this old get resent
332 //
333 if ((now - packet.TickCount) > m_ResendTimeout)
334 {
335 // Resend the packet. Set the packet's tick count to
336 // now, and keep it marked as resent.
337 //
338 packet.Header.Resent = true;
339 QueuePacket(packet, ThrottleOutPacketType.Resend,
340 data.Identifier);
341 }
342
343 // The discard logic
344 // If the packet is in the queue for <DiscardTimeout> s
345 // without having been processed, then we have clogged
346 // pipes. Most likely, the client is gone
347 // Drop the packets
348 //
349 if ((now - packet.TickCount) > m_DiscardTimeout)
350 {
351 if (!m_ImportantPackets.Contains(packet.Type))
352 m_NeedAck.Remove(packet.Header.Sequence);
353
354 TriggerOnPacketDrop(packet, data.Identifier);
355
356 continue;
357 }
358 }
359 }
360 }
361
362 // Send the pending packet acks to the client
363 // Will send blocks of acks for up to 250 packets
364 //
365 private void SendAcks()
366 {
367 lock (m_NeedAck)
368 {
369 if (m_PendingAcks.Count == 0)
370 return;
371
372 PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
373
374 // The case of equality is more common than one might think,
375 // because this function will be called unconditionally when
376 // the counter reaches 250. So there is a good chance another
377 // packet with 250 blocks exists.
378 //
379 if (acks.Packets == null ||
380 acks.Packets.Length != m_PendingAcks.Count)
381 acks.Packets = new PacketAckPacket.PacketsBlock[m_PendingAcks.Count];
382 int i = 0;
383 foreach (uint ack in new List<uint>(m_PendingAcks.Keys))
384 {
385 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
386 acks.Packets[i].ID = ack;
387
388 m_PendingAcks.Remove(ack);
389 i++;
390 }
391
392 acks.Header.Reliable = false;
393 OutPacket(acks, ThrottleOutPacketType.Unknown);
394 }
395 }
396
397 // Queue a packet ack. It will be sent either after 250 acks are
398 // queued, or when the timer fires.
399 //
400 private void AckPacket(Packet packet)
401 {
402 lock (m_NeedAck)
403 {
404 if (m_PendingAcks.Count < 250)
405 {
406 if (!m_PendingAcks.ContainsKey(packet.Header.Sequence))
407 m_PendingAcks.Add(packet.Header.Sequence,
408 packet.Header.Sequence);
409 return;
410 }
411 }
412
413 SendAcks();
414
415 lock (m_NeedAck)
416 {
417 // If this is still full we have a truly exceptional
418 // condition (means, can't happen)
419 //
420 if (m_PendingAcks.Count < 250)
421 {
422 if (!m_PendingAcks.ContainsKey(packet.Header.Sequence))
423 m_PendingAcks.Add(packet.Header.Sequence,
424 packet.Header.Sequence);
425 return;
426 }
427 }
428 }
429
430 // When the timer elapses, send the pending acks, trigger resends
431 // and report all the stats.
432 //
433 private void AckTimerElapsed(object sender, ElapsedEventArgs ea)
434 {
435 SendAcks();
436 ResendUnacked();
437 SendPacketStats();
438 }
439
440 // Push out pachet counts for the sim status reporter
441 //
442 private void SendPacketStats()
443 {
444 PacketStats handlerPacketStats = OnPacketStats;
445 if (handlerPacketStats != null)
446 {
447 handlerPacketStats(
448 m_PacketsReceived - m_PacketsReceivedReported,
449 m_PacketsSent - m_PacketsSentReported,
450 m_UnackedBytes);
451
452 m_PacketsReceivedReported = m_PacketsReceived;
453 m_PacketsSentReported = m_PacketsSent;
454 }
455 }
456
457 // We can't keep an unlimited record of dupes. This will prune the
458 // dictionary by age.
459 //
460// private void PruneDupeTracker()
461// {
462// lock (m_DupeTracker)
463// {
464// Dictionary<uint, int> packs =
465// new Dictionary<uint, int>(m_DupeTracker);
466//
467// foreach (uint pack in packs.Keys)
468// {
469// if (Util.UnixTimeSinceEpoch() - m_DupeTracker[pack] >
470// m_DupeTrackerWindow)
471// m_DupeTracker.Remove(pack);
472// }
473// }
474// }
475
476 public void InPacket(Packet packet)
477 {
478 if (packet == null)
479 return;
480
481 // If this client is on another partial instance, no need
482 // to handle packets
483 //
484 if (!m_Client.IsActive && packet.Type != PacketType.LogoutRequest)
485 {
486 PacketPool.Instance.ReturnPacket(packet);
487 return;
488 }
489
490 // Any packet can have some packet acks in the header.
491 // Process them here
492 //
493 if (packet.Header.AppendedAcks)
494 {
495 foreach (uint id in packet.Header.AckList)
496 {
497 ProcessAck(id);
498 }
499 }
500
501 // When too many acks are needed to be sent, the client sends
502 // a packet consisting of acks only
503 //
504 if (packet.Type == PacketType.PacketAck)
505 {
506 PacketAckPacket ackPacket = (PacketAckPacket)packet;
507
508 foreach (PacketAckPacket.PacketsBlock block in
509 ackPacket.Packets)
510 {
511 ProcessAck(block.ID);
512 }
513
514 PacketPool.Instance.ReturnPacket(packet);
515 return;
516 }
517 else if (packet.Type == PacketType.StartPingCheck)
518 {
519 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
520 CompletePingCheckPacket endPing = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck);
521
522 endPing.PingID.PingID = startPing.PingID.PingID;
523 OutPacket(endPing, ThrottleOutPacketType.Task);
524 }
525 else
526 {
527 LLQueItem item = new LLQueItem();
528 item.Packet = packet;
529 item.Incoming = true;
530 m_PacketQueue.Enqueue(item);
531 }
532 }
533
534 public void ProcessInPacket(Packet packet)
535 {
536 // Always ack the packet!
537 //
538 if (packet.Header.Reliable)
539 AckPacket(packet);
540
541 if (packet.Type != PacketType.AgentUpdate)
542 m_PacketsReceived++;
543
544 // Check for duplicate packets.. packets that the client is
545 // resending because it didn't receive our ack
546 //
547 lock (m_DupeTracker)
548 {
549 if (m_DupeTracker.ContainsKey(packet.Header.Sequence))
550 return;
551
552 m_DupeTracker.Add(packet.Header.Sequence,
553 Util.UnixTimeSinceEpoch());
554 }
555
556 m_Client.ProcessInPacket(packet);
557 }
558
559 public void Flush()
560 {
561 m_PacketQueue.Flush();
562 }
563
564 public void Clear()
565 {
566 m_NeedAck.Clear();
567 m_PendingAcks.Clear();
568 m_Sequence += 1000000;
569 }
570
571 private void ProcessAck(uint id)
572 {
573 AckData data;
574 Packet packet;
575
576 lock (m_NeedAck)
577 {
578 if (!m_NeedAck.TryGetValue(id, out data))
579 return;
580
581 packet = data.Packet;
582
583 m_NeedAck.Remove(id);
584 m_UnackedBytes -= packet.ToBytes().Length;
585
586 m_LastAck = System.Environment.TickCount;
587 }
588 }
589
590 // Allocate packet sequence numbers in a threadsave manner
591 //
592 protected uint NextPacketSequenceNumber()
593 {
594 // Set the sequence number
595 uint seq = 1;
596 lock (m_SequenceLock)
597 {
598 if (m_Sequence >= MAX_SEQUENCE)
599 {
600 m_Sequence = 1;
601 }
602 else
603 {
604 m_Sequence++;
605 }
606 seq = m_Sequence;
607 }
608 return seq;
609 }
610
611 public ClientInfo GetClientInfo()
612 {
613 ClientInfo info = new ClientInfo();
614 info.pendingAcks = m_PendingAcks;
615 info.needAck = new Dictionary<uint, byte[]>();
616
617 lock (m_NeedAck)
618 {
619 foreach (uint key in m_NeedAck.Keys)
620 info.needAck.Add(key, m_NeedAck[key].Packet.ToBytes());
621 }
622
623 LLQueItem[] queitems = m_PacketQueue.GetQueueArray();
624
625 for (int i = 0; i < queitems.Length; i++)
626 {
627 if (queitems[i].Incoming == false)
628 info.out_packets.Add(queitems[i].Packet.ToBytes());
629 }
630
631 info.sequence = m_Sequence;
632
633 return info;
634 }
635
636 public void SetClientInfo(ClientInfo info)
637 {
638 m_PendingAcks = info.pendingAcks;
639 m_NeedAck = new Dictionary<uint, AckData>();
640
641 Packet packet = null;
642 int packetEnd = 0;
643 byte[] zero = new byte[3000];
644
645 foreach (uint key in info.needAck.Keys)
646 {
647 byte[] buff = info.needAck[key];
648 packetEnd = buff.Length - 1;
649
650 try
651 {
652 packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero);
653 }
654 catch (Exception)
655 {
656 }
657
658 m_NeedAck.Add(key, new AckData(packet, null));
659 }
660
661 m_Sequence = info.sequence;
662 }
663
664 public void AddImportantPacket(PacketType type)
665 {
666 if (m_ImportantPackets.Contains(type))
667 return;
668
669 m_ImportantPackets.Add(type);
670 }
671
672 public void RemoveImportantPacket(PacketType type)
673 {
674 if (!m_ImportantPackets.Contains(type))
675 return;
676
677 m_ImportantPackets.Remove(type);
678 }
679
680 private void DropResend(Object id)
681 {
682 foreach (AckData data in new List<AckData>(m_NeedAck.Values))
683 {
684 if (data.Identifier != null && data.Identifier == id)
685 {
686 m_NeedAck.Remove(data.Packet.Header.Sequence);
687 return;
688 }
689 }
690 }
691
692 private void TriggerOnPacketDrop(Packet packet, Object id)
693 {
694 PacketDrop handlerPacketDrop = OnPacketDrop;
695
696 if (handlerPacketDrop == null)
697 return;
698
699 handlerPacketDrop(packet, id);
700 }
701 }
702}
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs
new file mode 100644
index 0000000..aed9465
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketQueue.cs
@@ -0,0 +1,567 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System;
29using System.Collections.Generic;
30using System.Threading;
31using System.Timers;
32using libsecondlife;
33using libsecondlife.Packets;
34using OpenSim.Framework;
35using OpenSim.Framework.Statistics;
36using OpenSim.Framework.Statistics.Interfaces;
37using Timer=System.Timers.Timer;
38
39namespace OpenSim.Region.ClientStack.LindenUDP
40{
41 public class LLPacketQueue : IPullStatsProvider
42 {
43 private static readonly log4net.ILog m_log
44 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45
46 private bool m_enabled = true;
47
48 private BlockingQueue<LLQueItem> SendQueue;
49
50 private Queue<LLQueItem> IncomingPacketQueue;
51 private Queue<LLQueItem> OutgoingPacketQueue;
52 private Queue<LLQueItem> ResendOutgoingPacketQueue;
53 private Queue<LLQueItem> LandOutgoingPacketQueue;
54 private Queue<LLQueItem> WindOutgoingPacketQueue;
55 private Queue<LLQueItem> CloudOutgoingPacketQueue;
56 private Queue<LLQueItem> TaskOutgoingPacketQueue;
57 private Queue<LLQueItem> TaskLowpriorityPacketQueue;
58 private Queue<LLQueItem> TextureOutgoingPacketQueue;
59 private Queue<LLQueItem> AssetOutgoingPacketQueue;
60
61 // private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
62 // private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
63
64 // All throttle times and number of bytes are calculated by dividing by this value
65 // This value also determines how many times per throttletimems the timer will run
66 // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds
67
68 private int throttleTimeDivisor = 7;
69
70 private int throttletimems = 1000;
71
72 private LLPacketThrottle ResendThrottle;
73 private LLPacketThrottle LandThrottle;
74 private LLPacketThrottle WindThrottle;
75 private LLPacketThrottle CloudThrottle;
76 private LLPacketThrottle TaskThrottle;
77 private LLPacketThrottle AssetThrottle;
78 private LLPacketThrottle TextureThrottle;
79 private LLPacketThrottle TotalThrottle;
80
81 // private long LastThrottle;
82 // private long ThrottleInterval;
83 private Timer throttleTimer;
84
85 private LLUUID m_agentId;
86
87 public LLPacketQueue(LLUUID agentId)
88 {
89 // While working on this, the BlockingQueue had me fooled for a bit.
90 // The Blocking queue causes the thread to stop until there's something
91 // in it to process. it's an on-purpose threadlock though because
92 // without it, the clientloop will suck up all sim resources.
93
94 SendQueue = new BlockingQueue<LLQueItem>();
95
96 IncomingPacketQueue = new Queue<LLQueItem>();
97 OutgoingPacketQueue = new Queue<LLQueItem>();
98 ResendOutgoingPacketQueue = new Queue<LLQueItem>();
99 LandOutgoingPacketQueue = new Queue<LLQueItem>();
100 WindOutgoingPacketQueue = new Queue<LLQueItem>();
101 CloudOutgoingPacketQueue = new Queue<LLQueItem>();
102 TaskOutgoingPacketQueue = new Queue<LLQueItem>();
103 TaskLowpriorityPacketQueue = new Queue<LLQueItem>();
104 TextureOutgoingPacketQueue = new Queue<LLQueItem>();
105 AssetOutgoingPacketQueue = new Queue<LLQueItem>();
106
107
108 // Set up the throttle classes (min, max, current) in bytes
109 ResendThrottle = new LLPacketThrottle(5000, 100000, 16000);
110 LandThrottle = new LLPacketThrottle(1000, 100000, 2000);
111 WindThrottle = new LLPacketThrottle(0, 100000, 0);
112 CloudThrottle = new LLPacketThrottle(0, 100000, 0);
113 TaskThrottle = new LLPacketThrottle(1000, 800000, 3000);
114 AssetThrottle = new LLPacketThrottle(1000, 800000, 1000);
115 TextureThrottle = new LLPacketThrottle(1000, 800000, 4000);
116 // Total Throttle trumps all
117 // Number of bytes allowed to go out per second. (256kbps per client)
118 TotalThrottle = new LLPacketThrottle(0, 1500000, 28000);
119
120 throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor));
121 throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed);
122 throttleTimer.Start();
123
124 // TIMERS needed for this
125 // LastThrottle = DateTime.Now.Ticks;
126 // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor);
127
128 m_agentId = agentId;
129
130 if (StatsManager.SimExtraStats != null)
131 {
132 StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this);
133 }
134 }
135
136 /* STANDARD QUEUE MANIPULATION INTERFACES */
137
138
139 public void Enqueue(LLQueItem item)
140 {
141 if (!m_enabled)
142 {
143 return;
144 }
145 // We could micro lock, but that will tend to actually
146 // probably be worse than just synchronizing on SendQueue
147
148 if (item == null)
149 {
150 SendQueue.Enqueue(item);
151 return;
152 }
153
154 if (item.Incoming)
155 {
156 SendQueue.PriorityEnqueue(item);
157 return;
158 }
159
160 lock (this)
161 {
162 switch (item.throttleType)
163 {
164 case ThrottleOutPacketType.Resend:
165 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item);
166 break;
167 case ThrottleOutPacketType.Texture:
168 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item);
169 break;
170 case ThrottleOutPacketType.Task:
171 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item);
172 break;
173 case ThrottleOutPacketType.LowpriorityTask:
174 ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item);
175 break;
176 case ThrottleOutPacketType.Land:
177 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item);
178 break;
179 case ThrottleOutPacketType.Asset:
180 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item);
181 break;
182 case ThrottleOutPacketType.Cloud:
183 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item);
184 break;
185 case ThrottleOutPacketType.Wind:
186 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item);
187 break;
188
189 default:
190 // Acknowledgements and other such stuff should go directly to the blocking Queue
191 // Throttling them may and likely 'will' be problematic
192 SendQueue.PriorityEnqueue(item);
193 break;
194 }
195 }
196 }
197
198 public LLQueItem Dequeue()
199 {
200 return SendQueue.Dequeue();
201 }
202
203 public void Flush()
204 {
205 lock (this)
206 {
207 while (PacketsWaiting())
208 {
209 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
210 if (ResendOutgoingPacketQueue.Count > 0)
211 {
212 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue());
213 }
214 if (LandOutgoingPacketQueue.Count > 0)
215 {
216 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue());
217 }
218 if (WindOutgoingPacketQueue.Count > 0)
219 {
220 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue());
221 }
222 if (CloudOutgoingPacketQueue.Count > 0)
223 {
224 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue());
225 }
226 if (TaskOutgoingPacketQueue.Count > 0)
227 {
228 SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue());
229 }
230 if (TaskLowpriorityPacketQueue.Count > 0)
231 {
232 SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue());
233 }
234 if (TextureOutgoingPacketQueue.Count > 0)
235 {
236 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue());
237 }
238 if (AssetOutgoingPacketQueue.Count > 0)
239 {
240 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue());
241 }
242 }
243 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
244 }
245 }
246
247 public void Close()
248 {
249 Flush();
250
251 m_enabled = false;
252 throttleTimer.Stop();
253
254 if (StatsManager.SimExtraStats != null)
255 {
256 StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId);
257 }
258 }
259
260 private void ResetCounters()
261 {
262 ResendThrottle.Reset();
263 LandThrottle.Reset();
264 WindThrottle.Reset();
265 CloudThrottle.Reset();
266 TaskThrottle.Reset();
267 AssetThrottle.Reset();
268 TextureThrottle.Reset();
269 TotalThrottle.Reset();
270 }
271
272 private bool PacketsWaiting()
273 {
274 return (ResendOutgoingPacketQueue.Count > 0 ||
275 LandOutgoingPacketQueue.Count > 0 ||
276 WindOutgoingPacketQueue.Count > 0 ||
277 CloudOutgoingPacketQueue.Count > 0 ||
278 TaskOutgoingPacketQueue.Count > 0 ||
279 TaskLowpriorityPacketQueue.Count > 0 ||
280 AssetOutgoingPacketQueue.Count > 0 ||
281 TextureOutgoingPacketQueue.Count > 0);
282 }
283
284 public void ProcessThrottle()
285 {
286 // I was considering this.. Will an event fire if the thread it's on is blocked?
287
288 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
289 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
290 // so This'll pick up about around the right time.
291
292 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
293 int throttleLoops = 0;
294
295 // We're going to dequeue all of the saved up packets until
296 // we've hit the throttle limit or there's no more packets to send
297 lock (this)
298 {
299 ResetCounters();
300 // m_log.Info("[THROTTLE]: Entering Throttle");
301 while (TotalThrottle.UnderLimit() && PacketsWaiting() &&
302 (throttleLoops <= MaxThrottleLoops))
303 {
304 throttleLoops++;
305 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
306 if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0)
307 {
308 LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue();
309
310 SendQueue.Enqueue(qpack);
311 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
312 ResendThrottle.Add(qpack.Packet.ToBytes().Length);
313 }
314 if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0)
315 {
316 LLQueItem qpack = LandOutgoingPacketQueue.Dequeue();
317
318 SendQueue.Enqueue(qpack);
319 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
320 LandThrottle.Add(qpack.Packet.ToBytes().Length);
321 }
322 if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0)
323 {
324 LLQueItem qpack = WindOutgoingPacketQueue.Dequeue();
325
326 SendQueue.Enqueue(qpack);
327 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
328 WindThrottle.Add(qpack.Packet.ToBytes().Length);
329 }
330 if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0)
331 {
332 LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue();
333
334 SendQueue.Enqueue(qpack);
335 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
336 CloudThrottle.Add(qpack.Packet.ToBytes().Length);
337 }
338 if (TaskThrottle.UnderLimit() && (TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0))
339 {
340 LLQueItem qpack;
341 if (TaskOutgoingPacketQueue.Count > 0)
342 {
343 qpack = TaskOutgoingPacketQueue.Dequeue();
344 SendQueue.PriorityEnqueue(qpack);
345 }
346 else
347 {
348 qpack = TaskLowpriorityPacketQueue.Dequeue();
349 SendQueue.Enqueue(qpack);
350 }
351 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
352 TaskThrottle.Add(qpack.Packet.ToBytes().Length);
353 }
354 if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0)
355 {
356 LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue();
357
358 SendQueue.Enqueue(qpack);
359 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
360 TextureThrottle.Add(qpack.Packet.ToBytes().Length);
361 }
362 if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0)
363 {
364 LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue();
365
366 SendQueue.Enqueue(qpack);
367 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
368 AssetThrottle.Add(qpack.Packet.ToBytes().Length);
369 }
370 }
371 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
372 }
373 }
374
375 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
376 {
377 // just to change the signature, and that ProcessThrottle
378 // will be used elsewhere possibly
379 ProcessThrottle();
380 }
381
382 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item)
383 {
384 // The idea.. is if the packet throttle queues are empty
385 // and the client is under throttle for the type. Queue
386 // it up directly. This basically short cuts having to
387 // wait for the timer to fire to put things into the
388 // output queue
389
390 if ((q.Count == 0) && (throttle.UnderLimit()))
391 {
392 Monitor.Enter(this);
393 throttle.Add(item.Packet.ToBytes().Length);
394 TotalThrottle.Add(item.Packet.ToBytes().Length);
395 SendQueue.Enqueue(item);
396 Monitor.Pulse(this);
397 Monitor.Exit(this);
398 }
399 else
400 {
401 q.Enqueue(item);
402 }
403 }
404
405
406 private static int ScaleThrottle(int value, int curmax, int newmax)
407 {
408 return (value / curmax) * newmax;
409 }
410
411 public byte[] GetThrottlesPacked(float multiplier)
412 {
413 int singlefloat = 4;
414 float tResend = ResendThrottle.Throttle*multiplier;
415 float tLand = LandThrottle.Throttle*multiplier;
416 float tWind = WindThrottle.Throttle*multiplier;
417 float tCloud = CloudThrottle.Throttle*multiplier;
418 float tTask = TaskThrottle.Throttle*multiplier;
419 float tTexture = TextureThrottle.Throttle*multiplier;
420 float tAsset = AssetThrottle.Throttle*multiplier;
421
422 byte[] throttles = new byte[singlefloat*7];
423 int i = 0;
424 Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat);
425 i++;
426 Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat);
427 i++;
428 Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat);
429 i++;
430 Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat);
431 i++;
432 Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat);
433 i++;
434 Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat);
435 i++;
436 Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat);
437
438 return throttles;
439 }
440
441 public void SetThrottleFromClient(byte[] throttle)
442 {
443 // From mantis http://opensimulator.org/mantis/view.php?id=1374
444 // it appears that sometimes we are receiving empty throttle byte arrays.
445 // TODO: Investigate this behaviour
446 if (throttle.Length == 0)
447 {
448 m_log.Warn("[PACKET QUEUE]: SetThrottleFromClient unexpectedly received a throttle byte array containing no elements!");
449 return;
450 }
451
452 int tResend = -1;
453 int tLand = -1;
454 int tWind = -1;
455 int tCloud = -1;
456 int tTask = -1;
457 int tTexture = -1;
458 int tAsset = -1;
459 int tall = -1;
460 int singlefloat = 4;
461
462 //Agent Throttle Block contains 7 single floatingpoint values.
463 int j = 0;
464
465 // Some Systems may be big endian...
466 // it might be smart to do this check more often...
467 if (!BitConverter.IsLittleEndian)
468 for (int i = 0; i < 7; i++)
469 Array.Reverse(throttle, j + i*singlefloat, singlefloat);
470
471 // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_
472 // bytes
473 // Convert to integer, since.. the full fp space isn't used.
474 tResend = (int) BitConverter.ToSingle(throttle, j);
475 j += singlefloat;
476 tLand = (int) BitConverter.ToSingle(throttle, j);
477 j += singlefloat;
478 tWind = (int) BitConverter.ToSingle(throttle, j);
479 j += singlefloat;
480 tCloud = (int) BitConverter.ToSingle(throttle, j);
481 j += singlefloat;
482 tTask = (int) BitConverter.ToSingle(throttle, j);
483 j += singlefloat;
484 tTexture = (int) BitConverter.ToSingle(throttle, j);
485 j += singlefloat;
486 tAsset = (int) BitConverter.ToSingle(throttle, j);
487
488 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
489 /*
490 m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbytes=" + tResend +
491 " landbytes=" + tLand +
492 " windbytes=" + tWind +
493 " cloudbytes=" + tCloud +
494 " taskbytes=" + tTask +
495 " texturebytes=" + tTexture +
496 " Assetbytes=" + tAsset +
497 " Allbytes=" + tall);
498 */
499
500 // Total Sanity
501 // Make sure that the client sent sane total values.
502
503 // If the client didn't send acceptable values....
504 // Scale the clients values down until they are acceptable.
505
506 if (tall <= TotalThrottle.Max)
507 {
508 ResendThrottle.Throttle = tResend;
509 LandThrottle.Throttle = tLand;
510 WindThrottle.Throttle = tWind;
511 CloudThrottle.Throttle = tCloud;
512 TaskThrottle.Throttle = tTask;
513 TextureThrottle.Throttle = tTexture;
514 AssetThrottle.Throttle = tAsset;
515 TotalThrottle.Throttle = tall;
516 }
517// else if (tall < 1)
518// {
519// // client is stupid, penalize him by minning everything
520// ResendThrottle.Throttle = ResendThrottle.Min;
521// LandThrottle.Throttle = LandThrottle.Min;
522// WindThrottle.Throttle = WindThrottle.Min;
523// CloudThrottle.Throttle = CloudThrottle.Min;
524// TaskThrottle.Throttle = TaskThrottle.Min;
525// TextureThrottle.Throttle = TextureThrottle.Min;
526// AssetThrottle.Throttle = AssetThrottle.Min;
527// TotalThrottle.Throttle = TotalThrottle.Min;
528// }
529 else
530 {
531 // we're over so figure out percentages and use those
532 ResendThrottle.Throttle = tResend;
533
534 LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max);
535 WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max);
536 CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max);
537 TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max);
538 TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max);
539 AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max);
540 TotalThrottle.Throttle = TotalThrottle.Max;
541 }
542 // effectively wiggling the slider causes things reset
543// ResetCounters(); // DO NOT reset, better to send less for one period than more
544 }
545
546 // See IPullStatsProvider
547 public string GetStats()
548 {
549 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
550 SendQueue.Count(),
551 IncomingPacketQueue.Count,
552 OutgoingPacketQueue.Count,
553 ResendOutgoingPacketQueue.Count,
554 LandOutgoingPacketQueue.Count,
555 WindOutgoingPacketQueue.Count,
556 CloudOutgoingPacketQueue.Count,
557 TaskOutgoingPacketQueue.Count,
558 TextureOutgoingPacketQueue.Count,
559 AssetOutgoingPacketQueue.Count);
560 }
561
562 public LLQueItem[] GetQueueArray()
563 {
564 return SendQueue.GetQueueArray();
565 }
566 }
567}
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs
new file mode 100644
index 0000000..2a3f2e1
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketServer.cs
@@ -0,0 +1,150 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System.Net;
29using System.Net.Sockets;
30using libsecondlife;
31using libsecondlife.Packets;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications.Cache;
34using OpenSim.Region.ClientStack.LindenUDP;
35
36namespace OpenSim.Region.ClientStack.LindenUDP
37{
38 public class LLPacketServer
39 {
40 //private static readonly log4net.ILog m_log
41 // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
42
43 private readonly LLClientStackNetworkHandler m_networkHandler;
44 private IScene m_scene;
45
46 //private readonly ClientManager m_clientManager = new ClientManager();
47 //public ClientManager ClientManager
48 //{
49 // get { return m_clientManager; }
50 //}
51
52 public LLPacketServer(LLClientStackNetworkHandler networkHandler)
53 {
54 m_networkHandler = networkHandler;
55 m_networkHandler.RegisterPacketServer(this);
56 }
57
58 public IScene LocalScene
59 {
60 set { m_scene = value; }
61 }
62
63 /// <summary>
64 ///
65 /// </summary>
66 /// <param name="circuitCode"></param>
67 /// <param name="packet"></param>
68 public virtual void InPacket(uint circuitCode, Packet packet)
69 {
70 m_scene.ClientManager.InPacket(circuitCode, packet);
71 }
72
73 protected virtual IClientAPI CreateNewClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack,
74 ClientManager clientManager, IScene scene, AssetCache assetCache,
75 LLPacketServer packServer, AgentCircuitManager authenSessions,
76 LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP)
77 {
78 return
79 new LLClientView(remoteEP, scene, assetCache, packServer, authenSessions, agentId, sessionId, circuitCode, proxyEP);
80 }
81
82 public virtual bool AddNewClient(EndPoint epSender, UseCircuitCodePacket useCircuit, AssetCache assetCache,
83 AgentCircuitManager authenticateSessionsClass, EndPoint proxyEP)
84 {
85 IClientAPI newuser;
86
87 if (m_scene.ClientManager.TryGetClient(useCircuit.CircuitCode.Code, out newuser))
88 {
89 return false;
90 }
91 else
92 {
93 newuser = CreateNewClient(epSender, useCircuit, m_scene.ClientManager, m_scene, assetCache, this,
94 authenticateSessionsClass, useCircuit.CircuitCode.ID,
95 useCircuit.CircuitCode.SessionID, useCircuit.CircuitCode.Code, proxyEP);
96
97 m_scene.ClientManager.Add(useCircuit.CircuitCode.Code, newuser);
98
99 newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
100 newuser.OnLogout += LogoutHandler;
101 newuser.OnConnectionClosed += CloseClient;
102
103 return true;
104 }
105 }
106
107 public void LogoutHandler(IClientAPI client)
108 {
109 client.SendLogoutPacket();
110
111 CloseClient(client);
112 }
113
114 /// <summary>
115 ///
116 /// </summary>
117 /// <param name="buffer"></param>
118 /// <param name="size"></param>
119 /// <param name="flags"></param>
120 /// <param name="circuitcode"></param>
121 public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
122 {
123 m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
124 }
125
126 /// <summary>
127 ///
128 /// </summary>
129 /// <param name="circuitcode"></param>
130 public virtual void CloseCircuit(uint circuitcode)
131 {
132 m_networkHandler.RemoveClientCircuit(circuitcode);
133
134 //m_scene.ClientManager.CloseAllAgents(circuitcode);
135 }
136
137 /// <summary>
138 /// Completely close down the given client.
139 /// </summary>
140 /// <param name="client"></param>
141 public virtual void CloseClient(IClientAPI client)
142 {
143 //m_log.Info("PacketServer:CloseClient()");
144
145 CloseCircuit(client.CircuitCode);
146 m_scene.ClientManager.Remove(client.CircuitCode);
147 client.Close(false);
148 }
149 }
150} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs
new file mode 100644
index 0000000..b9f4594
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLPacketThrottle.cs
@@ -0,0 +1,93 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28namespace OpenSim.Region.ClientStack.LindenUDP
29{
30 public class LLPacketThrottle
31 {
32 private readonly int m_maxAllowableThrottle;
33 private readonly int m_minAllowableThrottle;
34 private int m_currentThrottle;
35 private const int m_throttleTimeDivisor = 7;
36 private int m_currentBytesSent;
37
38 public LLPacketThrottle(int Min, int Max, int Throttle)
39 {
40 m_maxAllowableThrottle = Max;
41 m_minAllowableThrottle = Min;
42 m_currentThrottle = Throttle;
43 m_currentBytesSent = 0;
44 }
45
46 public void Reset()
47 {
48 m_currentBytesSent = 0;
49 }
50
51 public bool UnderLimit()
52 {
53 return (m_currentBytesSent < (m_currentThrottle/m_throttleTimeDivisor));
54 }
55
56 public int Add(int bytes)
57 {
58 m_currentBytesSent += bytes;
59 return m_currentBytesSent;
60 }
61
62 // Properties
63 public int Max
64 {
65 get { return m_maxAllowableThrottle; }
66 }
67
68 public int Min
69 {
70 get { return m_minAllowableThrottle; }
71 }
72
73 public int Throttle
74 {
75 get { return m_currentThrottle; }
76 set
77 {
78 if (value > m_maxAllowableThrottle)
79 {
80 m_currentThrottle = m_maxAllowableThrottle;
81 }
82 else if (value < m_minAllowableThrottle)
83 {
84 m_currentThrottle = m_minAllowableThrottle;
85 }
86 else
87 {
88 m_currentThrottle = value;
89 }
90 }
91 }
92 }
93} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs
new file mode 100644
index 0000000..e836dd7
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLQueItem.cs
@@ -0,0 +1,45 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System;
29using libsecondlife.Packets;
30using OpenSim.Framework;
31
32namespace OpenSim.Region.ClientStack.LindenUDP
33{
34 public class LLQueItem
35 {
36 public LLQueItem()
37 {
38 }
39
40 public Packet Packet;
41 public bool Incoming;
42 public ThrottleOutPacketType throttleType;
43 public Object Identifier;
44 }
45}
diff --git a/OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs
new file mode 100644
index 0000000..41a3197
--- /dev/null
+++ b/OpenSim/Region/ClientStack/FunSLUDP/LLUDPServer.cs
@@ -0,0 +1,545 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using libsecondlife.Packets;
35using log4net;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications.Cache;
38using OpenSim.Region.ClientStack.LindenUDP;
39using OpenSim.Region.Environment.Scenes;
40
41namespace OpenSim.Region.ClientStack.LindenUDP
42{
43 public class LLUDPServer : LLClientStackNetworkHandler, IClientNetworkServer
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
48
49 //public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
50 public Hashtable clientCircuits_reverse = Hashtable.Synchronized(new Hashtable());
51
52 protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>();
53 private Socket m_socket;
54 protected IPEndPoint ServerIncoming;
55 protected byte[] RecvBuffer = new byte[4096];
56 protected byte[] ZeroBuffer = new byte[8192];
57 protected IPEndPoint ipeSender;
58 protected EndPoint epSender;
59 protected EndPoint epProxy;
60 protected int proxyPortOffset;
61 protected AsyncCallback ReceivedData;
62 protected LLPacketServer m_packetServer;
63 protected Location m_location;
64
65 protected uint listenPort;
66 protected bool Allow_Alternate_Port;
67 protected IPAddress listenIP = IPAddress.Parse("0.0.0.0");
68 protected IScene m_localScene;
69 protected AssetCache m_assetCache;
70 protected AgentCircuitManager m_authenticateSessionsClass;
71
72 public LLPacketServer PacketServer
73 {
74 get { return m_packetServer; }
75 set { m_packetServer = value; }
76 }
77
78 public IScene LocalScene
79 {
80 set
81 {
82 m_localScene = value;
83 m_packetServer.LocalScene = m_localScene;
84 m_location = new Location(m_localScene.RegionInfo.RegionHandle);
85 }
86 }
87
88 public ulong RegionHandle
89 {
90 get { return m_location.RegionHandle; }
91 }
92
93 Socket IClientNetworkServer.Server
94 {
95 get { return m_socket; }
96 }
97
98 public bool HandlesRegion(Location x)
99 {
100 return x == m_location;
101 }
102
103 public void AddScene(Scene x)
104 {
105 LocalScene = x;
106 }
107
108 public void Start()
109 {
110 ServerListener();
111 }
112
113 public void Stop()
114 {
115 m_socket.Close();
116 }
117
118 public LLUDPServer()
119 {
120 }
121
122 public LLUDPServer(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
123 {
124 Initialise(_listenIP, ref port, proxyPortOffset, allow_alternate_port, assetCache, authenticateClass);
125 }
126
127 public void Initialise(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
128 {
129 this.proxyPortOffset = proxyPortOffset;
130 listenPort = (uint) (port + proxyPortOffset);
131 listenIP = _listenIP;
132 Allow_Alternate_Port = allow_alternate_port;
133 m_assetCache = assetCache;
134 m_authenticateSessionsClass = authenticateClass;
135 CreatePacketServer();
136
137 // Return new port
138 // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered.
139 // So the option allow_alternate_ports="true" was added to default.xml
140 port = (uint)(listenPort - proxyPortOffset);
141 }
142
143 protected virtual void CreatePacketServer()
144 {
145 new LLPacketServer(this);
146 }
147
148 protected virtual void OnReceivedData(IAsyncResult result)
149 {
150 ipeSender = new IPEndPoint(listenIP, 0);
151 epSender = (EndPoint) ipeSender;
152 Packet packet = null;
153
154 int numBytes = 1;
155
156 try
157 {
158 numBytes = m_socket.EndReceiveFrom(result, ref epSender);
159 }
160 catch (SocketException e)
161 {
162 // TODO : Actually only handle those states that we have control over, re-throw everything else,
163 // TODO: implement cases as we encounter them.
164 //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString());
165 switch (e.SocketErrorCode)
166 {
167 case SocketError.AlreadyInProgress:
168 case SocketError.NetworkReset:
169 case SocketError.ConnectionReset:
170 try
171 {
172 CloseEndPoint(epSender);
173 }
174 catch (Exception a)
175 {
176 m_log.Info("[UDPSERVER]: " + a.ToString());
177 }
178 try
179 {
180 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
181 ReceivedData, null);
182
183 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
184 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
185 // This will happen over and over until we've gone through all packets
186 // sent to and from this particular user.
187 // Stupid I know..
188 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
189 }
190 catch (SocketException)
191 {
192 }
193 break;
194 default:
195 try
196 {
197 CloseEndPoint(epSender);
198 }
199 catch (Exception)
200 {
201 //m_log.Info("[UDPSERVER]" + a.ToString());
202 }
203 try
204 {
205 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
206 ReceivedData, null);
207
208 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
209 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
210 // This will happen over and over until we've gone through all packets
211 // sent to and from this particular user.
212 // Stupid I know..
213 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
214 }
215 catch (SocketException e2)
216 {
217 m_log.Error("[UDPSERVER]: " + e2.ToString());
218 }
219
220 // Here's some reference code! :D
221 // Shutdown and restart the UDP listener! hehe
222 // Shiny
223
224 //Server.Shutdown(SocketShutdown.Both);
225 //CloseEndPoint(epSender);
226 //ServerListener();
227 break;
228 }
229
230 //return;
231 }
232 catch (ObjectDisposedException e)
233 {
234 m_log.Debug("[UDPSERVER]: " + e.ToString());
235 try
236 {
237 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
238 ReceivedData, null);
239
240 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
241 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
242 // This will happen over and over until we've gone through all packets
243 // sent to and from this particular user.
244 // Stupid I know..
245 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
246 }
247
248 catch (SocketException e2)
249 {
250 m_log.Error("[UDPSERVER]: " + e2.ToString());
251 }
252 catch (ObjectDisposedException)
253 {
254 }
255 //return;
256 }
257
258 //System.Console.WriteLine("UDPServer : recieved message from {0}", epSender.ToString());
259 epProxy = epSender;
260 if (proxyPortOffset != 0)
261 {
262 epSender = PacketPool.DecodeProxyMessage(RecvBuffer, ref numBytes);
263 }
264
265 int packetEnd = numBytes - 1;
266
267 try
268 {
269 packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
270 }
271 catch (Exception e)
272 {
273 m_log.Debug("[UDPSERVER]: " + e.ToString());
274 }
275
276 try
277 {
278 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
279 }
280 catch (SocketException)
281 {
282 try
283 {
284 CloseEndPoint(epSender);
285 }
286 catch (Exception a)
287 {
288 m_log.Info("[UDPSERVER]: " + a.ToString());
289 }
290 try
291 {
292 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
293 ReceivedData, null);
294
295 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
296 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
297 // This will happen over and over until we've gone through all packets
298 // sent to and from this particular user.
299 // Stupid I know..
300 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
301 }
302 catch (SocketException e5)
303 {
304 m_log.Error("[UDPSERVER]: " + e5.ToString());
305 }
306 }
307 catch (ObjectDisposedException)
308 {
309 }
310
311 if (packet != null)
312 {
313 try
314 {
315 // do we already have a circuit for this endpoint
316 uint circuit;
317
318 bool ret = false;
319 lock (clientCircuits)
320 {
321 ret = clientCircuits.TryGetValue(epSender, out circuit);
322 }
323 if (ret)
324 {
325 //if so then send packet to the packetserver
326 //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
327 m_packetServer.InPacket(circuit, packet);
328 }
329 else if (packet.Type == PacketType.UseCircuitCode)
330 {
331 // new client
332 m_log.Debug("[UDPSERVER]: Adding New Client");
333 AddNewClient(packet);
334
335 UseCircuitCodePacket p = (UseCircuitCodePacket)packet;
336
337 // Ack the first UseCircuitCode packet
338 PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
339 // TODO: don't create new blocks if recycling an old packet
340 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
341 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
342 ack_it.Packets[0].ID = packet.Header.Sequence;
343 ack_it.Header.Reliable = false;
344 SendPacketTo(ack_it.ToBytes(),ack_it.ToBytes().Length,SocketFlags.None,p.CircuitCode.Code);
345 }
346 }
347 catch (Exception)
348 {
349 m_log.Error("[UDPSERVER]: Exception in processing packet.");
350 m_log.Debug("[UDPSERVER]: Adding New Client");
351 try
352 {
353 AddNewClient(packet);
354 }
355 catch (Exception e3)
356 {
357 m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
358 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
359 ReceivedData, null);
360 }
361 }
362 }
363
364 }
365
366 private void CloseEndPoint(EndPoint sender)
367 {
368 uint circuit;
369 lock (clientCircuits)
370 {
371 if (clientCircuits.TryGetValue(sender, out circuit))
372 {
373 m_packetServer.CloseCircuit(circuit);
374 }
375 }
376 }
377
378 protected virtual void AddNewClient(Packet packet)
379 {
380 //Slave regions don't accept new clients
381 if (m_localScene.Region_Status != RegionStatus.SlaveScene)
382 {
383 if (!(packet is UseCircuitCodePacket))
384 return;
385
386 UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
387 lock (clientCircuits)
388 {
389 if (!clientCircuits.ContainsKey(epSender))
390 clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
391 else
392 m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
393 }
394
395 // This doesn't need locking as it's synchronized data
396 if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
397 clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
398 else
399 m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
400
401
402 lock (proxyCircuits)
403 {
404 if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
405 proxyCircuits.Add(useCircuit.CircuitCode.Code, epProxy);
406 else
407 m_log.Error("[UDPSERVER]: proxyCircuits already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
408 }
409
410 PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass, epProxy);
411 }
412 PacketPool.Instance.ReturnPacket(packet);
413 }
414
415 public void ServerListener()
416 {
417 uint newPort = listenPort;
418 m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");
419
420 ServerIncoming = new IPEndPoint(listenIP, (int)newPort);
421 m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
422 m_socket.Bind(ServerIncoming);
423 // Add flags to the UDP socket to prevent "Socket forcibly closed by host"
424 // uint IOC_IN = 0x80000000;
425 // uint IOC_VENDOR = 0x18000000;
426 // uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
427 // TODO: this apparently works in .NET but not in Mono, need to sort out the right flags here.
428 // m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
429
430 listenPort = newPort;
431
432 m_log.Info("[SERVER]: UDP socket bound, getting ready to listen");
433
434 ipeSender = new IPEndPoint(listenIP, 0);
435 epSender = (EndPoint)ipeSender;
436 ReceivedData = new AsyncCallback(OnReceivedData);
437 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
438
439 m_log.Info("[SERVER]: Listening on port " + newPort);
440 }
441
442 public virtual void RegisterPacketServer(LLPacketServer server)
443 {
444 m_packetServer = server;
445 }
446
447 public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
448 //EndPoint packetSender)
449 {
450 // find the endpoint for this circuit
451 EndPoint sendto = null;
452 try {
453 sendto = (EndPoint)clientCircuits_reverse[circuitcode];
454 } catch {
455 // Exceptions here mean there is no circuit
456 m_log.Warn("Circuit not found, not sending packet");
457 return;
458 }
459
460 if (sendto != null)
461 {
462 //we found the endpoint so send the packet to it
463 if (proxyPortOffset != 0)
464 {
465 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString());
466 PacketPool.EncodeProxyMessage(buffer, ref size, sendto);
467 m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]);
468 }
469 else
470 {
471 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString());
472 m_socket.SendTo(buffer, size, flags, sendto);
473 }
474 }
475 }
476
477 public virtual void RemoveClientCircuit(uint circuitcode)
478 {
479 EndPoint sendto = null;
480 if (clientCircuits_reverse.Contains(circuitcode))
481 {
482 sendto = (EndPoint)clientCircuits_reverse[circuitcode];
483
484 clientCircuits_reverse.Remove(circuitcode);
485
486 lock (clientCircuits)
487 {
488 if (sendto != null)
489 {
490 clientCircuits.Remove(sendto);
491 }
492 else
493 {
494 m_log.DebugFormat(
495 "[UDPSERVER]: endpoint for circuit code {0} in RemoveClientCircuit() was unexpectedly null!", circuitcode);
496 }
497 }
498 lock (proxyCircuits)
499 {
500 proxyCircuits.Remove(circuitcode);
501 }
502 }
503 }
504
505 public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP)
506 {
507 //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient");
508
509 UseCircuitCodePacket useCircuit = new UseCircuitCodePacket();
510 useCircuit.CircuitCode.Code = circuit.circuitcode;
511 useCircuit.CircuitCode.ID = circuit.AgentID;
512 useCircuit.CircuitCode.SessionID = circuit.SessionID;
513
514 lock (clientCircuits)
515 {
516 if (!clientCircuits.ContainsKey(userEP))
517 clientCircuits.Add(userEP, useCircuit.CircuitCode.Code);
518 else
519 m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
520 }
521
522 // This data structure is synchronized, so we don't need the lock
523 if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
524 clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP);
525 else
526 m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
527
528 lock (proxyCircuits)
529 {
530 if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
531 {
532 proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
533 }
534 else
535 {
536 // re-set proxy endpoint
537 proxyCircuits.Remove(useCircuit.CircuitCode.Code);
538 proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
539 }
540 }
541
542 PacketServer.AddNewClient(userEP, useCircuit, m_assetCache, m_authenticateSessionsClass, proxyEP);
543 }
544 }
545}
diff --git a/prebuild.xml b/prebuild.xml
index 400ec00..4cd6207 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -888,6 +888,42 @@
888 </Files> 888 </Files>
889 </Project> 889 </Project>
890 890
891 <Project name="OpenSim.Region.ClientStack.FunSLUDP" path="OpenSim/Region/ClientStack/FunSLUDP" type="Library">
892 <Configuration name="Debug">
893 <Options>
894 <OutputPath>../../../../bin/</OutputPath>
895 </Options>
896 </Configuration>
897 <Configuration name="Release">
898 <Options>
899 <OutputPath>../../../../bin/</OutputPath>
900 </Options>
901 </Configuration>
902
903 <ReferencePath>../../../../bin/</ReferencePath>
904 <Reference name="System" localCopy="false"/>
905 <Reference name="System.Xml"/>
906 <Reference name="libsecondlife.dll"/>
907 <Reference name="Axiom.MathLib.dll"/>
908 <Reference name="OpenSim.Region.Environment"/>
909 <Reference name="OpenSim.Framework"/>
910 <Reference name="OpenSim.Data"/>
911 <Reference name="OpenSim.Framework.Servers"/>
912 <Reference name="OpenSim.Framework.Console"/>
913 <Reference name="OpenSim.Framework.Communications"/>
914 <Reference name="OpenSim.Framework.Statistics"/>
915 <Reference name="OpenSim.Region.ClientStack"/>
916 <Reference name="OpenSim.Region.Communications.Local"/>
917 <Reference name="OpenSim.Region.Physics.Manager"/>
918 <Reference name="XMLRPC.dll"/>
919 <Reference name="Nini.dll" />
920 <Reference name="log4net.dll"/>
921
922 <Files>
923 <Match pattern="*.cs" recurse="true"/>
924 </Files>
925 </Project>
926
891 <!-- Datastore Plugins --> 927 <!-- Datastore Plugins -->
892 <Project name="OpenSim.Data.Null" path="OpenSim/Data/Null" type="Library"> 928 <Project name="OpenSim.Data.Null" path="OpenSim/Data/Null" type="Library">
893 <Configuration name="Debug"> 929 <Configuration name="Debug">