aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP
diff options
context:
space:
mode:
authorAdam Frisby2008-05-02 16:41:08 +0000
committerAdam Frisby2008-05-02 16:41:08 +0000
commit29b8c84ceaaeca80bfa9c0bfc8c31e421e39ef71 (patch)
tree848ce119d9b87bc186c20b08cc604de50a872b31 /OpenSim/Region/ClientStack/LindenUDP
parent* Refactored ClientView into LLClientView. Removed all direct references to U... (diff)
downloadopensim-SC-29b8c84ceaaeca80bfa9c0bfc8c31e421e39ef71.zip
opensim-SC-29b8c84ceaaeca80bfa9c0bfc8c31e421e39ef71.tar.gz
opensim-SC-29b8c84ceaaeca80bfa9c0bfc8c31e421e39ef71.tar.bz2
opensim-SC-29b8c84ceaaeca80bfa9c0bfc8c31e421e39ef71.tar.xz
* Commit 2/3 - Please dont attempt to update to this revision until all 3 are in.
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientStackNetworkHandler.cs38
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs4927
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs532
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs150
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs93
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs43
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs499
7 files changed, 6282 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientStackNetworkHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientStackNetworkHandler.cs
new file mode 100644
index 0000000..c1989a5
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/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/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
new file mode 100644
index 0000000..5d45d99
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -0,0 +1,4927 @@
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.Region.ClientStack.LindenUDP;
43using OpenSim.Region.Environment.Scenes;
44using Timer=System.Timers.Timer;
45
46namespace OpenSim.Region.ClientStack.LindenUDP
47{
48 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
49
50 /// <summary>
51 /// Handles new client connections
52 /// Constructor takes a single Packet and authenticates everything
53 /// </summary>
54 public class LLClientView : IClientAPI
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 // ~ClientView()
59 // {
60 // m_log.Info("[CLIENTVIEW]: Destructor called");
61 // }
62
63 /* static variables */
64 public static TerrainManager TerrainManager;
65
66 public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, LLUUID agentID, ThrottleOutPacketType throttlePacketType);
67 public static SynchronizeClientHandler SynchronizeClient = null;
68 /* private variables */
69 private readonly LLUUID m_sessionId;
70 private LLUUID m_secureSessionId = LLUUID.Zero;
71 //private AgentAssetUpload UploadAssets;
72 private int m_debug = 0;
73 private readonly AssetCache m_assetCache;
74 // private InventoryCache m_inventoryCache;
75 private int m_cachedTextureSerial = 0;
76 private Timer m_clientPingTimer;
77
78 private bool m_clientBlocked = false;
79
80 private int m_packetsReceived = 0;
81 private int m_lastPacketsReceivedSentToScene = 0;
82 private int m_unAckedBytes = 0;
83
84 private int m_packetsSent = 0;
85 private int m_lastPacketsSentSentToScene = 0;
86
87 private int m_probesWithNoIngressPackets = 0;
88 private int m_lastPacketsReceived = 0;
89 private byte[] ZeroOutBuffer = new byte[4096];
90
91 private readonly LLUUID m_agentId;
92 private readonly uint m_circuitCode;
93 private int m_moneyBalance;
94
95 private int m_animationSequenceNumber = 1;
96
97 private byte[] m_channelVersion = Helpers.StringToField("OpenSimulator 0.5"); // Dummy value needed by libSL
98
99 /* protected variables */
100
101 protected static Dictionary<PacketType, PacketMethod> PacketHandlers =
102 new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
103
104 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
105
106 protected IScene m_scene;
107 protected AgentCircuitManager m_authenticateSessionsHandler;
108
109 protected LLPacketQueue m_packetQueue;
110
111 protected Dictionary<uint, uint> m_pendingAcks = new Dictionary<uint, uint>();
112 protected Dictionary<uint, Packet> m_needAck = new Dictionary<uint, Packet>();
113
114 protected Timer m_ackTimer;
115 protected uint m_sequence = 0;
116 protected object m_sequenceLock = new object();
117 protected const int MAX_APPENDED_ACKS = 10;
118 protected const int RESEND_TIMEOUT = 4000;
119 protected const int MAX_SEQUENCE = 0xFFFFFF;
120 protected LLPacketServer m_networkServer;
121
122 /* public variables */
123 protected string m_firstName;
124 protected string m_lastName;
125 protected Thread m_clientThread;
126 protected LLVector3 m_startpos;
127 protected EndPoint m_userEndPoint;
128 protected EndPoint m_proxyEndPoint;
129
130 /* Instantiated Designated Event Delegates */
131 //- used so we don't create new objects for each incoming packet and then toss it out later */
132
133 private RequestAvatarProperties handlerRequestAvatarProperties = null; //OnRequestAvatarProperties;
134 private UpdateAvatarProperties handlerUpdateAvatarProperties = null; // OnUpdateAvatarProperties;
135 private ChatFromViewer handlerChatFromViewer = null; //OnChatFromViewer;
136 private ChatFromViewer handlerChatFromViewer2 = null; //OnChatFromViewer;
137 private ImprovedInstantMessage handlerInstantMessage = null; //OnInstantMessage;
138 private FriendActionDelegate handlerApproveFriendRequest = null; //OnApproveFriendRequest;
139 private FriendshipTermination handlerTerminateFriendship = null; //OnTerminateFriendship;
140 private RezObject handlerRezObject = null; //OnRezObject;
141 private GenericCall4 handlerDeRezObject = null; //OnDeRezObject;
142 private ModifyTerrain handlerModifyTerrain = null;
143 private Action<IClientAPI> handlerRegionHandShakeReply = null; //OnRegionHandShakeReply;
144 private GenericCall2 handlerRequestWearables = null; //OnRequestWearables;
145 private Action<IClientAPI> handlerRequestAvatarsData = null; //OnRequestAvatarsData;
146 private SetAppearance handlerSetAppearance = null; //OnSetAppearance;
147 private AvatarNowWearing handlerAvatarNowWearing = null; //OnAvatarNowWearing;
148 private RezSingleAttachmentFromInv handlerRezSingleAttachment = null; //OnRezSingleAttachmentFromInv;
149 private UUIDNameRequest handlerDetachAttachmentIntoInv = null; // Detach attachment!
150 private ObjectAttach handlerObjectAttach = null; //OnObjectAttach;
151 private SetAlwaysRun handlerSetAlwaysRun = null; //OnSetAlwaysRun;
152 private GenericCall2 handlerCompleteMovementToRegion = null; //OnCompleteMovementToRegion;
153 private UpdateAgent handlerAgentUpdate = null; //OnAgentUpdate;
154 private StartAnim handlerStartAnim = null;
155 private StopAnim handlerStopAnim = null;
156 private AgentRequestSit handlerAgentRequestSit = null; //OnAgentRequestSit;
157 private AgentSit handlerAgentSit = null; //OnAgentSit;
158 private AvatarPickerRequest handlerAvatarPickerRequest = null; //OnAvatarPickerRequest;
159 private FetchInventory handlerAgentDataUpdateRequest = null; //OnAgentDataUpdateRequest;
160 private FetchInventory handlerUserInfoRequest = null; //OnUserInfoRequest;
161 private TeleportLocationRequest handlerSetStartLocationRequest = null; //OnSetStartLocationRequest;
162 private TeleportLandmarkRequest handlerTeleportLandmarkRequest = null; //OnTeleportLandmarkRequest;
163 private LinkObjects handlerLinkObjects = null; //OnLinkObjects;
164 private DelinkObjects handlerDelinkObjects = null; //OnDelinkObjects;
165 private AddNewPrim handlerAddPrim = null; //OnAddPrim;
166 private UpdateShape handlerUpdatePrimShape = null; //null;
167 private ObjectExtraParams handlerUpdateExtraParams = null; //OnUpdateExtraParams;
168 private ObjectDuplicate handlerObjectDuplicate = null;
169 private ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null;
170 private ObjectSelect handlerObjectSelect = null;
171 private ObjectDeselect handlerObjectDeselect = null;
172 private ObjectIncludeInSearch handlerObjectIncludeInSearch = null;
173 private UpdatePrimFlags handlerUpdatePrimFlags = null; //OnUpdatePrimFlags;
174 private UpdatePrimTexture handlerUpdatePrimTexture = null;
175 private UpdateVector handlerGrabObject = null; //OnGrabObject;
176 private MoveObject handlerGrabUpdate = null; //OnGrabUpdate;
177 private ObjectSelect handlerDeGrabObject = null; //OnDeGrabObject;
178 private GenericCall7 handlerObjectDescription = null;
179 private GenericCall7 handlerObjectName = null;
180 private ObjectPermissions handlerObjectPermissions = null;
181 private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = null; //OnRequestObjectPropertiesFamily;
182 private TextureRequest handlerTextureRequest = null;
183 private UDPAssetUploadRequest handlerAssetUploadRequest = null; //OnAssetUploadRequest;
184 private RequestXfer handlerRequestXfer = null; //OnRequestXfer;
185 private XferReceive handlerXferReceive = null; //OnXferReceive;
186 private ConfirmXfer handlerConfirmXfer = null; //OnConfirmXfer;
187 private CreateInventoryFolder handlerCreateInventoryFolder = null; //OnCreateNewInventoryFolder;
188 private UpdateInventoryFolder handlerUpdateInventoryFolder = null;
189 private MoveInventoryFolder handlerMoveInventoryFolder = null;
190 private CreateNewInventoryItem handlerCreateNewInventoryItem = null; //OnCreateNewInventoryItem;
191 private FetchInventory handlerFetchInventory = null;
192 private FetchInventoryDescendents handlerFetchInventoryDescendents = null; //OnFetchInventoryDescendents;
193 private PurgeInventoryDescendents handlerPurgeInventoryDescendents = null; //OnPurgeInventoryDescendents;
194 private UpdateInventoryItem handlerUpdateInventoryItem = null;
195 private CopyInventoryItem handlerCopyInventoryItem = null;
196 private MoveInventoryItem handlerMoveInventoryItem = null;
197 private RemoveInventoryItem handlerRemoveInventoryItem = null;
198 private RemoveInventoryFolder handlerRemoveInventoryFolder = null;
199 private RequestTaskInventory handlerRequestTaskInventory = null; //OnRequestTaskInventory;
200 private UpdateTaskInventory handlerUpdateTaskInventory = null; //OnUpdateTaskInventory;
201 private MoveTaskInventory handlerMoveTaskItem = null;
202 private RemoveTaskInventory handlerRemoveTaskItem = null; //OnRemoveTaskItem;
203 private RezScript handlerRezScript = null; //OnRezScript;
204 private RequestMapBlocks handlerRequestMapBlocks = null; //OnRequestMapBlocks;
205 private RequestMapName handlerMapNameRequest = null; //OnMapNameRequest;
206 private TeleportLocationRequest handlerTeleportLocationRequest = null; //OnTeleportLocationRequest;
207 private MoneyBalanceRequest handlerMoneyBalanceRequest = null; //OnMoneyBalanceRequest;
208 private UUIDNameRequest handlerNameRequest = null;
209 private ParcelAccessListRequest handlerParcelAccessListRequest = null; //OnParcelAccessListRequest;
210 private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = null; //OnParcelAccessListUpdateRequest;
211 private ParcelPropertiesRequest handlerParcelPropertiesRequest = null; //OnParcelPropertiesRequest;
212 private ParcelDivideRequest handlerParcelDivideRequest = null; //OnParcelDivideRequest;
213 private ParcelJoinRequest handlerParcelJoinRequest = null; //OnParcelJoinRequest;
214 private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = null; //OnParcelPropertiesUpdateRequest;
215 private ParcelSelectObjects handlerParcelSelectObjects = null; //OnParcelSelectObjects;
216 private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = null; //OnParcelObjectOwnerRequest;
217 private EstateOwnerMessageRequest handlerEstateOwnerMessage = null; //OnEstateOwnerMessage;
218 private RegionInfoRequest handlerRegionInfoRequest = null; //OnRegionInfoRequest;
219 private EstateCovenantRequest handlerEstateCovenantRequest = null; //OnEstateCovenantRequest;
220 private RequestGodlikePowers handlerReqGodlikePowers = null; //OnRequestGodlikePowers;
221 private GodKickUser handlerGodKickUser = null; //OnGodKickUser;
222 private ViewerEffectEventHandler handlerViewerEffect = null; //OnViewerEffect;
223 private Action<IClientAPI> handlerLogout = null; //OnLogout;
224 private MoneyTransferRequest handlerMoneyTransferRequest = null; //OnMoneyTransferRequest;
225 private ParcelBuy handlerParcelBuy = null;
226 private EconomyDataRequest handlerEconomoyDataRequest = null;
227
228 private UpdateVector handlerUpdatePrimSinglePosition = null; //OnUpdatePrimSinglePosition;
229 private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = null; //OnUpdatePrimSingleRotation;
230 private UpdateVector handlerUpdatePrimScale = null; //OnUpdatePrimScale;
231 private UpdateVector handlerUpdatePrimGroupScale = null; //OnUpdateGroupScale;
232 private UpdateVector handlerUpdateVector = null; //OnUpdatePrimGroupPosition;
233 private UpdatePrimRotation handlerUpdatePrimRotation = null; //OnUpdatePrimGroupRotation;
234 private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = null; //OnUpdatePrimGroupMouseRotation;
235 private PacketStats handlerPacketStats = null; // OnPacketStats;#
236 private RequestAsset handlerRequestAsset = null; // OnRequestAsset;
237 private UUIDNameRequest handlerTeleportHomeRequest = null;
238
239 private ScriptAnswer handlerScriptAnswer = null;
240 private RequestPayPrice handlerRequestPayPrice = null;
241 private ObjectDeselect handlerObjectDetach = null;
242 private AgentSit handlerOnUndo = null;
243
244 /* Properties */
245
246 public LLUUID SecureSessionId
247 {
248 get { return m_secureSessionId; }
249 }
250
251 public IScene Scene
252 {
253 get { return m_scene; }
254 }
255
256 public LLUUID SessionId
257 {
258 get { return m_sessionId; }
259 }
260
261 public LLVector3 StartPos
262 {
263 get { return m_startpos; }
264 set { m_startpos = value; }
265 }
266
267 public LLUUID AgentId
268 {
269 get { return m_agentId; }
270 }
271
272 /// <summary>
273 /// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
274 /// </summary>
275 public bool ChildAgentStatus()
276 {
277 return m_scene.PresenceChildStatus(AgentId);
278 }
279
280 /// <summary>
281 /// First name of the agent/avatar represented by the client
282 /// </summary>
283 public string FirstName
284 {
285 get { return m_firstName; }
286 }
287
288 /// <summary>
289 /// Last name of the agent/avatar represented by the client
290 /// </summary>
291 public string LastName
292 {
293 get { return m_lastName; }
294 }
295
296 /// <summary>
297 /// Full name of the client (first name and last name)
298 /// </summary>
299 public string Name
300 {
301 get { return FirstName + " " + LastName; }
302 }
303
304 public uint CircuitCode
305 {
306 get { return m_circuitCode; }
307 }
308
309 public int MoneyBalance
310 {
311 get { return m_moneyBalance; }
312 }
313
314 public int NextAnimationSequenceNumber
315 {
316 get { return m_animationSequenceNumber++; }
317 }
318
319 /* METHODS */
320
321 public LLClientView(EndPoint remoteEP, IScene scene, AssetCache assetCache, LLPacketServer packServer,
322 AgentCircuitManager authenSessions, LLUUID agentId, LLUUID sessionId, uint circuitCode, EndPoint proxyEP)
323 {
324 m_moneyBalance = 1000;
325
326 m_channelVersion = Helpers.StringToField(scene.GetSimulatorVersion());
327
328 m_scene = scene;
329 m_assetCache = assetCache;
330
331 m_networkServer = packServer;
332 // m_inventoryCache = inventoryCache;
333 m_authenticateSessionsHandler = authenSessions;
334
335 m_log.Info("[CLIENT]: Started up new client thread to handle incoming request");
336
337 m_agentId = agentId;
338 m_sessionId = sessionId;
339 m_circuitCode = circuitCode;
340
341 m_userEndPoint = remoteEP;
342 m_proxyEndPoint = proxyEP;
343
344 m_startpos = m_authenticateSessionsHandler.GetPosition(circuitCode);
345
346 // While working on this, the BlockingQueue had me fooled for a bit.
347 // The Blocking queue causes the thread to stop until there's something
348 // in it to process. It's an on-purpose threadlock though because
349 // without it, the clientloop will suck up all sim resources.
350
351 m_packetQueue = new LLPacketQueue(agentId);
352
353 RegisterLocalPacketHandlers();
354
355 m_clientThread = new Thread(new ThreadStart(AuthUser));
356 m_clientThread.Name = "ClientThread";
357 m_clientThread.IsBackground = true;
358 m_clientThread.Start();
359 ThreadTracker.Add(m_clientThread);
360 }
361
362 public void SetDebug(int newDebug)
363 {
364 m_debug = newDebug;
365 }
366
367 # region Client Methods
368
369 private void CloseCleanup(bool shutdownCircuit)
370 {
371 m_scene.RemoveClient(AgentId);
372
373 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
374 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
375
376 // Send the STOP packet
377 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
378 OutPacket(disable, ThrottleOutPacketType.Unknown);
379
380 m_packetQueue.Close();
381
382 Thread.Sleep(2000);
383
384
385 // Shut down timers
386 m_ackTimer.Stop();
387 m_clientPingTimer.Stop();
388
389 // This is just to give the client a reasonable chance of
390 // flushing out all it's packets. There should probably
391 // be a better mechanism here
392
393 // We can't reach into other scenes and close the connection
394 // We need to do this over grid communications
395 //m_scene.CloseAllAgents(CircuitCode);
396
397 // If we're not shutting down the circuit, then this is the last time we'll go here.
398 // If we are shutting down the circuit, the UDP Server will come back here with
399 // ShutDownCircuit = false
400 if (!(shutdownCircuit))
401 {
402 GC.Collect();
403 m_clientThread.Abort();
404 }
405 }
406
407 /// <summary>
408 /// Close down the client view. This *must* be the last method called, since the last #
409 /// statement of CloseCleanup() aborts the thread.
410 /// </summary>
411 /// <param name="shutdownCircuit"></param>
412 public void Close(bool shutdownCircuit)
413 {
414 // Pull Client out of Region
415 m_log.Info("[CLIENT]: Close has been called");
416 m_packetQueue.Flush();
417
418 //raiseevent on the packet server to Shutdown the circuit
419 if (shutdownCircuit)
420 {
421 OnConnectionClosed(this);
422 }
423
424 CloseCleanup(shutdownCircuit);
425 }
426
427 public void Kick(string message)
428 {
429 if (!ChildAgentStatus())
430 {
431 KickUserPacket kupack = (KickUserPacket)PacketPool.Instance.GetPacket(PacketType.KickUser);
432 kupack.UserInfo.AgentID = AgentId;
433 kupack.UserInfo.SessionID = SessionId;
434 kupack.TargetBlock.TargetIP = (uint)0;
435 kupack.TargetBlock.TargetPort = (ushort)0;
436 kupack.UserInfo.Reason = Helpers.StringToField(message);
437 OutPacket(kupack, ThrottleOutPacketType.Task);
438 }
439 }
440
441 public void Stop()
442 {
443 // Shut down timers
444 m_ackTimer.Stop();
445 m_clientPingTimer.Stop();
446 }
447
448 public void Restart()
449 {
450 // re-construct
451 m_pendingAcks = new Dictionary<uint, uint>();
452 m_needAck = new Dictionary<uint, Packet>();
453 m_sequence += 1000000;
454
455 m_ackTimer = new Timer(750);
456 m_ackTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
457 m_ackTimer.Start();
458
459 m_clientPingTimer = new Timer(5000);
460 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity);
461 m_clientPingTimer.Enabled = true;
462 }
463
464 public void Terminate()
465 {
466 // disable blocking queue
467 m_packetQueue.Enqueue(null);
468
469 // wait for thread stoped
470 m_clientThread.Join();
471
472 // delete circuit code
473 m_networkServer.CloseClient(this);
474 }
475
476 #endregion
477
478 # region Packet Handling
479
480 public static bool AddPacketHandler(PacketType packetType, PacketMethod handler)
481 {
482 bool result = false;
483 lock (PacketHandlers)
484 {
485 if (!PacketHandlers.ContainsKey(packetType))
486 {
487 PacketHandlers.Add(packetType, handler);
488 result = true;
489 }
490 }
491 return result;
492 }
493
494 public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler)
495 {
496 bool result = false;
497 lock (m_packetHandlers)
498 {
499 if (!m_packetHandlers.ContainsKey(packetType))
500 {
501 m_packetHandlers.Add(packetType, handler);
502 result = true;
503 }
504 }
505 return result;
506 }
507
508 /// <summary>
509 /// Try to process a packet using registered packet handlers
510 /// </summary>
511 /// <param name="packet"></param>
512 /// <returns>True if a handler was found which successfully processed the packet.</returns>
513 protected virtual bool ProcessPacketMethod(Packet packet)
514 {
515 bool result = false;
516 bool found = false;
517 PacketMethod method;
518 if (m_packetHandlers.TryGetValue(packet.Type, out method))
519 {
520 //there is a local handler for this packet type
521 result = method(this, packet);
522 }
523 else
524 {
525 //there is not a local handler so see if there is a Global handler
526 lock (PacketHandlers)
527 {
528 found = PacketHandlers.TryGetValue(packet.Type, out method);
529 }
530 if (found)
531 {
532 result = method(this, packet);
533 }
534 }
535 return result;
536 }
537
538 protected void DebugPacket(string direction, Packet packet)
539 {
540 if (m_debug > 0)
541 {
542 string info = String.Empty;
543
544 if (m_debug < 255 && packet.Type == PacketType.AgentUpdate)
545 return;
546 if (m_debug < 254 && packet.Type == PacketType.ViewerEffect)
547 return;
548 if (m_debug < 253 && (
549 packet.Type == PacketType.CompletePingCheck ||
550 packet.Type == PacketType.StartPingCheck
551 ))
552 return;
553 if (m_debug < 252 && packet.Type == PacketType.PacketAck)
554 return;
555
556 if (m_debug > 1)
557 {
558 info = packet.ToString();
559 }
560 else
561 {
562 info = packet.Type.ToString();
563 }
564 Console.WriteLine(m_circuitCode + ":" + direction + ": " + info);
565 }
566 }
567
568 protected virtual void ClientLoop()
569 {
570 m_log.Info("[CLIENT]: Entered loop");
571 while (true)
572 {
573 LLQueItem nextPacket = m_packetQueue.Dequeue();
574 if (nextPacket == null)
575 {
576 break;
577 }
578 if (nextPacket.Incoming)
579 {
580 if (nextPacket.Packet.Type != PacketType.AgentUpdate)
581 {
582 m_packetsReceived++;
583 }
584 DebugPacket("IN", nextPacket.Packet);
585 ProcessInPacket(nextPacket.Packet);
586 }
587 else
588 {
589 DebugPacket("OUT", nextPacket.Packet);
590 ProcessOutPacket(nextPacket.Packet);
591 }
592 }
593 }
594
595 # endregion
596
597 protected void CheckClientConnectivity(object sender, ElapsedEventArgs e)
598 {
599 if (m_packetsReceived == m_lastPacketsReceived)
600 {
601 m_probesWithNoIngressPackets++;
602 if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) || (m_probesWithNoIngressPackets > 90 && m_clientBlocked))
603 {
604
605 if (OnConnectionClosed != null)
606 {
607 OnConnectionClosed(this);
608 }
609 }
610 else
611 {
612 // this will normally trigger at least one packet (ping response)
613 SendStartPingCheck(0);
614
615 }
616 }
617 else
618 {
619 // Something received in the meantime - we can reset the counters
620 m_probesWithNoIngressPackets = 0;
621 m_lastPacketsReceived = m_packetsReceived;
622
623 }
624 //SendPacketStats();
625 }
626
627 # region Setup
628
629 protected virtual void InitNewClient()
630 {
631 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
632
633 // Establish our two timers. We could probably get this down to one
634 m_ackTimer = new Timer(750);
635 m_ackTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
636 m_ackTimer.Start();
637
638 m_clientPingTimer = new Timer(5000);
639 m_clientPingTimer.Elapsed += new ElapsedEventHandler(CheckClientConnectivity);
640 m_clientPingTimer.Enabled = true;
641
642 m_log.Info("[CLIENT]: Adding viewer agent to scene");
643 m_scene.AddNewClient(this, true);
644 }
645
646 protected virtual void AuthUser()
647 {
648 // AuthenticateResponse sessionInfo = m_gridServer.AuthenticateSession(m_cirpack.m_circuitCode.m_sessionId, m_cirpack.m_circuitCode.ID, m_cirpack.m_circuitCode.Code);
649 AuthenticateResponse sessionInfo =
650 m_authenticateSessionsHandler.AuthenticateSession(m_sessionId, m_agentId,
651 m_circuitCode);
652 if (!sessionInfo.Authorised)
653 {
654 //session/circuit not authorised
655 m_log.Info("[CLIENT]: New user request denied to " + m_userEndPoint.ToString());
656 m_packetQueue.Close();
657 m_clientThread.Abort();
658 }
659 else
660 {
661 m_log.Info("[CLIENT]: Got authenticated connection from " + m_userEndPoint.ToString());
662 //session is authorised
663 m_firstName = sessionInfo.LoginInfo.First;
664 m_lastName = sessionInfo.LoginInfo.Last;
665
666 if (sessionInfo.LoginInfo.SecureSession != LLUUID.Zero)
667 {
668 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
669 }
670 // This sets up all the timers
671 InitNewClient();
672
673 ClientLoop();
674 }
675 }
676
677 # endregion
678
679 // Previously ClientView.API partial class
680 public event Action<IClientAPI> OnLogout;
681 public event ObjectPermissions OnObjectPermissions;
682
683 public event Action<IClientAPI> OnConnectionClosed;
684 public event ViewerEffectEventHandler OnViewerEffect;
685 public event ImprovedInstantMessage OnInstantMessage;
686 public event ChatFromViewer OnChatFromViewer;
687 public event TextureRequest OnRequestTexture;
688 public event RezObject OnRezObject;
689 public event GenericCall4 OnDeRezObject;
690 public event ModifyTerrain OnModifyTerrain;
691 public event Action<IClientAPI> OnRegionHandShakeReply;
692 public event GenericCall2 OnRequestWearables;
693 public event SetAppearance OnSetAppearance;
694 public event AvatarNowWearing OnAvatarNowWearing;
695 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
696 public event UUIDNameRequest OnDetachAttachmentIntoInv;
697 public event ObjectAttach OnObjectAttach;
698 public event ObjectDeselect OnObjectDetach;
699 public event GenericCall2 OnCompleteMovementToRegion;
700 public event UpdateAgent OnAgentUpdate;
701 public event AgentRequestSit OnAgentRequestSit;
702 public event AgentSit OnAgentSit;
703 public event AvatarPickerRequest OnAvatarPickerRequest;
704 public event StartAnim OnStartAnim;
705 public event StopAnim OnStopAnim;
706 public event Action<IClientAPI> OnRequestAvatarsData;
707 public event LinkObjects OnLinkObjects;
708 public event DelinkObjects OnDelinkObjects;
709 public event UpdateVector OnGrabObject;
710 public event ObjectSelect OnDeGrabObject;
711 public event ObjectDuplicate OnObjectDuplicate;
712 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
713 public event MoveObject OnGrabUpdate;
714 public event AddNewPrim OnAddPrim;
715 public event RequestGodlikePowers OnRequestGodlikePowers;
716 public event GodKickUser OnGodKickUser;
717 public event ObjectExtraParams OnUpdateExtraParams;
718 public event UpdateShape OnUpdatePrimShape;
719 public event ObjectSelect OnObjectSelect;
720 public event ObjectDeselect OnObjectDeselect;
721 public event GenericCall7 OnObjectDescription;
722 public event GenericCall7 OnObjectName;
723 public event ObjectIncludeInSearch OnObjectIncludeInSearch;
724 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
725 public event UpdatePrimFlags OnUpdatePrimFlags;
726 public event UpdatePrimTexture OnUpdatePrimTexture;
727 public event UpdateVector OnUpdatePrimGroupPosition;
728 public event UpdateVector OnUpdatePrimSinglePosition;
729 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
730 public event UpdatePrimSingleRotation OnUpdatePrimSingleRotation;
731 public event UpdatePrimGroupRotation OnUpdatePrimGroupMouseRotation;
732 public event UpdateVector OnUpdatePrimScale;
733 public event UpdateVector OnUpdatePrimGroupScale;
734 public event StatusChange OnChildAgentStatus;
735 public event GenericCall2 OnStopMovement;
736 public event Action<LLUUID> OnRemoveAvatar;
737 public event RequestMapBlocks OnRequestMapBlocks;
738 public event RequestMapName OnMapNameRequest;
739 public event TeleportLocationRequest OnTeleportLocationRequest;
740 public event TeleportLandmarkRequest OnTeleportLandmarkRequest;
741 public event DisconnectUser OnDisconnectUser;
742 public event RequestAvatarProperties OnRequestAvatarProperties;
743 public event SetAlwaysRun OnSetAlwaysRun;
744
745 public event FetchInventory OnAgentDataUpdateRequest;
746 public event FetchInventory OnUserInfoRequest;
747 public event TeleportLocationRequest OnSetStartLocationRequest;
748 public event UpdateAvatarProperties OnUpdateAvatarProperties;
749
750
751 public event CreateNewInventoryItem OnCreateNewInventoryItem;
752 public event CreateInventoryFolder OnCreateNewInventoryFolder;
753 public event UpdateInventoryFolder OnUpdateInventoryFolder;
754 public event MoveInventoryFolder OnMoveInventoryFolder;
755 public event FetchInventoryDescendents OnFetchInventoryDescendents;
756 public event PurgeInventoryDescendents OnPurgeInventoryDescendents;
757 public event FetchInventory OnFetchInventory;
758 public event RequestTaskInventory OnRequestTaskInventory;
759 public event UpdateInventoryItem OnUpdateInventoryItem;
760 public event CopyInventoryItem OnCopyInventoryItem;
761 public event MoveInventoryItem OnMoveInventoryItem;
762 public event RemoveInventoryItem OnRemoveInventoryItem;
763 public event RemoveInventoryFolder OnRemoveInventoryFolder;
764 public event UDPAssetUploadRequest OnAssetUploadRequest;
765 public event XferReceive OnXferReceive;
766 public event RequestXfer OnRequestXfer;
767 public event ConfirmXfer OnConfirmXfer;
768 public event RezScript OnRezScript;
769 public event UpdateTaskInventory OnUpdateTaskInventory;
770 public event MoveTaskInventory OnMoveTaskItem;
771 public event RemoveTaskInventory OnRemoveTaskItem;
772 public event RequestAsset OnRequestAsset;
773
774 public event UUIDNameRequest OnNameFromUUIDRequest;
775
776 public event ParcelAccessListRequest OnParcelAccessListRequest;
777 public event ParcelAccessListUpdateRequest OnParcelAccessListUpdateRequest;
778 public event ParcelPropertiesRequest OnParcelPropertiesRequest;
779 public event ParcelDivideRequest OnParcelDivideRequest;
780 public event ParcelJoinRequest OnParcelJoinRequest;
781 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
782 public event ParcelSelectObjects OnParcelSelectObjects;
783 public event ParcelObjectOwnerRequest OnParcelObjectOwnerRequest;
784 public event EstateOwnerMessageRequest OnEstateOwnerMessage;
785 public event RegionInfoRequest OnRegionInfoRequest;
786 public event EstateCovenantRequest OnEstateCovenantRequest;
787
788 public event FriendActionDelegate OnApproveFriendRequest;
789 public event FriendActionDelegate OnDenyFriendRequest;
790 public event FriendshipTermination OnTerminateFriendship;
791
792 public event PacketStats OnPacketStats;
793
794 public event MoneyTransferRequest OnMoneyTransferRequest;
795 public event EconomyDataRequest OnEconomyDataRequest;
796
797 public event MoneyBalanceRequest OnMoneyBalanceRequest;
798 public event ParcelBuy OnParcelBuy;
799
800 public event UUIDNameRequest OnTeleportHomeRequest;
801
802 public event ScriptAnswer OnScriptAnswer;
803 public event RequestPayPrice OnRequestPayPrice;
804 public event AgentSit OnUndo;
805
806 #region Scene/Avatar to Client
807
808 /// <summary>
809 ///
810 /// </summary>
811 /// <param name="regionInfo"></param>
812 public void SendRegionHandshake(RegionInfo regionInfo)
813 {
814 RegionHandshakePacket handshake = (RegionHandshakePacket)PacketPool.Instance.GetPacket(PacketType.RegionHandshake);
815
816 bool estatemanager = false;
817 LLUUID[] EstateManagers = regionInfo.EstateSettings.estateManagers;
818 for (int i = 0; i < EstateManagers.Length; i++)
819 {
820 if (EstateManagers[i] == AgentId)
821 estatemanager = true;
822 }
823
824 handshake.RegionInfo.BillableFactor = regionInfo.EstateSettings.billableFactor;
825 handshake.RegionInfo.IsEstateManager = estatemanager;
826 handshake.RegionInfo.TerrainHeightRange00 = regionInfo.EstateSettings.terrainHeightRange0;
827 handshake.RegionInfo.TerrainHeightRange01 = regionInfo.EstateSettings.terrainHeightRange1;
828 handshake.RegionInfo.TerrainHeightRange10 = regionInfo.EstateSettings.terrainHeightRange2;
829 handshake.RegionInfo.TerrainHeightRange11 = regionInfo.EstateSettings.terrainHeightRange3;
830 handshake.RegionInfo.TerrainStartHeight00 = regionInfo.EstateSettings.terrainStartHeight0;
831 handshake.RegionInfo.TerrainStartHeight01 = regionInfo.EstateSettings.terrainStartHeight1;
832 handshake.RegionInfo.TerrainStartHeight10 = regionInfo.EstateSettings.terrainStartHeight2;
833 handshake.RegionInfo.TerrainStartHeight11 = regionInfo.EstateSettings.terrainStartHeight3;
834 handshake.RegionInfo.SimAccess = (byte)regionInfo.EstateSettings.simAccess;
835 handshake.RegionInfo.WaterHeight = regionInfo.EstateSettings.waterHeight;
836
837 handshake.RegionInfo.RegionFlags = (uint)regionInfo.EstateSettings.regionFlags;
838 handshake.RegionInfo.SimName = Helpers.StringToField(regionInfo.RegionName);
839 handshake.RegionInfo.SimOwner = regionInfo.MasterAvatarAssignedUUID;
840 handshake.RegionInfo.TerrainBase0 = regionInfo.EstateSettings.terrainBase0;
841 handshake.RegionInfo.TerrainBase1 = regionInfo.EstateSettings.terrainBase1;
842 handshake.RegionInfo.TerrainBase2 = regionInfo.EstateSettings.terrainBase2;
843 handshake.RegionInfo.TerrainBase3 = regionInfo.EstateSettings.terrainBase3;
844 handshake.RegionInfo.TerrainDetail0 = regionInfo.EstateSettings.terrainDetail0;
845 handshake.RegionInfo.TerrainDetail1 = regionInfo.EstateSettings.terrainDetail1;
846 handshake.RegionInfo.TerrainDetail2 = regionInfo.EstateSettings.terrainDetail2;
847 handshake.RegionInfo.TerrainDetail3 = regionInfo.EstateSettings.terrainDetail3;
848 handshake.RegionInfo.CacheID = LLUUID.Random(); //I guess this is for the client to remember an old setting?
849
850 OutPacket(handshake, ThrottleOutPacketType.Task);
851 }
852
853 /// <summary>
854 ///
855 /// </summary>
856 /// <param name="regInfo"></param>
857 public void MoveAgentIntoRegion(RegionInfo regInfo, LLVector3 pos, LLVector3 look)
858 {
859 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
860 mov.SimData.ChannelVersion = m_channelVersion;
861 mov.AgentData.SessionID = m_sessionId;
862 mov.AgentData.AgentID = AgentId;
863 mov.Data.RegionHandle = regInfo.RegionHandle;
864 mov.Data.Timestamp = 1172750370; // TODO - dynamicalise this
865
866 if ((pos.X == 0) && (pos.Y == 0) && (pos.Z == 0))
867 {
868 mov.Data.Position = m_startpos;
869 }
870 else
871 {
872 mov.Data.Position = pos;
873 }
874 mov.Data.LookAt = look;
875
876 // Hack to get this out immediately and skip the throttles
877 OutPacket(mov, ThrottleOutPacketType.Unknown);
878 }
879
880 /// <summary>
881 ///
882 /// </summary>
883 /// <param name="message"></param>
884 /// <param name="type"></param>
885 /// <param name="fromPos"></param>
886 /// <param name="fromName"></param>
887 /// <param name="fromAgentID"></param>
888 public void SendChatMessage(string message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID)
889 {
890 SendChatMessage(Helpers.StringToField(message), type, fromPos, fromName, fromAgentID);
891 }
892
893 public void SendChatMessage(byte[] message, byte type, LLVector3 fromPos, string fromName, LLUUID fromAgentID)
894 {
895 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
896 reply.ChatData.Audible = 1;
897 reply.ChatData.Message = message;
898 reply.ChatData.ChatType = type;
899 reply.ChatData.SourceType = 1;
900 reply.ChatData.Position = fromPos;
901 reply.ChatData.FromName = Helpers.StringToField(fromName);
902 reply.ChatData.OwnerID = fromAgentID;
903 reply.ChatData.SourceID = fromAgentID;
904
905 OutPacket(reply, ThrottleOutPacketType.Task);
906 }
907
908 /// <summary>
909 /// Send an instant message to this client
910 /// </summary>
911 /// <param name="message"></param>
912 /// <param name="target"></param>
913 public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent,
914 LLUUID imSessionID, string fromName, byte dialog, uint timeStamp)
915 {
916 SendInstantMessage(
917 fromAgent, fromAgentSession, message, toAgent,
918 imSessionID, fromName, dialog, timeStamp, new byte[0]);
919 }
920
921 /// <summary>
922 /// Send an instant message to this client
923 /// </summary>
924 /// <param name="message"></param>
925 /// <param name="target"></param>
926 public void SendInstantMessage(LLUUID fromAgent, LLUUID fromAgentSession, string message, LLUUID toAgent,
927 LLUUID imSessionID, string fromName, byte dialog, uint timeStamp,
928 byte[] binaryBucket)
929 {
930 ImprovedInstantMessagePacket msg
931 = (ImprovedInstantMessagePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedInstantMessage);
932
933 msg.AgentData.AgentID = fromAgent;
934 msg.AgentData.SessionID = fromAgentSession;
935 msg.MessageBlock.FromAgentName = Helpers.StringToField(fromName);
936 msg.MessageBlock.Dialog = dialog;
937 msg.MessageBlock.FromGroup = false;
938 msg.MessageBlock.ID = imSessionID;
939 msg.MessageBlock.Offline = 0;
940 msg.MessageBlock.ParentEstateID = 0;
941 msg.MessageBlock.Position = new LLVector3();
942 msg.MessageBlock.RegionID = LLUUID.Random();
943 msg.MessageBlock.Timestamp = timeStamp;
944 msg.MessageBlock.ToAgentID = toAgent;
945 msg.MessageBlock.Message = Helpers.StringToField(message);
946 msg.MessageBlock.BinaryBucket = binaryBucket;
947
948 OutPacket(msg, ThrottleOutPacketType.Task);
949 }
950
951 /// <summary>
952 /// Send the region heightmap to the client
953 /// </summary>
954 /// <param name="map">heightmap</param>
955 public virtual void SendLayerData(float[] map)
956 {
957 try
958 {
959 int[] patches = new int[4];
960
961 for (int y = 0; y < 16; y++)
962 {
963 for (int x = 0; x < 16; x += 4)
964 {
965 patches[0] = x + 0 + y * 16;
966 patches[1] = x + 1 + y * 16;
967 patches[2] = x + 2 + y * 16;
968 patches[3] = x + 3 + y * 16;
969
970 Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
971 OutPacket(layerpack, ThrottleOutPacketType.Land);
972 }
973 }
974 }
975 catch (Exception e)
976 {
977 m_log.Warn("[client]: " +
978 "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString());
979 }
980 }
981
982 /// <summary>
983 /// Sends a specified patch to a client
984 /// </summary>
985 /// <param name="px">Patch coordinate (x) 0..16</param>
986 /// <param name="py">Patch coordinate (y) 0..16</param>
987 /// <param name="map">heightmap</param>
988 public void SendLayerData(int px, int py, float[] map)
989 {
990 try
991 {
992 int[] patches = new int[1];
993 int patchx, patchy;
994 patchx = px;
995 patchy = py;
996
997 patches[0] = patchx + 0 + patchy * 16;
998
999 Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches);
1000 OutPacket(layerpack, ThrottleOutPacketType.Land);
1001 }
1002 catch (Exception e)
1003 {
1004 m_log.Warn("[client]: " +
1005 "ClientView.API.cs: SendLayerData() - Failed with exception " + e.ToString());
1006 }
1007 }
1008
1009 /// <summary>
1010 ///
1011 /// </summary>
1012 /// <param name="neighbourHandle"></param>
1013 /// <param name="neighbourIP"></param>
1014 /// <param name="neighbourPort"></param>
1015 public void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourEndPoint)
1016 {
1017 IPAddress neighbourIP = neighbourEndPoint.Address;
1018 ushort neighbourPort = (ushort)neighbourEndPoint.Port;
1019
1020 EnableSimulatorPacket enablesimpacket = (EnableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.EnableSimulator);
1021 // TODO: don't create new blocks if recycling an old packet
1022 enablesimpacket.SimulatorInfo = new EnableSimulatorPacket.SimulatorInfoBlock();
1023 enablesimpacket.SimulatorInfo.Handle = neighbourHandle;
1024
1025 byte[] byteIP = neighbourIP.GetAddressBytes();
1026 enablesimpacket.SimulatorInfo.IP = (uint)byteIP[3] << 24;
1027 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[2] << 16;
1028 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[1] << 8;
1029 enablesimpacket.SimulatorInfo.IP += (uint)byteIP[0];
1030 enablesimpacket.SimulatorInfo.Port = neighbourPort;
1031 OutPacket(enablesimpacket, ThrottleOutPacketType.Task);
1032 }
1033
1034 /// <summary>
1035 ///
1036 /// </summary>
1037 /// <returns></returns>
1038 public AgentCircuitData RequestClientInfo()
1039 {
1040 AgentCircuitData agentData = new AgentCircuitData();
1041 agentData.AgentID = AgentId;
1042 agentData.SessionID = m_sessionId;
1043 agentData.SecureSessionID = SecureSessionId;
1044 agentData.circuitcode = m_circuitCode;
1045 agentData.child = false;
1046 agentData.firstname = m_firstName;
1047 agentData.lastname = m_lastName;
1048 agentData.CapsPath = m_scene.GetCapsPath(m_agentId);
1049 return agentData;
1050 }
1051
1052 public void CrossRegion(ulong newRegionHandle, LLVector3 pos, LLVector3 lookAt, IPEndPoint externalIPEndPoint,
1053 string capsURL)
1054 {
1055 LLVector3 look = new LLVector3(lookAt.X * 10, lookAt.Y * 10, lookAt.Z * 10);
1056
1057 //CrossedRegionPacket newSimPack = (CrossedRegionPacket)PacketPool.Instance.GetPacket(PacketType.CrossedRegion);
1058 CrossedRegionPacket newSimPack = new CrossedRegionPacket();
1059 // TODO: don't create new blocks if recycling an old packet
1060 newSimPack.AgentData = new CrossedRegionPacket.AgentDataBlock();
1061 newSimPack.AgentData.AgentID = AgentId;
1062 newSimPack.AgentData.SessionID = m_sessionId;
1063 newSimPack.Info = new CrossedRegionPacket.InfoBlock();
1064 newSimPack.Info.Position = pos;
1065 newSimPack.Info.LookAt = look;
1066 newSimPack.RegionData = new CrossedRegionPacket.RegionDataBlock();
1067 newSimPack.RegionData.RegionHandle = newRegionHandle;
1068 byte[] byteIP = externalIPEndPoint.Address.GetAddressBytes();
1069 newSimPack.RegionData.SimIP = (uint)byteIP[3] << 24;
1070 newSimPack.RegionData.SimIP += (uint)byteIP[2] << 16;
1071 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1072 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1073 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1074 newSimPack.RegionData.SeedCapability = Helpers.StringToField(capsURL);
1075
1076 // Hack to get this out immediately and skip throttles
1077 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
1078 }
1079
1080 public void SendMapBlock(List<MapBlockData> mapBlocks)
1081 {
1082 MapBlockReplyPacket mapReply = (MapBlockReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapBlockReply);
1083 // TODO: don't create new blocks if recycling an old packet
1084 mapReply.AgentData.AgentID = AgentId;
1085 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks.Count];
1086 mapReply.AgentData.Flags = 0;
1087
1088 for (int i = 0; i < mapBlocks.Count; i++)
1089 {
1090 mapReply.Data[i] = new MapBlockReplyPacket.DataBlock();
1091 mapReply.Data[i].MapImageID = mapBlocks[i].MapImageId;
1092 mapReply.Data[i].X = mapBlocks[i].X;
1093 mapReply.Data[i].Y = mapBlocks[i].Y;
1094 mapReply.Data[i].WaterHeight = mapBlocks[i].WaterHeight;
1095 mapReply.Data[i].Name = Helpers.StringToField(mapBlocks[i].Name);
1096 mapReply.Data[i].RegionFlags = mapBlocks[i].RegionFlags;
1097 mapReply.Data[i].Access = mapBlocks[i].Access;
1098 mapReply.Data[i].Agents = mapBlocks[i].Agents;
1099 }
1100 OutPacket(mapReply, ThrottleOutPacketType.Land);
1101 }
1102
1103 public void SendLocalTeleport(LLVector3 position, LLVector3 lookAt, uint flags)
1104 {
1105 TeleportLocalPacket tpLocal = (TeleportLocalPacket)PacketPool.Instance.GetPacket(PacketType.TeleportLocal);
1106 tpLocal.Info.AgentID = AgentId;
1107 tpLocal.Info.TeleportFlags = flags;
1108 tpLocal.Info.LocationID = 2;
1109 tpLocal.Info.LookAt = lookAt;
1110 tpLocal.Info.Position = position;
1111
1112 // Hack to get this out immediately and skip throttles
1113 OutPacket(tpLocal, ThrottleOutPacketType.Unknown);
1114 }
1115
1116 public void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint newRegionEndPoint, uint locationID,
1117 uint flags, string capsURL)
1118 {
1119 //TeleportFinishPacket teleport = (TeleportFinishPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFinish);
1120
1121 TeleportFinishPacket teleport = new TeleportFinishPacket();
1122 teleport.Info.AgentID = AgentId;
1123 teleport.Info.RegionHandle = regionHandle;
1124 teleport.Info.SimAccess = simAccess;
1125
1126 teleport.Info.SeedCapability = Helpers.StringToField(capsURL);
1127
1128 IPAddress oIP = newRegionEndPoint.Address;
1129 byte[] byteIP = oIP.GetAddressBytes();
1130 uint ip = (uint)byteIP[3] << 24;
1131 ip += (uint)byteIP[2] << 16;
1132 ip += (uint)byteIP[1] << 8;
1133 ip += (uint)byteIP[0];
1134
1135 teleport.Info.SimIP = ip;
1136 teleport.Info.SimPort = (ushort)newRegionEndPoint.Port;
1137 teleport.Info.LocationID = 4;
1138 teleport.Info.TeleportFlags = 1 << 4;
1139
1140 // Hack to get this out immediately and skip throttles.
1141 OutPacket(teleport, ThrottleOutPacketType.Unknown);
1142 }
1143
1144 /// <summary>
1145 ///
1146 /// </summary>
1147 public void SendTeleportFailed(string reason)
1148 {
1149 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1150 tpFailed.Info.AgentID = AgentId;
1151 tpFailed.Info.Reason = Helpers.StringToField(reason);
1152
1153 // Hack to get this out immediately and skip throttles
1154 OutPacket(tpFailed, ThrottleOutPacketType.Unknown);
1155 }
1156
1157 /// <summary>
1158 ///
1159 /// </summary>
1160 public void SendTeleportLocationStart()
1161 {
1162 //TeleportStartPacket tpStart = (TeleportStartPacket)PacketPool.Instance.GetPacket(PacketType.TeleportStart);
1163 TeleportStartPacket tpStart = new TeleportStartPacket();
1164 tpStart.Info.TeleportFlags = 16; // Teleport via location
1165
1166 // Hack to get this out immediately and skip throttles
1167 OutPacket(tpStart, ThrottleOutPacketType.Unknown);
1168 }
1169
1170 public void SendMoneyBalance(LLUUID transaction, bool success, byte[] description, int balance)
1171 {
1172 MoneyBalanceReplyPacket money = (MoneyBalanceReplyPacket)PacketPool.Instance.GetPacket(PacketType.MoneyBalanceReply);
1173 money.MoneyData.AgentID = AgentId;
1174 money.MoneyData.TransactionID = transaction;
1175 money.MoneyData.TransactionSuccess = success;
1176 money.MoneyData.Description = description;
1177 money.MoneyData.MoneyBalance = balance;
1178 OutPacket(money, ThrottleOutPacketType.Task);
1179 }
1180
1181 public void SendPayPrice(LLUUID objectID, int[] payPrice)
1182 {
1183 if(payPrice[0] == 0 &&
1184 payPrice[1] == 0 &&
1185 payPrice[2] == 0 &&
1186 payPrice[3] == 0 &&
1187 payPrice[4] == 0)
1188 return;
1189
1190 PayPriceReplyPacket payPriceReply = (PayPriceReplyPacket)PacketPool.Instance.GetPacket(PacketType.PayPriceReply);
1191 payPriceReply.ObjectData.ObjectID = objectID;
1192 payPriceReply.ObjectData.DefaultPayPrice = payPrice[0];
1193
1194 payPriceReply.ButtonData=new PayPriceReplyPacket.ButtonDataBlock[4];
1195 payPriceReply.ButtonData[0]=new PayPriceReplyPacket.ButtonDataBlock();
1196 payPriceReply.ButtonData[0].PayButton = payPrice[1];
1197 payPriceReply.ButtonData[1]=new PayPriceReplyPacket.ButtonDataBlock();
1198 payPriceReply.ButtonData[1].PayButton = payPrice[2];
1199 payPriceReply.ButtonData[2]=new PayPriceReplyPacket.ButtonDataBlock();
1200 payPriceReply.ButtonData[2].PayButton = payPrice[3];
1201 payPriceReply.ButtonData[3]=new PayPriceReplyPacket.ButtonDataBlock();
1202 payPriceReply.ButtonData[3].PayButton = payPrice[4];
1203
1204 OutPacket(payPriceReply, ThrottleOutPacketType.Task);
1205 }
1206
1207 public void SendStartPingCheck(byte seq)
1208 {
1209 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
1210 pc.PingID.PingID = seq;
1211 pc.Header.Reliable = false;
1212 OutPacket(pc, ThrottleOutPacketType.Unknown);
1213 }
1214
1215 public void SendKillObject(ulong regionHandle, uint localID)
1216 {
1217 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1218 // TODO: don't create new blocks if recycling an old packet
1219 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1];
1220 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock();
1221 kill.ObjectData[0].ID = localID;
1222 kill.Header.Reliable = false;
1223 OutPacket(kill, ThrottleOutPacketType.Task);
1224 }
1225
1226 /// <summary>
1227 /// Send information about the items contained in a folder to the client.
1228 ///
1229 /// XXX This method needs some refactoring loving
1230 /// </summary>
1231 /// <param name="ownerID">The owner of the folder</param>
1232 /// <param name="folderID">The id of the folder</param>
1233 /// <param name="items">The items contained in the folder identified by folderID</param>
1234 /// <param name="fetchFolders">Do we need to send folder information?</param>
1235 /// <param name="fetchItems">Do we need to send item information?</param>
1236 public void SendInventoryFolderDetails(LLUUID ownerID, LLUUID folderID, List<InventoryItemBase> items,
1237 List<InventoryFolderBase> folders,
1238 bool fetchFolders, bool fetchItems)
1239 {
1240 // An inventory descendents packet consists of a single agent section and an inventory details
1241 // section for each inventory item. The size of each inventory item is approximately 550 bytes.
1242 // In theory, UDP has a maximum packet size of 64k, so it should be possible to send descendent
1243 // packets containing metadata for in excess of 100 items. But in practice, there may be other
1244 // factors (e.g. firewalls) restraining the maximum UDP packet size. See,
1245 //
1246 // http://opensimulator.org/mantis/view.php?id=226
1247 //
1248 // for one example of this kind of thing. In fact, the Linden servers appear to only send about
1249 // 6 to 7 items at a time, so let's stick with 6
1250 int MAX_ITEMS_PER_PACKET = 6;
1251
1252//Ckrinke This variable is not used, so comment out to remove the warning from the compiler (3-21-08)
1253//Ckrinke uint FULL_MASK_PERMISSIONS = 2147483647;
1254
1255 if (fetchItems)
1256 {
1257 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1258
1259 if (items.Count < MAX_ITEMS_PER_PACKET)
1260 {
1261 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count];
1262 descend.AgentData.Descendents = items.Count;
1263 }
1264 else
1265 {
1266 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET];
1267 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1268 }
1269
1270 // Even if we aren't fetching the folders, we still need to include the folder count
1271 // in the total number of descendents. Failure to do so will cause subtle bugs such
1272 // as the failure of textures which haven't been expanded in inventory to show up
1273 // in the texture prim edit selection panel.
1274 if (!fetchFolders)
1275 {
1276 descend.AgentData.Descendents += folders.Count;
1277 }
1278
1279 int count = 0;
1280 int i = 0;
1281 foreach (InventoryItemBase item in items)
1282 {
1283 descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock();
1284 descend.ItemData[i].ItemID = item.ID;
1285 descend.ItemData[i].AssetID = item.AssetID;
1286 descend.ItemData[i].CreatorID = item.Creator;
1287 descend.ItemData[i].BaseMask = item.BasePermissions;
1288 descend.ItemData[i].Description = Helpers.StringToField(item.Description);
1289 descend.ItemData[i].EveryoneMask = item.EveryOnePermissions;
1290 descend.ItemData[i].OwnerMask = item.CurrentPermissions;
1291 descend.ItemData[i].FolderID = item.Folder;
1292 descend.ItemData[i].InvType = (sbyte)item.InvType;
1293 descend.ItemData[i].Name = Helpers.StringToField(item.Name);
1294 descend.ItemData[i].NextOwnerMask = item.NextPermissions;
1295 descend.ItemData[i].OwnerID = item.Owner;
1296 descend.ItemData[i].Type = (sbyte)item.AssetType;
1297
1298 //descend.ItemData[i].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1299 descend.ItemData[i].GroupID = item.GroupID;
1300 descend.ItemData[i].GroupOwned = item.GroupOwned;
1301 descend.ItemData[i].GroupMask = 0;
1302 descend.ItemData[i].CreationDate = item.CreationDate;
1303 descend.ItemData[i].SalePrice = item.SalePrice;
1304 descend.ItemData[i].SaleType = item.SaleType;
1305 descend.ItemData[i].Flags = item.Flags;
1306
1307 descend.ItemData[i].CRC =
1308 Helpers.InventoryCRC(descend.ItemData[i].CreationDate, descend.ItemData[i].SaleType,
1309 descend.ItemData[i].InvType, descend.ItemData[i].Type,
1310 descend.ItemData[i].AssetID, descend.ItemData[i].GroupID,
1311 descend.ItemData[i].SalePrice,
1312 descend.ItemData[i].OwnerID, descend.ItemData[i].CreatorID,
1313 descend.ItemData[i].ItemID, descend.ItemData[i].FolderID,
1314 descend.ItemData[i].EveryoneMask,
1315 descend.ItemData[i].Flags, descend.ItemData[i].OwnerMask,
1316 descend.ItemData[i].GroupMask, item.CurrentPermissions);
1317
1318 i++;
1319 count++;
1320 if (i == MAX_ITEMS_PER_PACKET)
1321 {
1322 OutPacket(descend, ThrottleOutPacketType.Asset);
1323
1324 if ((items.Count - count) > 0)
1325 {
1326 descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1327 if ((items.Count - count) < MAX_ITEMS_PER_PACKET)
1328 {
1329 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[items.Count - count];
1330 descend.AgentData.Descendents = items.Count - count;
1331 }
1332 else
1333 {
1334 descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[MAX_ITEMS_PER_PACKET];
1335 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1336 }
1337 i = 0;
1338 }
1339 }
1340 }
1341
1342 if (i < MAX_ITEMS_PER_PACKET)
1343 {
1344 OutPacket(descend, ThrottleOutPacketType.Asset);
1345 }
1346 }
1347
1348 //send subfolders
1349 if (fetchFolders)
1350 {
1351 InventoryDescendentsPacket descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1352
1353 if (folders.Count < MAX_ITEMS_PER_PACKET)
1354 {
1355 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[folders.Count];
1356 descend.AgentData.Descendents = folders.Count;
1357 }
1358 else
1359 {
1360 descend.FolderData = new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET];
1361 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1362 }
1363
1364 // Not sure if this scenario ever actually occurs, but nonetheless we include the items
1365 // count even if we're not sending item data for the same reasons as above.
1366 if (!fetchItems)
1367 {
1368 descend.AgentData.Descendents += items.Count;
1369 }
1370
1371 int i = 0;
1372 int count = 0;
1373 foreach (InventoryFolderBase folder in folders)
1374 {
1375 descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock();
1376 descend.FolderData[i].FolderID = folder.ID;
1377 descend.FolderData[i].Name = Helpers.StringToField(folder.Name);
1378 descend.FolderData[i].ParentID = folder.ParentID;
1379 descend.FolderData[i].Type = (sbyte) folder.Type;
1380
1381 i++;
1382 count++;
1383 if (i == MAX_ITEMS_PER_PACKET)
1384 {
1385 OutPacket(descend, ThrottleOutPacketType.Asset);
1386
1387 if ((folders.Count - count) > 0)
1388 {
1389 descend = CreateInventoryDescendentsPacket(ownerID, folderID);
1390 if ((folders.Count - count) < MAX_ITEMS_PER_PACKET)
1391 {
1392 descend.FolderData =
1393 new InventoryDescendentsPacket.FolderDataBlock[folders.Count - count];
1394 descend.AgentData.Descendents = folders.Count - count;
1395 }
1396 else
1397 {
1398 descend.FolderData =
1399 new InventoryDescendentsPacket.FolderDataBlock[MAX_ITEMS_PER_PACKET];
1400 descend.AgentData.Descendents = MAX_ITEMS_PER_PACKET;
1401 }
1402 i = 0;
1403 }
1404 }
1405 }
1406
1407 if (i < MAX_ITEMS_PER_PACKET)
1408 {
1409 OutPacket(descend, ThrottleOutPacketType.Asset);
1410 }
1411 }
1412 }
1413
1414 private InventoryDescendentsPacket CreateInventoryDescendentsPacket(LLUUID ownerID, LLUUID folderID)
1415 {
1416 InventoryDescendentsPacket descend = (InventoryDescendentsPacket)PacketPool.Instance.GetPacket(PacketType.InventoryDescendents);
1417 descend.AgentData.AgentID = AgentId;
1418 descend.AgentData.OwnerID = ownerID;
1419 descend.AgentData.FolderID = folderID;
1420 descend.AgentData.Version = 1;
1421
1422 return descend;
1423 }
1424
1425 public void SendInventoryItemDetails(LLUUID ownerID, InventoryItemBase item)
1426 {
1427 uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1428 FetchInventoryReplyPacket inventoryReply = (FetchInventoryReplyPacket)PacketPool.Instance.GetPacket(PacketType.FetchInventoryReply);
1429 // TODO: don't create new blocks if recycling an old packet
1430 inventoryReply.AgentData.AgentID = AgentId;
1431 inventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1];
1432 inventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock();
1433 inventoryReply.InventoryData[0].ItemID = item.ID;
1434 inventoryReply.InventoryData[0].AssetID = item.AssetID;
1435 inventoryReply.InventoryData[0].CreatorID = item.Creator;
1436 inventoryReply.InventoryData[0].BaseMask = item.BasePermissions;
1437 inventoryReply.InventoryData[0].CreationDate =
1438 (int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
1439 inventoryReply.InventoryData[0].Description = Helpers.StringToField(item.Description);
1440 inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions;
1441 inventoryReply.InventoryData[0].FolderID = item.Folder;
1442 inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType;
1443 inventoryReply.InventoryData[0].Name = Helpers.StringToField(item.Name);
1444 inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions;
1445 inventoryReply.InventoryData[0].OwnerID = item.Owner;
1446 inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions;
1447 inventoryReply.InventoryData[0].Type = (sbyte)item.AssetType;
1448
1449 //inventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1450 inventoryReply.InventoryData[0].GroupID = item.GroupID;
1451 inventoryReply.InventoryData[0].GroupOwned = item.GroupOwned;
1452 inventoryReply.InventoryData[0].GroupMask = 0;
1453 inventoryReply.InventoryData[0].Flags = item.Flags;
1454 inventoryReply.InventoryData[0].SalePrice = item.SalePrice;
1455 inventoryReply.InventoryData[0].SaleType = item.SaleType;
1456
1457 inventoryReply.InventoryData[0].CRC =
1458 Helpers.InventoryCRC(1000, 0, inventoryReply.InventoryData[0].InvType,
1459 inventoryReply.InventoryData[0].Type, inventoryReply.InventoryData[0].AssetID,
1460 inventoryReply.InventoryData[0].GroupID, 100,
1461 inventoryReply.InventoryData[0].OwnerID, inventoryReply.InventoryData[0].CreatorID,
1462 inventoryReply.InventoryData[0].ItemID, inventoryReply.InventoryData[0].FolderID,
1463 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1464 FULL_MASK_PERMISSIONS);
1465
1466 OutPacket(inventoryReply, ThrottleOutPacketType.Asset);
1467 }
1468
1469 /// <see>IClientAPI.SendBulkUpdateInventory(InventoryItemBase)</see>
1470 public void SendBulkUpdateInventory(InventoryItemBase item)
1471 {
1472 uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1473
1474 BulkUpdateInventoryPacket bulkUpdate
1475 = (BulkUpdateInventoryPacket)PacketPool.Instance.GetPacket(PacketType.BulkUpdateInventory);
1476
1477 bulkUpdate.AgentData.AgentID = AgentId;
1478 bulkUpdate.AgentData.TransactionID = LLUUID.Random();
1479
1480 bulkUpdate.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1];
1481 bulkUpdate.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock();
1482 bulkUpdate.FolderData[0].FolderID = LLUUID.Zero;
1483 bulkUpdate.FolderData[0].ParentID = LLUUID.Zero;
1484 bulkUpdate.FolderData[0].Type = -1;
1485 bulkUpdate.FolderData[0].Name = new byte[0];
1486
1487 bulkUpdate.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1];
1488 bulkUpdate.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock();
1489 bulkUpdate.ItemData[0].ItemID = item.ID;
1490 bulkUpdate.ItemData[0].AssetID = item.AssetID;
1491 bulkUpdate.ItemData[0].CreatorID = item.Creator;
1492 bulkUpdate.ItemData[0].BaseMask = item.BasePermissions;
1493 bulkUpdate.ItemData[0].CreationDate = 1000;
1494 bulkUpdate.ItemData[0].Description = Helpers.StringToField(item.Description);
1495 bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions;
1496 bulkUpdate.ItemData[0].FolderID = item.Folder;
1497 bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType;
1498 bulkUpdate.ItemData[0].Name = Helpers.StringToField(item.Name);
1499 bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions;
1500 bulkUpdate.ItemData[0].OwnerID = item.Owner;
1501 bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions;
1502 bulkUpdate.ItemData[0].Type = (sbyte)item.AssetType;
1503
1504 //bulkUpdate.ItemData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1505 bulkUpdate.ItemData[0].GroupID = item.GroupID;
1506 bulkUpdate.ItemData[0].GroupOwned = item.GroupOwned;
1507 bulkUpdate.ItemData[0].GroupMask = 0;
1508 bulkUpdate.ItemData[0].Flags = item.Flags;
1509 bulkUpdate.ItemData[0].SalePrice = item.SalePrice;
1510 bulkUpdate.ItemData[0].SaleType = item.SaleType;
1511
1512 bulkUpdate.ItemData[0].CRC =
1513 Helpers.InventoryCRC(1000, 0, bulkUpdate.ItemData[0].InvType,
1514 bulkUpdate.ItemData[0].Type, bulkUpdate.ItemData[0].AssetID,
1515 bulkUpdate.ItemData[0].GroupID, 100,
1516 bulkUpdate.ItemData[0].OwnerID, bulkUpdate.ItemData[0].CreatorID,
1517 bulkUpdate.ItemData[0].ItemID, bulkUpdate.ItemData[0].FolderID,
1518 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1519 FULL_MASK_PERMISSIONS);
1520
1521 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
1522 }
1523
1524 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
1525 public void SendInventoryItemCreateUpdate(InventoryItemBase Item)
1526 {
1527 uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
1528
1529 UpdateCreateInventoryItemPacket InventoryReply
1530 = (UpdateCreateInventoryItemPacket)PacketPool.Instance.GetPacket(
1531 PacketType.UpdateCreateInventoryItem);
1532
1533 // TODO: don't create new blocks if recycling an old packet
1534 InventoryReply.AgentData.AgentID = AgentId;
1535 InventoryReply.AgentData.SimApproved = true;
1536 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
1537 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
1538 InventoryReply.InventoryData[0].ItemID = Item.ID;
1539 InventoryReply.InventoryData[0].AssetID = Item.AssetID;
1540 InventoryReply.InventoryData[0].CreatorID = Item.Creator;
1541 InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions;
1542 InventoryReply.InventoryData[0].Description = Helpers.StringToField(Item.Description);
1543 InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions;
1544 InventoryReply.InventoryData[0].FolderID = Item.Folder;
1545 InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType;
1546 InventoryReply.InventoryData[0].Name = Helpers.StringToField(Item.Name);
1547 InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions;
1548 InventoryReply.InventoryData[0].OwnerID = Item.Owner;
1549 InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions;
1550 InventoryReply.InventoryData[0].Type = (sbyte)Item.AssetType;
1551
1552 //InventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000");
1553 InventoryReply.InventoryData[0].GroupID = Item.GroupID;
1554 InventoryReply.InventoryData[0].GroupOwned = Item.GroupOwned;
1555 InventoryReply.InventoryData[0].GroupMask = 0;
1556 InventoryReply.InventoryData[0].Flags = Item.Flags;
1557 InventoryReply.InventoryData[0].SalePrice = Item.SalePrice;
1558 InventoryReply.InventoryData[0].SaleType = Item.SaleType;
1559
1560 InventoryReply.InventoryData[0].CRC =
1561 Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType,
1562 InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID,
1563 InventoryReply.InventoryData[0].GroupID, 100,
1564 InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID,
1565 InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID,
1566 FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS,
1567 FULL_MASK_PERMISSIONS);
1568
1569 OutPacket(InventoryReply, ThrottleOutPacketType.Asset);
1570 }
1571
1572 public void SendRemoveInventoryItem(LLUUID itemID)
1573 {
1574 RemoveInventoryItemPacket remove = (RemoveInventoryItemPacket)PacketPool.Instance.GetPacket(PacketType.RemoveInventoryItem);
1575 // TODO: don't create new blocks if recycling an old packet
1576 remove.AgentData.AgentID = AgentId;
1577 remove.AgentData.SessionID = m_sessionId;
1578 remove.InventoryData = new RemoveInventoryItemPacket.InventoryDataBlock[1];
1579 remove.InventoryData[0] = new RemoveInventoryItemPacket.InventoryDataBlock();
1580 remove.InventoryData[0].ItemID = itemID;
1581
1582 OutPacket(remove, ThrottleOutPacketType.Asset);
1583 }
1584
1585 public void SendTaskInventory(LLUUID taskID, short serial, byte[] fileName)
1586 {
1587 ReplyTaskInventoryPacket replytask = (ReplyTaskInventoryPacket)PacketPool.Instance.GetPacket(PacketType.ReplyTaskInventory);
1588 replytask.InventoryData.TaskID = taskID;
1589 replytask.InventoryData.Serial = serial;
1590 replytask.InventoryData.Filename = fileName;
1591 OutPacket(replytask, ThrottleOutPacketType.Asset);
1592 }
1593
1594 public void SendXferPacket(ulong xferID, uint packet, byte[] data)
1595 {
1596 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
1597 sendXfer.XferID.ID = xferID;
1598 sendXfer.XferID.Packet = packet;
1599 sendXfer.DataPacket.Data = data;
1600 OutPacket(sendXfer, ThrottleOutPacketType.Task);
1601 }
1602
1603 public void SendEconomyData(float EnergyEfficiency, int ObjectCapacity, int ObjectCount, int PriceEnergyUnit,
1604 int PriceGroupCreate, int PriceObjectClaim, float PriceObjectRent, float PriceObjectScaleFactor,
1605 int PriceParcelClaim, float PriceParcelClaimFactor, int PriceParcelRent, int PricePublicObjectDecay,
1606 int PricePublicObjectDelete, int PriceRentLight, int PriceUpload, int TeleportMinPrice, float TeleportPriceExponent)
1607 {
1608 EconomyDataPacket economyData = (EconomyDataPacket)PacketPool.Instance.GetPacket(PacketType.EconomyData);
1609 economyData.Info.EnergyEfficiency = EnergyEfficiency;
1610 economyData.Info.ObjectCapacity = ObjectCapacity;
1611 economyData.Info.ObjectCount = ObjectCount;
1612 economyData.Info.PriceEnergyUnit = PriceEnergyUnit;
1613 economyData.Info.PriceGroupCreate = PriceGroupCreate;
1614 economyData.Info.PriceObjectClaim = PriceObjectClaim;
1615 economyData.Info.PriceObjectRent = PriceObjectRent;
1616 economyData.Info.PriceObjectScaleFactor = PriceObjectScaleFactor;
1617 economyData.Info.PriceParcelClaim = PriceParcelClaim;
1618 economyData.Info.PriceParcelClaimFactor = PriceParcelClaimFactor;
1619 economyData.Info.PriceParcelRent = PriceParcelRent;
1620 economyData.Info.PricePublicObjectDecay = PricePublicObjectDecay;
1621 economyData.Info.PricePublicObjectDelete = PricePublicObjectDelete;
1622 economyData.Info.PriceRentLight = PriceRentLight;
1623 economyData.Info.PriceUpload = PriceUpload;
1624 economyData.Info.TeleportMinPrice = TeleportMinPrice;
1625 economyData.Info.TeleportPriceExponent = TeleportPriceExponent;
1626 economyData.Header.Reliable = true;
1627 OutPacket(economyData, ThrottleOutPacketType.Unknown);
1628
1629 }
1630
1631 public void SendAvatarPickerReply(AvatarPickerReplyPacket replyPacket)
1632 {
1633 OutPacket(replyPacket, ThrottleOutPacketType.Task);
1634 }
1635
1636 public void SendAgentDataUpdate(LLUUID agentid, LLUUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
1637 {
1638 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
1639 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
1640 sendAgentDataUpdate.AgentData.AgentID = agentid;
1641 sendAgentDataUpdate.AgentData.FirstName = Helpers.StringToField(firstname);
1642 sendAgentDataUpdate.AgentData.GroupName = Helpers.StringToField(groupname);
1643 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
1644 sendAgentDataUpdate.AgentData.GroupTitle = Helpers.StringToField(grouptitle);
1645 sendAgentDataUpdate.AgentData.LastName = Helpers.StringToField(lastname);
1646 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
1647 }
1648
1649 /// <summary>
1650 /// Send an alert message to the client. On the Linden client (tested 1.19.1.4), this pops up a brief duration
1651 /// blue information box in the bottom right hand corner.
1652 /// </summary>
1653 /// <param name="message"></param>
1654 public void SendAlertMessage(string message)
1655 {
1656 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
1657 alertPack.AlertData.Message = Helpers.StringToField(message);
1658 OutPacket(alertPack, ThrottleOutPacketType.Task);
1659 }
1660
1661 /// <summary>
1662 /// Send an agent alert message to the client.
1663 /// </summary>
1664 /// <param name="message"></param>
1665 /// <param name="modal">On the linden client, if this true then it displays a one button text box placed in the
1666 /// middle of the window. If false, the message is displayed in a brief duration blue information box (as for
1667 /// the AlertMessage packet).</param>
1668 public void SendAgentAlertMessage(string message, bool modal)
1669 {
1670 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
1671 alertPack.AgentData.AgentID = AgentId;
1672 alertPack.AlertData.Message = Helpers.StringToField(message);
1673 alertPack.AlertData.Modal = modal;
1674 OutPacket(alertPack, ThrottleOutPacketType.Task);
1675 }
1676
1677 public void SendLoadURL(string objectname, LLUUID objectID, LLUUID ownerID, bool groupOwned, string message,
1678 string url)
1679 {
1680 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
1681 loadURL.Data.ObjectName = Helpers.StringToField(objectname);
1682 loadURL.Data.ObjectID = objectID;
1683 loadURL.Data.OwnerID = ownerID;
1684 loadURL.Data.OwnerIsGroup = groupOwned;
1685 loadURL.Data.Message = Helpers.StringToField(message);
1686 loadURL.Data.URL = Helpers.StringToField(url);
1687 OutPacket(loadURL, ThrottleOutPacketType.Task);
1688 }
1689
1690 public void SendDialog(string objectname, LLUUID objectID, LLUUID ownerID, string msg, LLUUID textureID, int ch, string[] buttonlabels)
1691 {
1692 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
1693 dialog.Data.ObjectID = objectID;
1694 dialog.Data.ObjectName = Helpers.StringToField(objectname);
1695 dialog.Data.FirstName = Helpers.StringToField(this.FirstName);
1696 dialog.Data.LastName = Helpers.StringToField(this.LastName);
1697 dialog.Data.Message = Helpers.StringToField(msg);
1698 dialog.Data.ImageID = textureID;
1699 dialog.Data.ChatChannel = ch;
1700 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
1701 for (int i = 0; i < buttonlabels.Length; i++)
1702 {
1703 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
1704 buttons[i].ButtonLabel = Helpers.StringToField(buttonlabels[i]);
1705 }
1706 dialog.Buttons = buttons;
1707 OutPacket(dialog, ThrottleOutPacketType.Task);
1708 }
1709
1710 public void SendPreLoadSound(LLUUID objectID, LLUUID ownerID, LLUUID soundID)
1711 {
1712 PreloadSoundPacket preSound = (PreloadSoundPacket)PacketPool.Instance.GetPacket(PacketType.PreloadSound);
1713 // TODO: don't create new blocks if recycling an old packet
1714 preSound.DataBlock = new PreloadSoundPacket.DataBlockBlock[1];
1715 preSound.DataBlock[0] = new PreloadSoundPacket.DataBlockBlock();
1716 preSound.DataBlock[0].ObjectID = objectID;
1717 preSound.DataBlock[0].OwnerID = ownerID;
1718 preSound.DataBlock[0].SoundID = soundID;
1719 OutPacket(preSound, ThrottleOutPacketType.Task);
1720 }
1721
1722 public void SendPlayAttachedSound(LLUUID soundID, LLUUID objectID, LLUUID ownerID, float gain, byte flags)
1723 {
1724 AttachedSoundPacket sound = (AttachedSoundPacket)PacketPool.Instance.GetPacket(PacketType.AttachedSound);
1725 sound.DataBlock.SoundID = soundID;
1726 sound.DataBlock.ObjectID = objectID;
1727 sound.DataBlock.OwnerID = ownerID;
1728 sound.DataBlock.Gain = gain;
1729 sound.DataBlock.Flags = flags;
1730
1731 OutPacket(sound, ThrottleOutPacketType.Task);
1732 }
1733
1734 public void SendTriggeredSound(LLUUID soundID, LLUUID ownerID, LLUUID objectID, LLUUID parentID, ulong handle, LLVector3 position, float gain)
1735 {
1736 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
1737 sound.SoundData.SoundID = soundID;
1738 sound.SoundData.OwnerID = ownerID;
1739 sound.SoundData.ObjectID = objectID;
1740 sound.SoundData.ParentID = parentID;
1741 sound.SoundData.Handle = handle;
1742 sound.SoundData.Position = position;
1743 sound.SoundData.Gain = gain;
1744
1745 OutPacket(sound, ThrottleOutPacketType.Task);
1746 }
1747
1748 public void SendAttachedSoundGainChange(LLUUID objectID, float gain)
1749 {
1750 AttachedSoundGainChangePacket sound = (AttachedSoundGainChangePacket)PacketPool.Instance.GetPacket(PacketType.AttachedSoundGainChange);
1751 sound.DataBlock.ObjectID = objectID;
1752 sound.DataBlock.Gain = gain;
1753
1754 OutPacket(sound, ThrottleOutPacketType.Task);
1755 }
1756
1757 public void SendSunPos(LLVector3 sunPos, LLVector3 sunVel)
1758 {
1759 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
1760 viewertime.TimeInfo.SunDirection = sunPos;
1761 viewertime.TimeInfo.SunAngVelocity = sunVel;
1762 viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch();
1763 viewertime.Header.Reliable = false;
1764 OutPacket(viewertime, ThrottleOutPacketType.Task);
1765 }
1766
1767 public void SendViewerTime(int phase)
1768 {
1769 Console.WriteLine("SunPhase: {0}", phase);
1770 SimulatorViewerTimeMessagePacket viewertime = (SimulatorViewerTimeMessagePacket)PacketPool.Instance.GetPacket(PacketType.SimulatorViewerTimeMessage);
1771 //viewertime.TimeInfo.SecPerDay = 86400;
1772 //viewertime.TimeInfo.SecPerYear = 31536000;
1773 viewertime.TimeInfo.SecPerDay = 1000;
1774 viewertime.TimeInfo.SecPerYear = 365000;
1775 viewertime.TimeInfo.SunPhase = 1;
1776 int sunPhase = (phase + 2) / 2;
1777 if ((sunPhase < 6) || (sunPhase > 36))
1778 {
1779 viewertime.TimeInfo.SunDirection = new LLVector3(0f, 0.8f, -0.8f);
1780 Console.WriteLine("sending night");
1781 }
1782 else
1783 {
1784 if (sunPhase < 12)
1785 {
1786 sunPhase = 12;
1787 }
1788 sunPhase = sunPhase - 12;
1789
1790 float yValue = 0.1f * (sunPhase);
1791 Console.WriteLine("Computed SunPhase: {0}, yValue: {1}", sunPhase, yValue);
1792 if (yValue > 1.2f)
1793 {
1794 yValue = yValue - 1.2f;
1795 }
1796
1797 yValue = Util.Clip(yValue, 0, 1);
1798
1799 if (sunPhase < 14)
1800 {
1801 yValue = 1 - yValue;
1802 }
1803 if (sunPhase < 12)
1804 {
1805 yValue *= -1;
1806 }
1807 viewertime.TimeInfo.SunDirection = new LLVector3(0f, yValue, 0.3f);
1808 Console.WriteLine("sending sun update " + yValue);
1809 }
1810 viewertime.TimeInfo.SunAngVelocity = new LLVector3(0, 0.0f, 10.0f);
1811 viewertime.TimeInfo.UsecSinceStart = (ulong)Util.UnixTimeSinceEpoch();
1812 viewertime.Header.Reliable = false;
1813 OutPacket(viewertime, ThrottleOutPacketType.Task);
1814 }
1815
1816 public void SendAvatarProperties(LLUUID avatarID, string aboutText, string bornOn, string charterMember,
1817 string flAbout, uint flags, LLUUID flImageID, LLUUID imageID, string profileURL,
1818 LLUUID partnerID)
1819 {
1820 AvatarPropertiesReplyPacket avatarReply = (AvatarPropertiesReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPropertiesReply);
1821 avatarReply.AgentData.AgentID = AgentId;
1822 avatarReply.AgentData.AvatarID = avatarID;
1823 if (aboutText != null)
1824 avatarReply.PropertiesData.AboutText = Helpers.StringToField(aboutText);
1825 else
1826 avatarReply.PropertiesData.AboutText = Helpers.StringToField("");
1827 avatarReply.PropertiesData.BornOn = Helpers.StringToField(bornOn);
1828 avatarReply.PropertiesData.CharterMember = Helpers.StringToField(charterMember);
1829 if (flAbout != null)
1830 avatarReply.PropertiesData.FLAboutText = Helpers.StringToField(flAbout);
1831 else
1832 avatarReply.PropertiesData.FLAboutText = Helpers.StringToField("");
1833 avatarReply.PropertiesData.Flags = 0;
1834 avatarReply.PropertiesData.FLImageID = flImageID;
1835 avatarReply.PropertiesData.ImageID = imageID;
1836 avatarReply.PropertiesData.ProfileURL = Helpers.StringToField(profileURL);
1837 avatarReply.PropertiesData.PartnerID = partnerID;
1838 OutPacket(avatarReply, ThrottleOutPacketType.Task);
1839 }
1840
1841 #endregion
1842
1843 #region Appearance/ Wearables Methods
1844
1845 /// <summary>
1846 ///
1847 /// </summary>
1848 /// <param name="wearables"></param>
1849 public void SendWearables(AvatarWearable[] wearables, int serial)
1850 {
1851 AgentWearablesUpdatePacket aw = (AgentWearablesUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentWearablesUpdate);
1852 aw.AgentData.AgentID = AgentId;
1853 aw.AgentData.SerialNum = (uint)serial;
1854 aw.AgentData.SessionID = m_sessionId;
1855
1856 // TODO: don't create new blocks if recycling an old packet
1857 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13];
1858 AgentWearablesUpdatePacket.WearableDataBlock awb;
1859 for (int i = 0; i < wearables.Length; i++)
1860 {
1861 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
1862 awb.WearableType = (byte)i;
1863 awb.AssetID = wearables[i].AssetID;
1864 awb.ItemID = wearables[i].ItemID;
1865 aw.WearableData[i] = awb;
1866 }
1867
1868 OutPacket(aw, ThrottleOutPacketType.Task);
1869 }
1870
1871 /// <summary>
1872 ///
1873 /// </summary>
1874 /// <param name="agentID"></param>
1875 /// <param name="visualParams"></param>
1876 /// <param name="textureEntry"></param>
1877 public void SendAppearance(LLUUID agentID, byte[] visualParams, byte[] textureEntry)
1878 {
1879 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
1880 // TODO: don't create new blocks if recycling an old packet
1881 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218];
1882 avp.ObjectData.TextureEntry = textureEntry;
1883
1884 AvatarAppearancePacket.VisualParamBlock avblock = null;
1885 for (int i = 0; i < visualParams.Length; i++)
1886 {
1887 avblock = new AvatarAppearancePacket.VisualParamBlock();
1888 avblock.ParamValue = visualParams[i];
1889 avp.VisualParam[i] = avblock;
1890 }
1891
1892 avp.Sender.IsTrial = false;
1893 avp.Sender.ID = agentID;
1894 OutPacket(avp, ThrottleOutPacketType.Task);
1895 }
1896
1897 public void SendAnimations(LLUUID[] animations, int[] seqs, LLUUID sourceAgentId)
1898 {
1899 AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation);
1900 // TODO: don't create new blocks if recycling an old packet
1901 ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1];
1902 ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock();
1903 ani.AnimationSourceList[0].ObjectID = sourceAgentId;
1904 ani.Sender = new AvatarAnimationPacket.SenderBlock();
1905 ani.Sender.ID = sourceAgentId;
1906 ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[animations.Length];
1907
1908 for (int i = 0; i < animations.Length; ++i)
1909 {
1910 ani.AnimationList[i] = new AvatarAnimationPacket.AnimationListBlock();
1911 ani.AnimationList[i].AnimID = animations[i];
1912 ani.AnimationList[i].AnimSequenceID = seqs[i];
1913 }
1914 ani.Header.Reliable = false;
1915 OutPacket(ani, ThrottleOutPacketType.Task);
1916 }
1917
1918 #endregion
1919
1920 #region Avatar Packet/data sending Methods
1921
1922 /// <summary>
1923 /// send a objectupdate packet with information about the clients avatar
1924 /// </summary>
1925 /// <param name="regionInfo"></param>
1926 /// <param name="firstName"></param>
1927 /// <param name="lastName"></param>
1928 /// <param name="avatarID"></param>
1929 /// <param name="avatarLocalID"></param>
1930 /// <param name="Pos"></param>
1931 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, LLUUID avatarID,
1932 uint avatarLocalID, LLVector3 Pos, byte[] textureEntry, uint parentID)
1933 {
1934 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
1935 // TODO: don't create new blocks if recycling an old packet
1936 objupdate.RegionData.RegionHandle = regionHandle;
1937 objupdate.RegionData.TimeDilation = ushort.MaxValue;
1938 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
1939 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry);
1940
1941 //give this avatar object a local id and assign the user a name
1942 objupdate.ObjectData[0].ID = avatarLocalID;
1943 objupdate.ObjectData[0].FullID = avatarID;
1944 objupdate.ObjectData[0].ParentID = parentID;
1945 objupdate.ObjectData[0].NameValue =
1946 Helpers.StringToField("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName);
1947 LLVector3 pos2 = new LLVector3((float)Pos.X, (float)Pos.Y, (float)Pos.Z);
1948 byte[] pb = pos2.GetBytes();
1949 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
1950
1951 OutPacket(objupdate, ThrottleOutPacketType.Task);
1952 }
1953
1954 /// <summary>
1955 ///
1956 /// </summary>
1957 /// <param name="regionHandle"></param>
1958 /// <param name="timeDilation"></param>
1959 /// <param name="localID"></param>
1960 /// <param name="position"></param>
1961 /// <param name="velocity"></param>
1962 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
1963 LLVector3 velocity, LLQuaternion rotation)
1964 {
1965 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock =
1966 CreateAvatarImprovedBlock(localID, position, velocity, rotation);
1967 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
1968 // TODO: don't create new blocks if recycling an old packet
1969 terse.RegionData.RegionHandle = regionHandle;
1970 terse.RegionData.TimeDilation = timeDilation;
1971 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
1972 terse.ObjectData[0] = terseBlock;
1973
1974 terse.Header.Reliable = false;
1975
1976
1977 OutPacket(terse, ThrottleOutPacketType.Task);
1978 }
1979
1980 public void SendCoarseLocationUpdate(List<LLVector3> CoarseLocations)
1981 {
1982 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
1983 // TODO: don't create new blocks if recycling an old packet
1984 int total = CoarseLocations.Count;
1985 CoarseLocationUpdatePacket.IndexBlock ib =
1986 new CoarseLocationUpdatePacket.IndexBlock();
1987 loc.Location = new CoarseLocationUpdatePacket.LocationBlock[total];
1988 for (int i = 0; i < total; i++)
1989 {
1990 CoarseLocationUpdatePacket.LocationBlock lb =
1991 new CoarseLocationUpdatePacket.LocationBlock();
1992 lb.X = (byte)CoarseLocations[i].X;
1993 lb.Y = (byte)CoarseLocations[i].Y;
1994 lb.Z = (byte)(CoarseLocations[i].Z / 4);
1995 loc.Location[i] = lb;
1996 }
1997 ib.You = -1;
1998 ib.Prey = -1;
1999 loc.Index = ib;
2000 loc.Header.Reliable = false;
2001 OutPacket(loc, ThrottleOutPacketType.Task);
2002 }
2003
2004 #endregion
2005
2006 #region Primitive Packet/data Sending Methods
2007
2008 /// <summary>
2009 ///
2010 /// </summary>
2011 /// <param name="localID"></param>
2012 /// <param name="rotation"></param>
2013 /// <param name="attachPoint"></param>
2014 public void AttachObject(uint localID, LLQuaternion rotation, byte attachPoint)
2015 {
2016
2017 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach);
2018 Console.WriteLine("Attach object!");
2019 // TODO: don't create new blocks if recycling an old packet
2020 attach.AgentData.AgentID = AgentId;
2021 attach.AgentData.SessionID = m_sessionId;
2022 attach.AgentData.AttachmentPoint = attachPoint;
2023 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
2024 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
2025 attach.ObjectData[0].ObjectLocalID = localID;
2026 attach.ObjectData[0].Rotation = rotation;
2027
2028 OutPacket(attach, ThrottleOutPacketType.Task);
2029 }
2030
2031 public void SendPrimitiveToClient(
2032 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos,
2033 uint flags,
2034 LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
2035 LLQuaternion rotation, byte clickAction)
2036 {
2037 byte[] textureanim = new byte[0];
2038
2039 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, flags,
2040 objectID, ownerID, text, color, parentID, particleSystem,
2041 rotation, clickAction, textureanim, false,(uint)0, LLUUID.Zero);
2042 }
2043 public void SendPrimitiveToClient(
2044 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, LLVector3 pos,
2045 uint flags,
2046 LLUUID objectID, LLUUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
2047 LLQuaternion rotation, byte clickAction, byte[] textureanim, bool attachment, uint AttachPoint, LLUUID AssetId)
2048 {
2049 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
2050 // TODO: don't create new blocks if recycling an old packet
2051 outPacket.RegionData.RegionHandle = regionHandle;
2052 outPacket.RegionData.TimeDilation = timeDilation;
2053 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
2054
2055 outPacket.ObjectData[0] = CreatePrimUpdateBlock(primShape, flags);
2056
2057 outPacket.ObjectData[0].ID = localID;
2058 outPacket.ObjectData[0].FullID = objectID;
2059 outPacket.ObjectData[0].OwnerID = ownerID;
2060
2061 // Anything more than 255 will cause libsecondlife to barf
2062 if (text.Length > 255)
2063 {
2064 text = text.Remove(255);
2065 }
2066
2067 outPacket.ObjectData[0].Text = Helpers.StringToField(text);
2068
2069 outPacket.ObjectData[0].TextColor[0] = color[0];
2070 outPacket.ObjectData[0].TextColor[1] = color[1];
2071 outPacket.ObjectData[0].TextColor[2] = color[2];
2072 outPacket.ObjectData[0].TextColor[3] = color[3];
2073 outPacket.ObjectData[0].ParentID = parentID;
2074 outPacket.ObjectData[0].PSBlock = particleSystem;
2075 outPacket.ObjectData[0].ClickAction = clickAction;
2076 //outPacket.ObjectData[0].Flags = 0;
2077
2078 if (attachment)
2079 {
2080 // Necessary???
2081 outPacket.ObjectData[0].JointAxisOrAnchor = new LLVector3(0, 0, 2);
2082 outPacket.ObjectData[0].JointPivot = new LLVector3(0, 0, 0);
2083
2084 // Item from inventory???
2085 outPacket.ObjectData[0].NameValue =
2086 Helpers.StringToField("AttachItemID STRING RW SV " + AssetId.UUID);
2087 outPacket.ObjectData[0].State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
2088 }
2089
2090 // Sound Radius
2091 outPacket.ObjectData[0].Radius = 20;
2092
2093 byte[] pb = pos.GetBytes();
2094 Array.Copy(pb, 0, outPacket.ObjectData[0].ObjectData, 0, pb.Length);
2095
2096 byte[] rot = rotation.GetBytes();
2097 Array.Copy(rot, 0, outPacket.ObjectData[0].ObjectData, 36, rot.Length);
2098
2099 if (textureanim.Length > 0)
2100 {
2101 outPacket.ObjectData[0].TextureAnim = textureanim;
2102 }
2103
2104 OutPacket(outPacket, ThrottleOutPacketType.Task);
2105 }
2106
2107 /// <summary>
2108 ///
2109 /// </summary>
2110 /// <param name="regionHandle"></param>
2111 /// <param name="timeDilation"></param>
2112 /// <param name="localID"></param>
2113 /// <param name="position"></param>
2114 /// <param name="rotation"></param>
2115 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
2116 LLQuaternion rotation, byte state, LLUUID AssetId)
2117 {
2118 LLVector3 velocity = new LLVector3(0f, 0f, 0f);
2119 LLVector3 rotationalvelocity = new LLVector3(0f, 0f, 0f);
2120 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
2121 // TODO: don't create new blocks if recycling an old packet
2122 terse.RegionData.RegionHandle = regionHandle;
2123 terse.RegionData.TimeDilation = timeDilation;
2124 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
2125 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, state); // AssetID should fall into here probably somehow...
2126 terse.Header.Reliable = false;
2127 OutPacket(terse, ThrottleOutPacketType.Task);
2128 }
2129
2130 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, LLVector3 position,
2131 LLQuaternion rotation, LLVector3 velocity, LLVector3 rotationalvelocity)
2132 {
2133 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
2134 // TODO: don't create new blocks if recycling an old packet
2135 terse.RegionData.RegionHandle = regionHandle;
2136 terse.RegionData.TimeDilation = timeDilation;
2137 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
2138 terse.ObjectData[0] = CreatePrimImprovedBlock(localID, position, rotation, velocity, rotationalvelocity, 0);
2139 terse.Header.Reliable = false;
2140 OutPacket(terse, ThrottleOutPacketType.Task);
2141 }
2142
2143 #endregion
2144
2145 #region Helper Methods
2146
2147 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, LLVector3 pos,
2148 LLVector3 velocity,
2149 LLQuaternion rotation)
2150 {
2151 byte[] bytes = new byte[60];
2152 int i = 0;
2153 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
2154
2155 dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry;
2156
2157 uint ID = localID;
2158
2159 bytes[i++] = (byte)(ID % 256);
2160 bytes[i++] = (byte)((ID >> 8) % 256);
2161 bytes[i++] = (byte)((ID >> 16) % 256);
2162 bytes[i++] = (byte)((ID >> 24) % 256);
2163 bytes[i++] = 0;
2164 bytes[i++] = 1;
2165 i += 14;
2166 bytes[i++] = 128;
2167 bytes[i++] = 63;
2168
2169 byte[] pb = pos.GetBytes();
2170 Array.Copy(pb, 0, bytes, i, pb.Length);
2171 i += 12;
2172 ushort InternVelocityX;
2173 ushort InternVelocityY;
2174 ushort InternVelocityZ;
2175 Vector3 internDirec = new Vector3(0, 0, 0);
2176
2177 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z);
2178
2179 internDirec = internDirec / 128.0f;
2180 internDirec.x += 1;
2181 internDirec.y += 1;
2182 internDirec.z += 1;
2183
2184 InternVelocityX = (ushort)(32768 * internDirec.x);
2185 InternVelocityY = (ushort)(32768 * internDirec.y);
2186 InternVelocityZ = (ushort)(32768 * internDirec.z);
2187
2188 ushort ac = 32767;
2189 bytes[i++] = (byte)(InternVelocityX % 256);
2190 bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
2191 bytes[i++] = (byte)(InternVelocityY % 256);
2192 bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
2193 bytes[i++] = (byte)(InternVelocityZ % 256);
2194 bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
2195
2196 //accel
2197 bytes[i++] = (byte)(ac % 256);
2198 bytes[i++] = (byte)((ac >> 8) % 256);
2199 bytes[i++] = (byte)(ac % 256);
2200 bytes[i++] = (byte)((ac >> 8) % 256);
2201 bytes[i++] = (byte)(ac % 256);
2202 bytes[i++] = (byte)((ac >> 8) % 256);
2203
2204 //rotation
2205 ushort rw, rx, ry, rz;
2206 rw = (ushort)(32768 * (rotation.W + 1));
2207 rx = (ushort)(32768 * (rotation.X + 1));
2208 ry = (ushort)(32768 * (rotation.Y + 1));
2209 rz = (ushort)(32768 * (rotation.Z + 1));
2210
2211 //rot
2212 bytes[i++] = (byte)(rx % 256);
2213 bytes[i++] = (byte)((rx >> 8) % 256);
2214 bytes[i++] = (byte)(ry % 256);
2215 bytes[i++] = (byte)((ry >> 8) % 256);
2216 bytes[i++] = (byte)(rz % 256);
2217 bytes[i++] = (byte)((rz >> 8) % 256);
2218 bytes[i++] = (byte)(rw % 256);
2219 bytes[i++] = (byte)((rw >> 8) % 256);
2220
2221 //rotation vel
2222 bytes[i++] = (byte)(ac % 256);
2223 bytes[i++] = (byte)((ac >> 8) % 256);
2224 bytes[i++] = (byte)(ac % 256);
2225 bytes[i++] = (byte)((ac >> 8) % 256);
2226 bytes[i++] = (byte)(ac % 256);
2227 bytes[i++] = (byte)((ac >> 8) % 256);
2228
2229 dat.Data = bytes;
2230
2231 return (dat);
2232 }
2233
2234 /// <summary>
2235 ///
2236 /// </summary>
2237 /// <param name="localID"></param>
2238 /// <param name="position"></param>
2239 /// <param name="rotation"></param>
2240 /// <returns></returns>
2241 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID,
2242 LLVector3 position,
2243 LLQuaternion rotation,
2244 LLVector3 velocity,
2245 LLVector3 rotationalvelocity,
2246 byte state)
2247 {
2248 uint ID = localID;
2249 byte[] bytes = new byte[60];
2250
2251 int i = 0;
2252 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
2253 dat.TextureEntry = new byte[0];
2254 bytes[i++] = (byte)(ID % 256);
2255 bytes[i++] = (byte)((ID >> 8) % 256);
2256 bytes[i++] = (byte)((ID >> 16) % 256);
2257 bytes[i++] = (byte)((ID >> 24) % 256);
2258 bytes[i++] = state;
2259 bytes[i++] = 0;
2260
2261 byte[] pb = position.GetBytes();
2262 Array.Copy(pb, 0, bytes, i, pb.Length);
2263 i += 12;
2264 ushort ac = 32767;
2265
2266 ushort velx, vely, velz;
2267 Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z);
2268
2269 vel = vel / 128.0f;
2270 vel.x += 1;
2271 vel.y += 1;
2272 vel.z += 1;
2273 //vel
2274 velx = (ushort)(32768 * (vel.x));
2275 vely = (ushort)(32768 * (vel.y));
2276 velz = (ushort)(32768 * (vel.z));
2277
2278 bytes[i++] = (byte)(velx % 256);
2279 bytes[i++] = (byte)((velx >> 8) % 256);
2280 bytes[i++] = (byte)(vely % 256);
2281 bytes[i++] = (byte)((vely >> 8) % 256);
2282 bytes[i++] = (byte)(velz % 256);
2283 bytes[i++] = (byte)((velz >> 8) % 256);
2284
2285 //accel
2286 bytes[i++] = (byte)(ac % 256);
2287 bytes[i++] = (byte)((ac >> 8) % 256);
2288 bytes[i++] = (byte)(ac % 256);
2289 bytes[i++] = (byte)((ac >> 8) % 256);
2290 bytes[i++] = (byte)(ac % 256);
2291 bytes[i++] = (byte)((ac >> 8) % 256);
2292
2293 ushort rw, rx, ry, rz;
2294 rw = (ushort)(32768 * (rotation.W + 1));
2295 rx = (ushort)(32768 * (rotation.X + 1));
2296 ry = (ushort)(32768 * (rotation.Y + 1));
2297 rz = (ushort)(32768 * (rotation.Z + 1));
2298
2299 //rot
2300 bytes[i++] = (byte)(rx % 256);
2301 bytes[i++] = (byte)((rx >> 8) % 256);
2302 bytes[i++] = (byte)(ry % 256);
2303 bytes[i++] = (byte)((ry >> 8) % 256);
2304 bytes[i++] = (byte)(rz % 256);
2305 bytes[i++] = (byte)((rz >> 8) % 256);
2306 bytes[i++] = (byte)(rw % 256);
2307 bytes[i++] = (byte)((rw >> 8) % 256);
2308
2309 //rotation vel
2310 ushort rvelx, rvely, rvelz;
2311 Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z);
2312
2313 rvel = rvel / 128.0f;
2314 rvel.x += 1;
2315 rvel.y += 1;
2316 rvel.z += 1;
2317 //vel
2318 rvelx = (ushort)(32768 * (rvel.x));
2319 rvely = (ushort)(32768 * (rvel.y));
2320 rvelz = (ushort)(32768 * (rvel.z));
2321
2322 bytes[i++] = (byte)(rvelx % 256);
2323 bytes[i++] = (byte)((rvelx >> 8) % 256);
2324 bytes[i++] = (byte)(rvely % 256);
2325 bytes[i++] = (byte)((rvely >> 8) % 256);
2326 bytes[i++] = (byte)(rvelz % 256);
2327 bytes[i++] = (byte)((rvelz >> 8) % 256);
2328 dat.Data = bytes;
2329
2330
2331 return dat;
2332 }
2333
2334 /// <summary>
2335 /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive)
2336 /// </summary>
2337 /// <param name="primData"></param>
2338 /// <returns></returns>
2339 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags)
2340 {
2341 ObjectUpdatePacket.ObjectDataBlock objupdate = new ObjectUpdatePacket.ObjectDataBlock();
2342 SetDefaultPrimPacketValues(objupdate);
2343 objupdate.UpdateFlags = flags;
2344 SetPrimPacketShapeData(objupdate, primShape);
2345
2346 if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass))
2347 {
2348 objupdate.Data = new byte[1];
2349 objupdate.Data[0] = primShape.State;
2350 }
2351 return objupdate;
2352 }
2353
2354 protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData)
2355 {
2356 objectData.TextureEntry = primData.TextureEntry;
2357 objectData.PCode = primData.PCode;
2358 objectData.State = primData.State;
2359 objectData.PathBegin = primData.PathBegin;
2360 objectData.PathEnd = primData.PathEnd;
2361 objectData.PathScaleX = primData.PathScaleX;
2362 objectData.PathScaleY = primData.PathScaleY;
2363 objectData.PathShearX = primData.PathShearX;
2364 objectData.PathShearY = primData.PathShearY;
2365 objectData.PathSkew = primData.PathSkew;
2366 objectData.ProfileBegin = primData.ProfileBegin;
2367 objectData.ProfileEnd = primData.ProfileEnd;
2368 objectData.Scale = primData.Scale;
2369 objectData.PathCurve = primData.PathCurve;
2370 objectData.ProfileCurve = primData.ProfileCurve;
2371 objectData.ProfileHollow = primData.ProfileHollow;
2372 objectData.PathRadiusOffset = primData.PathRadiusOffset;
2373 objectData.PathRevolutions = primData.PathRevolutions;
2374 objectData.PathTaperX = primData.PathTaperX;
2375 objectData.PathTaperY = primData.PathTaperY;
2376 objectData.PathTwist = primData.PathTwist;
2377 objectData.PathTwistBegin = primData.PathTwistBegin;
2378 objectData.ExtraParams = primData.ExtraParams;
2379 }
2380
2381 /// <summary>
2382 /// Set some default values in a ObjectUpdatePacket
2383 /// </summary>
2384 /// <param name="objdata"></param>
2385 protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata)
2386 {
2387 objdata.PSBlock = new byte[0];
2388 objdata.ExtraParams = new byte[1];
2389 objdata.MediaURL = new byte[0];
2390 objdata.NameValue = new byte[0];
2391 objdata.Text = new byte[0];
2392 objdata.TextColor = new byte[4];
2393 objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0);
2394 objdata.JointPivot = new LLVector3(0, 0, 0);
2395 objdata.Material = 3;
2396 objdata.TextureAnim = new byte[0];
2397 objdata.Sound = LLUUID.Zero;
2398 objdata.State = 0;
2399 objdata.Data = new byte[0];
2400
2401 objdata.ObjectData = new byte[60];
2402 objdata.ObjectData[46] = 128;
2403 objdata.ObjectData[47] = 63;
2404 }
2405
2406
2407 /// <summary>
2408 ///
2409 /// </summary>
2410 /// <returns></returns>
2411 public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry)
2412 {
2413 ObjectUpdatePacket.ObjectDataBlock objdata = new ObjectUpdatePacket.ObjectDataBlock();
2414 // new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i);
2415
2416 SetDefaultAvatarPacketValues(ref objdata);
2417 objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24);
2418 objdata.PathCurve = 16;
2419 objdata.ProfileCurve = 1;
2420 objdata.PathScaleX = 100;
2421 objdata.PathScaleY = 100;
2422 objdata.ParentID = 0;
2423 objdata.OwnerID = LLUUID.Zero;
2424 objdata.Scale = new LLVector3(1, 1, 1);
2425 objdata.PCode = (byte)PCode.Avatar;
2426 if (textureEntry != null)
2427 {
2428 objdata.TextureEntry = textureEntry;
2429 }
2430 LLVector3 pos = new LLVector3(objdata.ObjectData, 16);
2431 pos.X = 100f;
2432 objdata.ID = 8880000;
2433 objdata.NameValue = Helpers.StringToField("FirstName STRING RW SV Test \nLastName STRING RW SV User ");
2434 //LLVector3 pos2 = new LLVector3(100f, 100f, 23f);
2435 //objdata.FullID=user.AgentId;
2436 byte[] pb = pos.GetBytes();
2437 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
2438
2439 return objdata;
2440 }
2441
2442 /// <summary>
2443 ///
2444 /// </summary>
2445 /// <param name="objdata"></param>
2446 protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata)
2447 {
2448 objdata.PSBlock = new byte[0];
2449 objdata.ExtraParams = new byte[1];
2450 objdata.MediaURL = new byte[0];
2451 objdata.NameValue = new byte[0];
2452 objdata.Text = new byte[0];
2453 objdata.TextColor = new byte[4];
2454 objdata.JointAxisOrAnchor = new LLVector3(0, 0, 0);
2455 objdata.JointPivot = new LLVector3(0, 0, 0);
2456 objdata.Material = 4;
2457 objdata.TextureAnim = new byte[0];
2458 objdata.Sound = LLUUID.Zero;
2459 LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005"));
2460 objdata.TextureEntry = ntex.ToBytes();
2461
2462 objdata.State = 0;
2463 objdata.Data = new byte[0];
2464
2465 objdata.ObjectData = new byte[76];
2466 objdata.ObjectData[15] = 128;
2467 objdata.ObjectData[16] = 63;
2468 objdata.ObjectData[56] = 128;
2469 objdata.ObjectData[61] = 102;
2470 objdata.ObjectData[62] = 40;
2471 objdata.ObjectData[63] = 61;
2472 objdata.ObjectData[64] = 189;
2473 }
2474
2475 public void SendNameReply(LLUUID profileId, string firstname, string lastname)
2476 {
2477 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
2478 // TODO: don't create new blocks if recycling an old packet
2479 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
2480 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
2481 packet.UUIDNameBlock[0].ID = profileId;
2482 packet.UUIDNameBlock[0].FirstName = Helpers.StringToField(firstname);
2483 packet.UUIDNameBlock[0].LastName = Helpers.StringToField(lastname);
2484
2485 OutPacket(packet, ThrottleOutPacketType.Task);
2486 }
2487
2488 #endregion
2489
2490 protected virtual void RegisterLocalPacketHandlers()
2491 {
2492 AddLocalPacketHandler(PacketType.LogoutRequest, Logout);
2493 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect);
2494 AddLocalPacketHandler(PacketType.AgentCachedTexture, AgentTextureCached);
2495 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, MultipleObjUpdate);
2496 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest);
2497 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest);
2498 }
2499
2500 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
2501 {
2502 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket)Pack;
2503 // validate the agent owns the agentID and sessionID
2504 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && money.AgentData.SessionID == sender.SessionId)
2505 {
2506 handlerMoneyTransferRequest = OnMoneyTransferRequest;
2507 if (handlerMoneyTransferRequest != null)
2508 {
2509 handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID,
2510 money.MoneyData.Amount, money.MoneyData.TransactionType,
2511 Util.FieldToString(money.MoneyData.Description));
2512 }
2513
2514 return true;
2515 }
2516 else
2517 {
2518 return false;
2519 }
2520 }
2521
2522 private bool HandleParcelBuyRequest(IClientAPI sender, Packet Pack)
2523 {
2524 ParcelBuyPacket parcel = (ParcelBuyPacket)Pack;
2525 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == this.SessionId)
2526 {
2527 handlerParcelBuy = OnParcelBuy;
2528 if (handlerParcelBuy != null)
2529 {
2530 handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, parcel.Data.IsGroupOwned,
2531 parcel.Data.RemoveContribution, parcel.Data.LocalID, parcel.ParcelData.Area, parcel.ParcelData.Price,
2532 false);
2533 }
2534 return true;
2535
2536 }
2537 else
2538 {
2539 return false;
2540 }
2541
2542 }
2543
2544 private bool HandleViewerEffect(IClientAPI sender, Packet Pack)
2545 {
2546 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
2547 handlerViewerEffect = OnViewerEffect;
2548 if (handlerViewerEffect != null)
2549 {
2550 handlerViewerEffect(sender, viewer.Effect);
2551 }
2552
2553 return true;
2554 }
2555
2556 public void SendScriptQuestion(LLUUID taskID, string taskName, string ownerName, LLUUID itemID, int question)
2557 {
2558 ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
2559 scriptQuestion.Data = new ScriptQuestionPacket.DataBlock();
2560 // TODO: don't create new blocks if recycling an old packet
2561 scriptQuestion.Data.TaskID = taskID;
2562 scriptQuestion.Data.ItemID = itemID;
2563 scriptQuestion.Data.Questions = question;
2564 scriptQuestion.Data.ObjectName = Helpers.StringToField(taskName);
2565 scriptQuestion.Data.ObjectOwner = Helpers.StringToField(ownerName);
2566
2567 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
2568 }
2569
2570 protected virtual bool Logout(IClientAPI client, Packet packet)
2571 {
2572 m_log.Info("[CLIENT]: Got a logout request");
2573
2574 handlerLogout = OnLogout;
2575
2576 if (handlerLogout != null)
2577 {
2578 handlerLogout(client);
2579 }
2580
2581 return true;
2582 }
2583
2584 /// <summary>
2585 /// Send a response back to a client when it asks the asset server (via the region server) if it has
2586 /// its appearance texture cached.
2587 ///
2588 /// At the moment, we always reply that there is no cached texture.
2589 /// </summary>
2590 /// <param name="simclient"></param>
2591 /// <param name="packet"></param>
2592 /// <returns></returns>
2593 protected bool AgentTextureCached(IClientAPI simclient, Packet packet)
2594 {
2595 //Console.WriteLine("texture cached: " + packet.ToString());
2596 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
2597 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
2598 // TODO: don't create new blocks if recycling an old packet
2599 cachedresp.AgentData.AgentID = AgentId;
2600 cachedresp.AgentData.SessionID = m_sessionId;
2601 cachedresp.AgentData.SerialNum = m_cachedTextureSerial;
2602 m_cachedTextureSerial++;
2603 cachedresp.WearableData =
2604 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
2605
2606 for (int i = 0; i < cachedtex.WearableData.Length; i++)
2607 {
2608 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
2609 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
2610 cachedresp.WearableData[i].TextureID = LLUUID.Zero;
2611 cachedresp.WearableData[i].HostName = new byte[0];
2612 }
2613
2614 // Temporarily throw these packets on to the wind queue, so we can identify whether these
2615 // are somehow the source of the packet bloat.
2616 OutPacket(cachedresp, ThrottleOutPacketType.Wind);
2617 return true;
2618 }
2619
2620 protected bool MultipleObjUpdate(IClientAPI simClient, Packet packet)
2621 {
2622 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
2623 // Console.WriteLine("new multi update packet " + multipleupdate.ToString());
2624 Scene tScene = (Scene)m_scene;
2625
2626 for (int i = 0; i < multipleupdate.ObjectData.Length; i++)
2627 {
2628 MultipleObjectUpdatePacket.ObjectDataBlock block = multipleupdate.ObjectData[i];
2629
2630 // Can't act on Null Data
2631 if (block.Data != null)
2632 {
2633 uint localId = block.ObjectLocalID;
2634 SceneObjectPart part = tScene.GetSceneObjectPart(localId);
2635
2636 if (part == null)
2637 {
2638 // It's a ghost! tell the client to delete it from view.
2639 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
2640 localId);
2641 }
2642 else
2643 {
2644 LLUUID partId = part.UUID;
2645 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
2646 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
2647
2648 switch (block.Type)
2649 {
2650 case 1:
2651 LLVector3 pos1 = new LLVector3(block.Data, 0);
2652
2653 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
2654 if (handlerUpdatePrimSinglePosition != null)
2655 {
2656
2657 // Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
2658 handlerUpdatePrimSinglePosition(localId, pos1, this);
2659 }
2660 break;
2661 case 2:
2662 LLQuaternion rot1 = new LLQuaternion(block.Data, 0, true);
2663
2664 handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
2665 if (handlerUpdatePrimSingleRotation != null)
2666 {
2667
2668 //Console.WriteLine("new tab rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
2669 handlerUpdatePrimSingleRotation(localId, rot1, this);
2670 }
2671 break;
2672 case 3:
2673
2674 LLQuaternion rot2 = new LLQuaternion(block.Data, 12, true);
2675 handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
2676 if (handlerUpdatePrimSingleRotation != null)
2677 {
2678
2679 //Console.WriteLine("new mouse rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
2680 handlerUpdatePrimSingleRotation(localId, rot2, this);
2681 }
2682 break;
2683 case 5:
2684
2685 LLVector3 scale1 = new LLVector3(block.Data, 12);
2686 LLVector3 pos11 = new LLVector3(block.Data, 0);
2687
2688 handlerUpdatePrimScale = OnUpdatePrimScale;
2689 if (handlerUpdatePrimScale != null)
2690 {
2691
2692 // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
2693 handlerUpdatePrimScale(localId, scale1, this);
2694
2695
2696 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
2697 if (handlerUpdatePrimSinglePosition != null)
2698 {
2699 handlerUpdatePrimSinglePosition(localId, pos11, this);
2700 }
2701 }
2702 break;
2703 case 9:
2704 LLVector3 pos2 = new LLVector3(block.Data, 0);
2705
2706 handlerUpdateVector = OnUpdatePrimGroupPosition;
2707
2708 if (handlerUpdateVector != null)
2709 {
2710
2711 handlerUpdateVector(localId, pos2, this);
2712 }
2713 break;
2714 case 10:
2715
2716 LLQuaternion rot3 = new LLQuaternion(block.Data, 0, true);
2717
2718 handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
2719 if (handlerUpdatePrimRotation != null)
2720 {
2721
2722 // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
2723 handlerUpdatePrimRotation(localId, rot3, this);
2724 }
2725 break;
2726 case 11:
2727
2728 LLVector3 pos3 = new LLVector3(block.Data, 0);
2729 LLQuaternion rot4 = new LLQuaternion(block.Data, 12, true);
2730
2731 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
2732 if (handlerUpdatePrimGroupRotation != null)
2733 {
2734
2735 //Console.WriteLine("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
2736 // Console.WriteLine("new rotation is " + rot.X + " , " + rot.Y + " , " + rot.Z + " , " + rot.W);
2737 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
2738 }
2739 break;
2740 case 13:
2741
2742 LLVector3 scale2 = new LLVector3(block.Data, 12);
2743 LLVector3 pos4 = new LLVector3(block.Data, 0);
2744
2745 handlerUpdatePrimScale = OnUpdatePrimScale;
2746 if (handlerUpdatePrimScale != null)
2747 {
2748
2749 //Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
2750 handlerUpdatePrimScale(localId, scale2, this);
2751
2752 // Change the position based on scale (for bug number 246)
2753 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
2754 // Console.WriteLine("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
2755 if (handlerUpdatePrimSinglePosition != null)
2756 {
2757 handlerUpdatePrimSinglePosition(localId, pos4, this);
2758 }
2759 }
2760 break;
2761 case 29:
2762 LLVector3 scale5 = new LLVector3(block.Data, 12);
2763 LLVector3 pos5 = new LLVector3(block.Data, 0);
2764
2765 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
2766 if (handlerUpdatePrimGroupScale != null)
2767 {
2768
2769 // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z );
2770 handlerUpdatePrimGroupScale(localId, scale5, this);
2771 handlerUpdateVector = OnUpdatePrimGroupPosition;
2772
2773 if (handlerUpdateVector != null)
2774 {
2775
2776 handlerUpdateVector(localId, pos5, this);
2777 }
2778 }
2779 break;
2780 case 21:
2781 LLVector3 scale6 = new LLVector3(block.Data, 12);
2782 LLVector3 pos6 = new LLVector3(block.Data, 0);
2783
2784 handlerUpdatePrimScale = OnUpdatePrimScale;
2785 if (handlerUpdatePrimScale != null)
2786 {
2787 // Console.WriteLine("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
2788 handlerUpdatePrimScale(localId, scale6, this);
2789 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
2790 if (handlerUpdatePrimSinglePosition != null)
2791 {
2792 handlerUpdatePrimSinglePosition(localId, pos6, this);
2793 }
2794 }
2795 break;
2796 }
2797 }
2798 }
2799 }
2800 return true;
2801 }
2802
2803 public void RequestMapLayer()
2804 {
2805 //should be getting the map layer from the grid server
2806 //send a layer covering the 800,800 - 1200,1200 area (should be covering the requested area)
2807 MapLayerReplyPacket mapReply = (MapLayerReplyPacket)PacketPool.Instance.GetPacket(PacketType.MapLayerReply);
2808 // TODO: don't create new blocks if recycling an old packet
2809 mapReply.AgentData.AgentID = AgentId;
2810 mapReply.AgentData.Flags = 0;
2811 mapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1];
2812 mapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock();
2813 mapReply.LayerData[0].Bottom = 0;
2814 mapReply.LayerData[0].Left = 0;
2815 mapReply.LayerData[0].Top = 30000;
2816 mapReply.LayerData[0].Right = 30000;
2817 mapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-1111-9999-000000000006");
2818 OutPacket(mapReply, ThrottleOutPacketType.Land);
2819 }
2820
2821 public void RequestMapBlocksX(int minX, int minY, int maxX, int maxY)
2822 {
2823 /*
2824 IList simMapProfiles = m_gridServer.RequestMapBlocks(minX, minY, maxX, maxY);
2825 MapBlockReplyPacket mbReply = new MapBlockReplyPacket();
2826 mbReply.AgentData.AgentId = this.AgentId;
2827 int len;
2828 if (simMapProfiles == null)
2829 len = 0;
2830 else
2831 len = simMapProfiles.Count;
2832
2833 mbReply.Data = new MapBlockReplyPacket.DataBlock[len];
2834 int iii;
2835 for (iii = 0; iii < len; iii++)
2836 {
2837 Hashtable mp = (Hashtable)simMapProfiles[iii];
2838 mbReply.Data[iii] = new MapBlockReplyPacket.DataBlock();
2839 mbReply.Data[iii].Name = System.Text.Encoding.UTF8.GetBytes((string)mp["name"]);
2840 mbReply.Data[iii].Access = System.Convert.ToByte(mp["access"]);
2841 mbReply.Data[iii].Agents = System.Convert.ToByte(mp["agents"]);
2842 mbReply.Data[iii].MapImageID = new LLUUID((string)mp["map-image-id"]);
2843 mbReply.Data[iii].RegionFlags = System.Convert.ToUInt32(mp["region-flags"]);
2844 mbReply.Data[iii].WaterHeight = System.Convert.ToByte(mp["water-height"]);
2845 mbReply.Data[iii].X = System.Convert.ToUInt16(mp["x"]);
2846 mbReply.Data[iii].Y = System.Convert.ToUInt16(mp["y"]);
2847 }
2848 this.OutPacket(mbReply, ThrottleOutPacketType.Land);
2849 */
2850 }
2851
2852 public byte[] GetThrottlesPacked(float multiplier)
2853 {
2854 return m_packetQueue.GetThrottlesPacked(multiplier);
2855 }
2856
2857 public void SetChildAgentThrottle(byte[] throttles)
2858 {
2859 m_packetQueue.SetThrottleFromClient(throttles);
2860 }
2861
2862 // Previously ClientView.m_packetQueue
2863
2864 // A thread safe sequence number allocator.
2865 protected uint NextSeqNum()
2866 {
2867 // Set the sequence number
2868 uint seq = 1;
2869 lock (m_sequenceLock)
2870 {
2871 if (m_sequence >= MAX_SEQUENCE)
2872 {
2873 m_sequence = 1;
2874 }
2875 else
2876 {
2877 m_sequence++;
2878 }
2879 seq = m_sequence;
2880 }
2881 return seq;
2882 }
2883
2884 protected void AddAck(Packet Pack)
2885 {
2886 lock (m_needAck)
2887 {
2888 if (!m_needAck.ContainsKey(Pack.Header.Sequence))
2889 {
2890 try
2891 {
2892 m_needAck.Add(Pack.Header.Sequence, Pack);
2893 m_unAckedBytes += Pack.ToBytes().Length;
2894 }
2895 catch (Exception) // HACKY
2896 {
2897 // Ignore
2898 // Seems to throw a exception here occasionally
2899 // of 'duplicate key' despite being locked.
2900 // !?!?!?
2901 }
2902 }
2903 else
2904 {
2905 // Client.Log("Attempted to add a duplicate sequence number (" +
2906 // packet.Header.m_sequence + ") to the m_needAck dictionary for packet type " +
2907 // packet.Type.ToString(), Helpers.LogLevel.Warning);
2908 }
2909 }
2910 }
2911
2912 protected virtual void SetPendingAcks(ref Packet Pack)
2913 {
2914 // Append any ACKs that need to be sent out to this packet
2915 lock (m_pendingAcks)
2916 {
2917 // TODO: If we are over MAX_APPENDED_ACKS we should drain off some of these
2918 if (m_pendingAcks.Count > 0 && m_pendingAcks.Count < MAX_APPENDED_ACKS)
2919 {
2920 Pack.Header.AckList = new uint[m_pendingAcks.Count];
2921 int i = 0;
2922
2923 foreach (uint ack in m_pendingAcks.Values)
2924 {
2925 Pack.Header.AckList[i] = ack;
2926 i++;
2927 }
2928
2929 m_pendingAcks.Clear();
2930 Pack.Header.AppendedAcks = true;
2931 }
2932 }
2933 }
2934
2935 protected virtual void ProcessOutPacket(Packet Pack)
2936 {
2937 // Keep track of when this packet was sent out
2938 Pack.TickCount = System.Environment.TickCount;
2939
2940 if (!Pack.Header.Resent)
2941 {
2942 Pack.Header.Sequence = NextSeqNum();
2943
2944 if (Pack.Header.Reliable) //DIRTY HACK
2945 {
2946 AddAck(Pack); // this adds the need to ack this packet later
2947
2948 if (Pack.Type != PacketType.PacketAck && Pack.Type != PacketType.LogoutRequest)
2949 {
2950 SetPendingAcks(ref Pack);
2951 }
2952 }
2953 }
2954
2955 // Actually make the byte array and send it
2956 try
2957 {
2958 byte[] sendbuffer = Pack.ToBytes();
2959 PacketPool.Instance.ReturnPacket(Pack);
2960
2961 if (Pack.Header.Zerocoded)
2962 {
2963 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
2964 m_networkServer.SendPacketTo(ZeroOutBuffer, packetsize, SocketFlags.None, m_circuitCode);
2965 }
2966 else
2967 {
2968 //Need some extra space in case we need to add proxy information to the message later
2969 Buffer.BlockCopy(sendbuffer, 0, ZeroOutBuffer, 0, sendbuffer.Length);
2970 m_networkServer.SendPacketTo(ZeroOutBuffer, sendbuffer.Length, SocketFlags.None, m_circuitCode);
2971 }
2972 }
2973 catch (Exception e)
2974 {
2975 m_log.Warn("[client]: " +
2976 "ClientView.m_packetQueue.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " +
2977 m_userEndPoint.ToString() + " - killing thread");
2978 m_log.Error(e.ToString());
2979 Close(true);
2980 }
2981 }
2982
2983 public virtual void InPacket(Packet NewPack)
2984 {
2985 if (!m_packetProcessingEnabled && NewPack.Type != PacketType.LogoutRequest)
2986 {
2987 PacketPool.Instance.ReturnPacket(NewPack);
2988 return;
2989 }
2990
2991 // Handle appended ACKs
2992 if (NewPack != null)
2993 {
2994 if (NewPack.Header.AppendedAcks)
2995 {
2996 lock (m_needAck)
2997 {
2998 foreach (uint ackedPacketId in NewPack.Header.AckList)
2999 {
3000 Packet ackedPacket;
3001
3002 if (m_needAck.TryGetValue(ackedPacketId, out ackedPacket))
3003 {
3004 m_unAckedBytes -= ackedPacket.ToBytes().Length;
3005 m_needAck.Remove(ackedPacketId);
3006 }
3007 }
3008 }
3009 }
3010
3011 // Handle PacketAck packets
3012 if (NewPack.Type == PacketType.PacketAck)
3013 {
3014 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
3015
3016 lock (m_needAck)
3017 {
3018 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
3019 {
3020 uint ackedPackId = block.ID;
3021 Packet ackedPacket;
3022 if (m_needAck.TryGetValue(ackedPackId, out ackedPacket))
3023 {
3024 m_unAckedBytes -= ackedPacket.ToBytes().Length;
3025 m_needAck.Remove(ackedPackId);
3026 }
3027 }
3028 }
3029 }
3030 else if ((NewPack.Type == PacketType.StartPingCheck))
3031 {
3032 //reply to pingcheck
3033 StartPingCheckPacket startPing = (StartPingCheckPacket)NewPack;
3034 CompletePingCheckPacket endPing = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck);
3035 endPing.PingID.PingID = startPing.PingID.PingID;
3036 OutPacket(endPing, ThrottleOutPacketType.Task);
3037 }
3038 else
3039 {
3040 LLQueItem item = new LLQueItem();
3041 item.Packet = NewPack;
3042 item.Incoming = true;
3043 m_packetQueue.Enqueue(item);
3044 }
3045 }
3046 }
3047
3048 public virtual void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType)
3049 {
3050 if ((SynchronizeClient != null) && (!IsActive))
3051 {
3052 // Sending packet to active client's server.
3053 if (SynchronizeClient(m_scene, NewPack, m_agentId, throttlePacketType))
3054 {
3055 return;
3056 }
3057 }
3058
3059 LLQueItem item = new LLQueItem();
3060 item.Packet = NewPack;
3061 item.Incoming = false;
3062 item.throttleType = throttlePacketType; // Packet throttle type
3063 m_packetQueue.Enqueue(item);
3064 m_packetsSent++;
3065 }
3066
3067 # region Low Level Packet Methods
3068
3069 protected void ack_pack(Packet Pack)
3070 {
3071 if (Pack.Header.Reliable)
3072 {
3073 PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
3074 // TODO: don't create new blocks if recycling an old packet
3075 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
3076 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
3077 ack_it.Packets[0].ID = Pack.Header.Sequence;
3078 ack_it.Header.Reliable = false;
3079
3080 OutPacket(ack_it, ThrottleOutPacketType.Unknown);
3081 }
3082 /*
3083 if (Pack.Header.Reliable)
3084 {
3085 lock (m_pendingAcks)
3086 {
3087 uint sequence = (uint)Pack.Header.m_sequence;
3088 if (!m_pendingAcks.ContainsKey(sequence)) { m_pendingAcks[sequence] = sequence; }
3089 }
3090 }*/
3091 }
3092
3093 protected void ResendUnacked()
3094 {
3095 int now = System.Environment.TickCount;
3096
3097 lock (m_needAck)
3098 {
3099 foreach (Packet packet in m_needAck.Values)
3100 {
3101 if ((now - packet.TickCount > RESEND_TIMEOUT) && (!packet.Header.Resent))
3102 {
3103 //m_log.Debug("[NETWORK]: Resending " + packet.Type.ToString() + " packet, " +
3104 //(now - packet.TickCount) + "ms have passed");
3105
3106 packet.Header.Resent = true;
3107 OutPacket(packet, ThrottleOutPacketType.Resend);
3108 }
3109 }
3110 }
3111 }
3112
3113 protected void SendAcks()
3114 {
3115 lock (m_pendingAcks)
3116 {
3117 if (m_pendingAcks.Count > 0)
3118 {
3119 if (m_pendingAcks.Count > 250)
3120 {
3121 // FIXME: Handle the odd case where we have too many pending ACKs queued up
3122 m_log.Info("[NETWORK]: Too many ACKs queued up!");
3123 return;
3124 }
3125
3126 //m_log.Info("[NETWORK]: Sending PacketAck");
3127
3128 int i = 0;
3129 PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
3130 // TODO: don't create new blocks if recycling an old packet
3131 acks.Packets = new PacketAckPacket.PacketsBlock[m_pendingAcks.Count];
3132
3133 foreach (uint ack in m_pendingAcks.Values)
3134 {
3135 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
3136 acks.Packets[i].ID = ack;
3137 i++;
3138 }
3139
3140 acks.Header.Reliable = false;
3141 OutPacket(acks, ThrottleOutPacketType.Unknown);
3142
3143 m_pendingAcks.Clear();
3144 }
3145 }
3146 }
3147
3148 protected void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
3149 {
3150
3151 SendAcks();
3152 ResendUnacked();
3153 SendPacketStats();
3154
3155 }
3156
3157 protected void SendPacketStats()
3158 {
3159 handlerPacketStats = OnPacketStats;
3160 if (handlerPacketStats != null)
3161 {
3162 handlerPacketStats(m_packetsReceived - m_lastPacketsReceivedSentToScene, m_packetsSent - m_lastPacketsSentSentToScene, m_unAckedBytes);
3163 m_lastPacketsReceivedSentToScene = m_packetsReceived;
3164 m_lastPacketsSentSentToScene = m_packetsSent;
3165 }
3166 }
3167
3168 #endregion
3169
3170 // Previously ClientView.ProcessPackets
3171
3172 public bool AddMoney(int debit)
3173 {
3174 if (m_moneyBalance + debit >= 0)
3175 {
3176 m_moneyBalance += debit;
3177 SendMoneyBalance(LLUUID.Zero, true, Helpers.StringToField("Poof Poof!"), m_moneyBalance);
3178 return true;
3179 }
3180 else
3181 {
3182 return false;
3183 }
3184 }
3185
3186 private bool m_packetProcessingEnabled = true;
3187
3188 public bool IsActive {
3189 get { return m_packetProcessingEnabled; }
3190 set { m_packetProcessingEnabled = value; }
3191 }
3192
3193 protected void ProcessInPacket(Packet Pack)
3194 {
3195 ack_pack(Pack);
3196
3197 if (ProcessPacketMethod(Pack))
3198 {
3199 //there is a handler registered that handled this packet type
3200 return;
3201 }
3202 else
3203 {
3204 switch (Pack.Type)
3205 {
3206 #region Scene/Avatar
3207
3208 case PacketType.AvatarPropertiesRequest:
3209 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
3210
3211 handlerRequestAvatarProperties = OnRequestAvatarProperties;
3212 if (handlerRequestAvatarProperties != null)
3213 {
3214 handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID);
3215 }
3216
3217 break;
3218 case PacketType.ChatFromViewer:
3219 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
3220
3221 string fromName = String.Empty; //ClientAvatar.firstname + " " + ClientAvatar.lastname;
3222 byte[] message = inchatpack.ChatData.Message;
3223 byte type = inchatpack.ChatData.Type;
3224 LLVector3 fromPos = new LLVector3(); // ClientAvatar.Pos;
3225 LLUUID fromAgentID = AgentId;
3226
3227 int channel = inchatpack.ChatData.Channel;
3228
3229 if (OnChatFromViewer != null)
3230 {
3231 ChatFromViewerArgs args = new ChatFromViewerArgs();
3232 args.Channel = channel;
3233 args.From = fromName;
3234 args.Message = Helpers.FieldToUTF8String(message);
3235 args.Type = (ChatTypeEnum)type;
3236 args.Position = fromPos;
3237
3238 args.Scene = Scene;
3239 args.Sender = this;
3240
3241 handlerChatFromViewer = OnChatFromViewer;
3242 if (handlerChatFromViewer != null)
3243 handlerChatFromViewer(this, args);
3244 }
3245 break;
3246 case PacketType.AvatarPropertiesUpdate:
3247 AvatarPropertiesUpdatePacket Packet = (AvatarPropertiesUpdatePacket)Pack;
3248
3249 handlerUpdateAvatarProperties = OnUpdateAvatarProperties;
3250 if (handlerUpdateAvatarProperties != null)
3251 {
3252 AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = Packet.PropertiesData;
3253 UserProfileData UserProfile = new UserProfileData();
3254 UserProfile.ID = AgentId;
3255 UserProfile.AboutText = Helpers.FieldToUTF8String(Properties.AboutText);
3256 UserProfile.FirstLifeAboutText = Helpers.FieldToUTF8String(Properties.FLAboutText);
3257 UserProfile.FirstLifeImage = Properties.FLImageID;
3258 UserProfile.Image = Properties.ImageID;
3259
3260 handlerUpdateAvatarProperties(this, UserProfile);
3261 }
3262 break;
3263
3264 case PacketType.ScriptDialogReply:
3265 ScriptDialogReplyPacket rdialog = (ScriptDialogReplyPacket)Pack;
3266 int ch = rdialog.Data.ChatChannel;
3267 byte[] msg = rdialog.Data.ButtonLabel;
3268 if (OnChatFromViewer != null)
3269 {
3270 ChatFromViewerArgs args = new ChatFromViewerArgs();
3271 args.Channel = ch;
3272 args.From = String.Empty;
3273 args.Message = Helpers.FieldToUTF8String(msg);
3274 args.Type = ChatTypeEnum.Shout;
3275 args.Position = new LLVector3();
3276 args.Scene = Scene;
3277 args.Sender = this;
3278 handlerChatFromViewer2 = OnChatFromViewer;
3279 if (handlerChatFromViewer2 != null)
3280 handlerChatFromViewer2(this, args);
3281 }
3282
3283 break;
3284 case PacketType.ImprovedInstantMessage:
3285 ImprovedInstantMessagePacket msgpack = (ImprovedInstantMessagePacket)Pack;
3286 string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName);
3287 string IMmessage = Helpers.FieldToUTF8String(msgpack.MessageBlock.Message);
3288 handlerInstantMessage = OnInstantMessage;
3289
3290 if (handlerInstantMessage != null)
3291 {
3292 handlerInstantMessage(this, msgpack.AgentData.AgentID, msgpack.AgentData.SessionID,
3293 msgpack.MessageBlock.ToAgentID, msgpack.MessageBlock.ID,
3294 msgpack.MessageBlock.Timestamp, IMfromName, IMmessage,
3295 msgpack.MessageBlock.Dialog, msgpack.MessageBlock.FromGroup,
3296 msgpack.MessageBlock.Offline, msgpack.MessageBlock.ParentEstateID,
3297 msgpack.MessageBlock.Position, msgpack.MessageBlock.RegionID,
3298 msgpack.MessageBlock.BinaryBucket);
3299 }
3300 break;
3301
3302 case PacketType.AcceptFriendship:
3303 AcceptFriendshipPacket afriendpack = (AcceptFriendshipPacket)Pack;
3304
3305 // My guess is this is the folder to stick the calling card into
3306 List<LLUUID> callingCardFolders = new List<LLUUID>();
3307
3308 LLUUID agentID = afriendpack.AgentData.AgentID;
3309 LLUUID transactionID = afriendpack.TransactionBlock.TransactionID;
3310
3311 for (int fi = 0; fi < afriendpack.FolderData.Length; fi++)
3312 {
3313 callingCardFolders.Add(afriendpack.FolderData[fi].FolderID);
3314 }
3315
3316 handlerApproveFriendRequest = OnApproveFriendRequest;
3317 if (handlerApproveFriendRequest != null)
3318 {
3319 handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders);
3320 }
3321 break;
3322 case PacketType.TerminateFriendship:
3323 TerminateFriendshipPacket tfriendpack = (TerminateFriendshipPacket)Pack;
3324 LLUUID listOwnerAgentID = tfriendpack.AgentData.AgentID;
3325 LLUUID exFriendID = tfriendpack.ExBlock.OtherID;
3326
3327 handlerTerminateFriendship = OnTerminateFriendship;
3328 if (handlerTerminateFriendship != null)
3329 {
3330 handlerTerminateFriendship(this, listOwnerAgentID, exFriendID);
3331 }
3332 break;
3333 case PacketType.RezObject:
3334 RezObjectPacket rezPacket = (RezObjectPacket)Pack;
3335
3336 handlerRezObject = OnRezObject;
3337 if (handlerRezObject != null)
3338 {
3339 //rezPacket.RezData.BypassRaycast;
3340 //rezPacket.RezData.RayEnd;
3341 //rezPacket.RezData.RayEndIsIntersection;
3342 //rezPacket.RezData.RayStart;
3343 //rezPacket.RezData.RayTargetID;
3344 //rezPacket.RezData.RemoveItem;
3345 //rezPacket.RezData.RezSelected;
3346 //rezPacket.RezData.FromTaskID;
3347 //m_log.Info("[REZData]: " + rezPacket.ToString());
3348
3349 handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd,
3350 rezPacket.RezData.RayStart, rezPacket.RezData.RayTargetID,
3351 rezPacket.RezData.BypassRaycast, rezPacket.RezData.RayEndIsIntersection,
3352 rezPacket.RezData.EveryoneMask, rezPacket.RezData.GroupMask,
3353 rezPacket.RezData.NextOwnerMask, rezPacket.RezData.ItemFlags,
3354 rezPacket.RezData.RezSelected, rezPacket.RezData.RemoveItem,
3355 rezPacket.RezData.FromTaskID);
3356 }
3357 break;
3358 case PacketType.DeRezObject:
3359 handlerDeRezObject = OnDeRezObject;
3360 if (handlerDeRezObject != null)
3361 {
3362 handlerDeRezObject(Pack, this);
3363 }
3364 break;
3365 case PacketType.ModifyLand:
3366 ModifyLandPacket modify = (ModifyLandPacket)Pack;
3367 //m_log.Info("[LAND]: LAND:" + modify.ToString());
3368 if (modify.ParcelData.Length > 0)
3369 {
3370 if (OnModifyTerrain != null)
3371 {
3372 for (int i = 0; i < modify.ParcelData.Length; i++)
3373 {
3374 handlerModifyTerrain = OnModifyTerrain;
3375 if (handlerModifyTerrain != null)
3376 {
3377 handlerModifyTerrain(modify.ModifyBlock.Height, modify.ModifyBlock.Seconds,
3378 modify.ModifyBlock.BrushSize,
3379 modify.ModifyBlock.Action, modify.ParcelData[i].North,
3380 modify.ParcelData[i].West, modify.ParcelData[i].South,
3381 modify.ParcelData[i].East, this);
3382 }
3383 }
3384 }
3385 }
3386
3387 break;
3388 case PacketType.RegionHandshakeReply:
3389
3390 handlerRegionHandShakeReply = OnRegionHandShakeReply;
3391 if (handlerRegionHandShakeReply != null)
3392 {
3393 handlerRegionHandShakeReply(this);
3394 }
3395
3396 break;
3397 case PacketType.AgentWearablesRequest:
3398 handlerRequestWearables = OnRequestWearables;
3399
3400 if (handlerRequestWearables != null)
3401 {
3402 handlerRequestWearables();
3403 }
3404
3405 handlerRequestAvatarsData = OnRequestAvatarsData;
3406
3407 if (handlerRequestAvatarsData != null)
3408 {
3409 handlerRequestAvatarsData(this);
3410 }
3411
3412 break;
3413 case PacketType.AgentSetAppearance:
3414 AgentSetAppearancePacket appear = (AgentSetAppearancePacket)Pack;
3415
3416 handlerSetAppearance = OnSetAppearance;
3417 if (handlerSetAppearance != null)
3418 {
3419 // Temporarily protect ourselves from the mantis #951 failure.
3420 // However, we could do this for several other handlers where a failure isn't terminal
3421 // for the client session anyway, in order to protect ourselves against bad code in plugins
3422 try
3423 {
3424 handlerSetAppearance(appear.ObjectData.TextureEntry, appear.VisualParam);
3425 }
3426 catch (Exception e)
3427 {
3428 m_log.ErrorFormat(
3429 "[CLIENT VIEW]: AgentSetApperance packet handler threw an exception, {0}",
3430 e);
3431 }
3432 }
3433
3434 break;
3435 case PacketType.AgentIsNowWearing:
3436 if (OnAvatarNowWearing != null)
3437 {
3438 AgentIsNowWearingPacket nowWearing = (AgentIsNowWearingPacket)Pack;
3439 AvatarWearingArgs wearingArgs = new AvatarWearingArgs();
3440 for (int i = 0; i < nowWearing.WearableData.Length; i++)
3441 {
3442 AvatarWearingArgs.Wearable wearable =
3443 new AvatarWearingArgs.Wearable(nowWearing.WearableData[i].ItemID,
3444 nowWearing.WearableData[i].WearableType);
3445 wearingArgs.NowWearing.Add(wearable);
3446 }
3447
3448 handlerAvatarNowWearing = OnAvatarNowWearing;
3449 if (handlerAvatarNowWearing != null)
3450 {
3451 handlerAvatarNowWearing(this, wearingArgs);
3452 }
3453 }
3454 break;
3455 case PacketType.RezSingleAttachmentFromInv:
3456 handlerRezSingleAttachment = OnRezSingleAttachmentFromInv;
3457 if (handlerRezSingleAttachment != null)
3458 {
3459 RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
3460 handlerRezSingleAttachment(this, rez.ObjectData.ItemID,
3461 rez.ObjectData.AttachmentPt, rez.ObjectData.ItemFlags, rez.ObjectData.NextOwnerMask);
3462 }
3463
3464 break;
3465 case PacketType.DetachAttachmentIntoInv:
3466 handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv;
3467 if (handlerDetachAttachmentIntoInv != null)
3468 {
3469 DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack;
3470
3471 LLUUID itemID = detachtoInv.ObjectData.ItemID;
3472 LLUUID ATTACH_agentID = detachtoInv.ObjectData.AgentID;
3473
3474 handlerDetachAttachmentIntoInv(itemID, this);
3475 }
3476 break;
3477 case PacketType.ObjectAttach:
3478 if (OnObjectAttach != null)
3479 {
3480 ObjectAttachPacket att = (ObjectAttachPacket)Pack;
3481
3482 handlerObjectAttach = OnObjectAttach;
3483
3484 if (handlerObjectAttach != null)
3485 {
3486 if (att.ObjectData.Length > 0)
3487 {
3488 handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation);
3489 }
3490 }
3491 }
3492
3493 break;
3494 case PacketType.ObjectDetach:
3495
3496 ObjectDetachPacket dett = (ObjectDetachPacket)Pack;
3497 for (int j = 0; j < dett.ObjectData.Length; j++)
3498 {
3499 uint obj = dett.ObjectData[j].ObjectLocalID;
3500 handlerObjectDetach = OnObjectDetach;
3501 if (handlerObjectDetach != null)
3502 {
3503 handlerObjectDetach(obj,this);
3504 }
3505
3506 }
3507
3508 break;
3509 case PacketType.SetAlwaysRun:
3510 SetAlwaysRunPacket run = (SetAlwaysRunPacket)Pack;
3511
3512 handlerSetAlwaysRun = OnSetAlwaysRun;
3513 if (handlerSetAlwaysRun != null)
3514 handlerSetAlwaysRun(this, run.AgentData.AlwaysRun);
3515
3516 break;
3517 case PacketType.CompleteAgentMovement:
3518 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
3519 if (handlerCompleteMovementToRegion != null)
3520 {
3521 handlerCompleteMovementToRegion();
3522 }
3523 handlerCompleteMovementToRegion = null;
3524
3525 break;
3526 case PacketType.AgentUpdate:
3527 if (OnAgentUpdate != null)
3528 {
3529 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
3530
3531 handlerAgentUpdate = OnAgentUpdate;
3532 if (handlerAgentUpdate != null)
3533 OnAgentUpdate(this, agenUpdate);
3534
3535 handlerAgentUpdate = null;
3536 //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa);
3537 }
3538 break;
3539 case PacketType.AgentAnimation:
3540 AgentAnimationPacket AgentAni = (AgentAnimationPacket)Pack;
3541
3542 handlerStartAnim = null;
3543 handlerStopAnim = null;
3544
3545 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
3546 {
3547 if (AgentAni.AnimationList[i].StartAnim)
3548 {
3549 handlerStartAnim = OnStartAnim;
3550 if (handlerStartAnim != null)
3551 {
3552 handlerStartAnim(this, AgentAni.AnimationList[i].AnimID);
3553 }
3554 }
3555 else
3556 {
3557 handlerStopAnim = OnStopAnim;
3558 if (handlerStopAnim != null)
3559 {
3560 handlerStopAnim(this, AgentAni.AnimationList[i].AnimID);
3561 }
3562 }
3563 }
3564 break;
3565 case PacketType.AgentRequestSit:
3566 if (OnAgentRequestSit != null)
3567 {
3568 AgentRequestSitPacket agentRequestSit = (AgentRequestSitPacket)Pack;
3569
3570 handlerAgentRequestSit = OnAgentRequestSit;
3571 if (handlerAgentRequestSit != null)
3572 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
3573 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
3574 }
3575 break;
3576 case PacketType.AgentSit:
3577 if (OnAgentSit != null)
3578 {
3579 AgentSitPacket agentSit = (AgentSitPacket)Pack;
3580
3581 handlerAgentSit = OnAgentSit;
3582 if (handlerAgentSit != null)
3583 {
3584 OnAgentSit(this, agentSit.AgentData.AgentID);
3585 }
3586 }
3587 break;
3588 case PacketType.AvatarPickerRequest:
3589 AvatarPickerRequestPacket avRequestQuery = (AvatarPickerRequestPacket)Pack;
3590 AvatarPickerRequestPacket.AgentDataBlock Requestdata = avRequestQuery.AgentData;
3591 AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data;
3592 //Console.WriteLine("Agent Sends:" + Helpers.FieldToUTF8String(querydata.Name));
3593
3594 handlerAvatarPickerRequest = OnAvatarPickerRequest;
3595 if (handlerAvatarPickerRequest != null)
3596 {
3597 handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID,
3598 Helpers.FieldToUTF8String(querydata.Name));
3599 }
3600 break;
3601 case PacketType.AgentDataUpdateRequest:
3602 AgentDataUpdateRequestPacket avRequestDataUpdatePacket = (AgentDataUpdateRequestPacket)Pack;
3603
3604 handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest;
3605
3606 if (handlerAgentDataUpdateRequest != null)
3607 {
3608 handlerAgentDataUpdateRequest(this, avRequestDataUpdatePacket.AgentData.AgentID, avRequestDataUpdatePacket.AgentData.SessionID);
3609 }
3610
3611 break;
3612 case PacketType.UserInfoRequest:
3613 UserInfoRequestPacket avUserInfoRequestPacket = (UserInfoRequestPacket)Pack;
3614
3615 handlerUserInfoRequest = OnUserInfoRequest;
3616 if (handlerUserInfoRequest != null)
3617 {
3618 handlerUserInfoRequest(this, avUserInfoRequestPacket.AgentData.AgentID, avUserInfoRequestPacket.AgentData.SessionID);
3619 }
3620 break;
3621
3622 case PacketType.SetStartLocationRequest:
3623 SetStartLocationRequestPacket avSetStartLocationRequestPacket = (SetStartLocationRequestPacket)Pack;
3624
3625 if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId)
3626 {
3627 handlerSetStartLocationRequest = OnSetStartLocationRequest;
3628 if (handlerSetStartLocationRequest != null)
3629 {
3630 handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos,
3631 avSetStartLocationRequestPacket.StartLocationData.LocationLookAt,
3632 avSetStartLocationRequestPacket.StartLocationData.LocationID);
3633 }
3634 }
3635 break;
3636
3637 case PacketType.AgentThrottle:
3638 AgentThrottlePacket atpack = (AgentThrottlePacket)Pack;
3639 m_packetQueue.SetThrottleFromClient(atpack.Throttle.Throttles);
3640 break;
3641
3642 case PacketType.AgentPause:
3643 m_probesWithNoIngressPackets = 0;
3644 m_clientBlocked = true;
3645 break;
3646
3647 case PacketType.AgentResume:
3648 m_probesWithNoIngressPackets = 0;
3649 m_clientBlocked = false;
3650 SendStartPingCheck(0);
3651
3652 break;
3653
3654 #endregion
3655
3656 #region Objects/m_sceneObjects
3657
3658 case PacketType.ObjectLink:
3659 ObjectLinkPacket link = (ObjectLinkPacket)Pack;
3660 uint parentprimid = 0;
3661 List<uint> childrenprims = new List<uint>();
3662 if (link.ObjectData.Length > 1)
3663 {
3664 parentprimid = link.ObjectData[0].ObjectLocalID;
3665
3666 for (int i = 1; i < link.ObjectData.Length; i++)
3667 {
3668 childrenprims.Add(link.ObjectData[i].ObjectLocalID);
3669 }
3670 }
3671 handlerLinkObjects = OnLinkObjects;
3672 if (handlerLinkObjects != null)
3673 {
3674 handlerLinkObjects(this, parentprimid, childrenprims);
3675 }
3676 break;
3677 case PacketType.ObjectDelink:
3678 ObjectDelinkPacket delink = (ObjectDelinkPacket)Pack;
3679
3680 // It appears the prim at index 0 is not always the root prim (for
3681 // instance, when one prim of a link set has been edited independently
3682 // of the others). Therefore, we'll pass all the ids onto the delink
3683 // method for it to decide which is the root.
3684 List<uint> prims = new List<uint>();
3685 for (int i = 0; i < delink.ObjectData.Length; i++)
3686 {
3687 prims.Add(delink.ObjectData[i].ObjectLocalID);
3688 }
3689 handlerDelinkObjects = OnDelinkObjects;
3690 if (handlerDelinkObjects != null)
3691 {
3692 handlerDelinkObjects(prims);
3693 }
3694
3695 break;
3696 case PacketType.ObjectAdd:
3697 if (OnAddPrim != null)
3698 {
3699 ObjectAddPacket addPacket = (ObjectAddPacket)Pack;
3700 PrimitiveBaseShape shape = GetShapeFromAddPacket(addPacket);
3701 // m_log.Info("[REZData]: " + addPacket.ToString());
3702 //BypassRaycast: 1
3703 //RayStart: <69.79469, 158.2652, 98.40343>
3704 //RayEnd: <61.97724, 141.995, 92.58341>
3705 //RayTargetID: 00000000-0000-0000-0000-000000000000
3706
3707 handlerAddPrim = OnAddPrim;
3708 if (handlerAddPrim != null)
3709 handlerAddPrim(AgentId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection);
3710 }
3711 break;
3712 case PacketType.ObjectShape:
3713 ObjectShapePacket shapePacket = (ObjectShapePacket)Pack;
3714 handlerUpdatePrimShape = null;
3715 for (int i = 0; i < shapePacket.ObjectData.Length; i++)
3716 {
3717 handlerUpdatePrimShape = OnUpdatePrimShape;
3718 if (handlerUpdatePrimShape != null)
3719 {
3720 handlerUpdatePrimShape(m_agentId, shapePacket.ObjectData[i].ObjectLocalID,
3721 shapePacket.ObjectData[i]);
3722 }
3723 }
3724 break;
3725 case PacketType.ObjectExtraParams:
3726 ObjectExtraParamsPacket extraPar = (ObjectExtraParamsPacket)Pack;
3727
3728 handlerUpdateExtraParams = OnUpdateExtraParams;
3729 if (handlerUpdateExtraParams != null)
3730 {
3731 handlerUpdateExtraParams(m_agentId, extraPar.ObjectData[0].ObjectLocalID,
3732 extraPar.ObjectData[0].ParamType,
3733 extraPar.ObjectData[0].ParamInUse, extraPar.ObjectData[0].ParamData);
3734 }
3735 break;
3736 case PacketType.ObjectDuplicate:
3737 ObjectDuplicatePacket dupe = (ObjectDuplicatePacket)Pack;
3738 ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData;
3739
3740 handlerObjectDuplicate = null;
3741
3742 for (int i = 0; i < dupe.ObjectData.Length; i++)
3743 {
3744 handlerObjectDuplicate = OnObjectDuplicate;
3745 if (handlerObjectDuplicate != null)
3746 {
3747 handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset,
3748 dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID,
3749 AgentandGroupData.GroupID);
3750 }
3751 }
3752
3753 break;
3754
3755 case PacketType.ObjectSelect:
3756 ObjectSelectPacket incomingselect = (ObjectSelectPacket)Pack;
3757
3758 handlerObjectSelect = null;
3759
3760 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
3761 {
3762 handlerObjectSelect = OnObjectSelect;
3763 if (handlerObjectSelect != null)
3764 {
3765 handlerObjectSelect(incomingselect.ObjectData[i].ObjectLocalID, this);
3766 }
3767 }
3768 break;
3769 case PacketType.ObjectDeselect:
3770 ObjectDeselectPacket incomingdeselect = (ObjectDeselectPacket)Pack;
3771
3772 handlerObjectDeselect = null;
3773
3774 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
3775 {
3776 handlerObjectDeselect = OnObjectDeselect;
3777 if (handlerObjectDeselect != null)
3778 {
3779 OnObjectDeselect(incomingdeselect.ObjectData[i].ObjectLocalID, this);
3780 }
3781 }
3782 break;
3783 case PacketType.ObjectFlagUpdate:
3784 ObjectFlagUpdatePacket flags = (ObjectFlagUpdatePacket)Pack;
3785
3786 handlerUpdatePrimFlags = OnUpdatePrimFlags;
3787
3788 if (handlerUpdatePrimFlags != null)
3789 {
3790 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, Pack, this);
3791 }
3792 break;
3793 case PacketType.ObjectImage:
3794 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
3795
3796 handlerUpdatePrimTexture = null;
3797 for (int i = 0; i < imagePack.ObjectData.Length; i++)
3798 {
3799 handlerUpdatePrimTexture = OnUpdatePrimTexture;
3800 if (handlerUpdatePrimTexture != null)
3801 {
3802 handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID,
3803 imagePack.ObjectData[i].TextureEntry, this);
3804 }
3805 }
3806 break;
3807 case PacketType.ObjectGrab:
3808 ObjectGrabPacket grab = (ObjectGrabPacket)Pack;
3809
3810 handlerGrabObject = OnGrabObject;
3811
3812 if (handlerGrabObject != null)
3813 {
3814 handlerGrabObject(grab.ObjectData.LocalID, grab.ObjectData.GrabOffset, this);
3815 }
3816 break;
3817 case PacketType.ObjectGrabUpdate:
3818 ObjectGrabUpdatePacket grabUpdate = (ObjectGrabUpdatePacket)Pack;
3819
3820 handlerGrabUpdate = OnGrabUpdate;
3821
3822 if (handlerGrabUpdate != null)
3823 {
3824 handlerGrabUpdate(grabUpdate.ObjectData.ObjectID, grabUpdate.ObjectData.GrabOffsetInitial,
3825 grabUpdate.ObjectData.GrabPosition, this);
3826 }
3827 break;
3828 case PacketType.ObjectDeGrab:
3829 ObjectDeGrabPacket deGrab = (ObjectDeGrabPacket)Pack;
3830
3831 handlerDeGrabObject = OnDeGrabObject;
3832 if (handlerDeGrabObject != null)
3833 {
3834 handlerDeGrabObject(deGrab.ObjectData.LocalID, this);
3835 }
3836 break;
3837 case PacketType.ObjectDescription:
3838 ObjectDescriptionPacket objDes = (ObjectDescriptionPacket)Pack;
3839
3840 handlerObjectDescription = null;
3841
3842 for (int i = 0; i < objDes.ObjectData.Length; i++)
3843 {
3844 handlerObjectDescription = OnObjectDescription;
3845 if (handlerObjectDescription != null)
3846 {
3847 handlerObjectDescription(this, objDes.ObjectData[i].LocalID,
3848 Util.FieldToString(objDes.ObjectData[i].Description));
3849 }
3850 }
3851 break;
3852 case PacketType.ObjectName:
3853 ObjectNamePacket objName = (ObjectNamePacket)Pack;
3854
3855 handlerObjectName = null;
3856 for (int i = 0; i < objName.ObjectData.Length; i++)
3857 {
3858 handlerObjectName = OnObjectName;
3859 if (handlerObjectName != null)
3860 {
3861 handlerObjectName(this, objName.ObjectData[i].LocalID,
3862 Util.FieldToString(objName.ObjectData[i].Name));
3863 }
3864 }
3865 break;
3866 case PacketType.ObjectPermissions:
3867 if (OnObjectPermissions != null)
3868 {
3869 ObjectPermissionsPacket newobjPerms = (ObjectPermissionsPacket)Pack;
3870
3871 LLUUID AgentID = newobjPerms.AgentData.AgentID;
3872 LLUUID SessionID = newobjPerms.AgentData.SessionID;
3873
3874 handlerObjectPermissions = null;
3875
3876 for (int i = 0; i < newobjPerms.ObjectData.Length; i++)
3877 {
3878 ObjectPermissionsPacket.ObjectDataBlock permChanges = newobjPerms.ObjectData[i];
3879
3880 byte field = permChanges.Field;
3881 uint localID = permChanges.ObjectLocalID;
3882 uint mask = permChanges.Mask;
3883 byte set = permChanges.Set;
3884
3885 handlerObjectPermissions = OnObjectPermissions;
3886
3887 if (handlerObjectPermissions != null)
3888 OnObjectPermissions(this, AgentID, SessionID, field, localID, mask, set);
3889 }
3890 }
3891
3892 // Here's our data,
3893 // PermField contains the field the info goes into
3894 // PermField determines which mask we're changing
3895 //
3896 // chmask is the mask of the change
3897 // setTF is whether we're adding it or taking it away
3898 //
3899 // objLocalID is the localID of the object.
3900
3901 // Unfortunately, we have to pass the event the packet because objData is an array
3902 // That means multiple object perms may be updated in a single packet.
3903
3904 break;
3905
3906 case PacketType.Undo:
3907 UndoPacket undoitem = (UndoPacket)Pack;
3908 if (undoitem.ObjectData.Length > 0)
3909 {
3910 for (int i = 0; i < undoitem.ObjectData.Length; i++)
3911 {
3912 LLUUID objiD = undoitem.ObjectData[i].ObjectID;
3913 handlerOnUndo = OnUndo;
3914 if (handlerOnUndo != null)
3915 {
3916 handlerOnUndo(this, objiD);
3917 }
3918
3919 }
3920 }
3921 break;
3922 case PacketType.ObjectDuplicateOnRay:
3923 ObjectDuplicateOnRayPacket dupeOnRay = (ObjectDuplicateOnRayPacket)Pack;
3924
3925 handlerObjectDuplicateOnRay = null;
3926
3927
3928 for (int i = 0; i < dupeOnRay.ObjectData.Length; i++)
3929 {
3930 handlerObjectDuplicateOnRay = OnObjectDuplicateOnRay;
3931 if (handlerObjectDuplicateOnRay != null)
3932 {
3933 handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags,
3934 dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd,
3935 dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection,
3936 dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates);
3937 }
3938 }
3939
3940 break;
3941 case PacketType.RequestObjectPropertiesFamily:
3942 //This powers the little tooltip that appears when you move your mouse over an object
3943 RequestObjectPropertiesFamilyPacket packToolTip = (RequestObjectPropertiesFamilyPacket)Pack;
3944
3945 RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData;
3946
3947 handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily;
3948
3949 if (handlerRequestObjectPropertiesFamily != null)
3950 {
3951 handlerRequestObjectPropertiesFamily(this, m_agentId, packObjBlock.RequestFlags,
3952 packObjBlock.ObjectID);
3953 }
3954
3955 break;
3956 case PacketType.ObjectIncludeInSearch:
3957 //This lets us set objects to appear in search (stuff like DataSnapshot, etc)
3958 ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack;
3959 handlerObjectIncludeInSearch = null;
3960
3961 foreach (ObjectIncludeInSearchPacket.ObjectDataBlock objData in packInSearch.ObjectData) {
3962 bool inSearch = objData.IncludeInSearch;
3963 uint localID = objData.ObjectLocalID;
3964
3965 handlerObjectIncludeInSearch = OnObjectIncludeInSearch;
3966
3967 if (handlerObjectIncludeInSearch != null) {
3968 handlerObjectIncludeInSearch(this, inSearch, localID);
3969 }
3970 }
3971 break;
3972
3973 case PacketType.ScriptAnswerYes:
3974 ScriptAnswerYesPacket scriptAnswer = (ScriptAnswerYesPacket)Pack;
3975
3976 handlerScriptAnswer = OnScriptAnswer;
3977 if (handlerScriptAnswer != null)
3978 {
3979 handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions);
3980 }
3981 break;
3982
3983 #endregion
3984
3985 #region Inventory/Asset/Other related packets
3986
3987 case PacketType.RequestImage:
3988 RequestImagePacket imageRequest = (RequestImagePacket)Pack;
3989 //Console.WriteLine("image request: " + Pack.ToString());
3990
3991 handlerTextureRequest = null;
3992
3993 for (int i = 0; i < imageRequest.RequestImage.Length; i++)
3994 {
3995 if (OnRequestTexture != null)
3996 {
3997 TextureRequestArgs args = new TextureRequestArgs();
3998 args.RequestedAssetID = imageRequest.RequestImage[i].Image;
3999 args.DiscardLevel = imageRequest.RequestImage[i].DiscardLevel;
4000 args.PacketNumber = imageRequest.RequestImage[i].Packet;
4001 args.Priority = imageRequest.RequestImage[i].DownloadPriority;
4002
4003 handlerTextureRequest = OnRequestTexture;
4004
4005 if (handlerTextureRequest != null)
4006 OnRequestTexture(this, args);
4007 }
4008 }
4009 break;
4010 case PacketType.TransferRequest:
4011 //Console.WriteLine("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
4012 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
4013 m_assetCache.AddAssetRequest(this, transfer);
4014 /* RequestAsset = OnRequestAsset;
4015 if (RequestAsset != null)
4016 {
4017 RequestAsset(this, transfer);
4018 }*/
4019 break;
4020 case PacketType.AssetUploadRequest:
4021 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
4022 // Console.WriteLine("upload request " + Pack.ToString());
4023 // Console.WriteLine("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
4024 LLUUID temp = LLUUID.Combine(request.AssetBlock.TransactionID, SecureSessionId);
4025
4026 handlerAssetUploadRequest = OnAssetUploadRequest;
4027
4028 if (handlerAssetUploadRequest != null)
4029 {
4030 handlerAssetUploadRequest(this, temp,
4031 request.AssetBlock.TransactionID, request.AssetBlock.Type,
4032 request.AssetBlock.AssetData, request.AssetBlock.StoreLocal,
4033 request.AssetBlock.Tempfile);
4034 }
4035 break;
4036 case PacketType.RequestXfer:
4037 RequestXferPacket xferReq = (RequestXferPacket)Pack;
4038
4039 handlerRequestXfer = OnRequestXfer;
4040
4041 if (handlerRequestXfer != null)
4042 {
4043 handlerRequestXfer(this, xferReq.XferID.ID, Util.FieldToString(xferReq.XferID.Filename));
4044 }
4045 break;
4046 case PacketType.SendXferPacket:
4047 SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack;
4048
4049 handlerXferReceive = OnXferReceive;
4050 if (handlerXferReceive != null)
4051 {
4052 handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data);
4053 }
4054 break;
4055 case PacketType.ConfirmXferPacket:
4056 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
4057
4058 handlerConfirmXfer = OnConfirmXfer;
4059 if (handlerConfirmXfer != null)
4060 {
4061 handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
4062 }
4063 break;
4064 case PacketType.CreateInventoryFolder:
4065 CreateInventoryFolderPacket invFolder = (CreateInventoryFolderPacket)Pack;
4066
4067 handlerCreateInventoryFolder = OnCreateNewInventoryFolder;
4068 if (handlerCreateInventoryFolder != null)
4069 {
4070 handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID,
4071 (ushort)invFolder.FolderData.Type,
4072 Util.FieldToString(invFolder.FolderData.Name),
4073 invFolder.FolderData.ParentID);
4074 }
4075 break;
4076 case PacketType.UpdateInventoryFolder:
4077 if (OnUpdateInventoryFolder != null)
4078 {
4079 UpdateInventoryFolderPacket invFolderx = (UpdateInventoryFolderPacket)Pack;
4080
4081 handlerUpdateInventoryFolder = null;
4082
4083 for (int i = 0; i < invFolderx.FolderData.Length; i++)
4084 {
4085 handlerUpdateInventoryFolder = OnUpdateInventoryFolder;
4086 if (handlerUpdateInventoryFolder != null)
4087 {
4088 OnUpdateInventoryFolder(this, invFolderx.FolderData[i].FolderID,
4089 (ushort)invFolderx.FolderData[i].Type,
4090 Util.FieldToString(invFolderx.FolderData[i].Name),
4091 invFolderx.FolderData[i].ParentID);
4092 }
4093 }
4094 }
4095 break;
4096 case PacketType.MoveInventoryFolder:
4097 if (OnMoveInventoryFolder != null)
4098 {
4099 MoveInventoryFolderPacket invFoldery = (MoveInventoryFolderPacket)Pack;
4100
4101 handlerMoveInventoryFolder = null;
4102
4103 for (int i = 0; i < invFoldery.InventoryData.Length; i++)
4104 {
4105 handlerMoveInventoryFolder = OnMoveInventoryFolder;
4106 if (handlerMoveInventoryFolder != null)
4107 {
4108 OnMoveInventoryFolder(this, invFoldery.InventoryData[i].FolderID,
4109 invFoldery.InventoryData[i].ParentID);
4110 }
4111 }
4112 }
4113 break;
4114 case PacketType.CreateInventoryItem:
4115 CreateInventoryItemPacket createItem = (CreateInventoryItemPacket)Pack;
4116
4117 handlerCreateNewInventoryItem = OnCreateNewInventoryItem;
4118 if (handlerCreateNewInventoryItem != null)
4119 {
4120 handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID,
4121 createItem.InventoryBlock.FolderID,
4122 createItem.InventoryBlock.CallbackID,
4123 Util.FieldToString(createItem.InventoryBlock.Description),
4124 Util.FieldToString(createItem.InventoryBlock.Name),
4125 createItem.InventoryBlock.InvType,
4126 createItem.InventoryBlock.Type,
4127 createItem.InventoryBlock.WearableType,
4128 createItem.InventoryBlock.NextOwnerMask);
4129 }
4130 break;
4131 case PacketType.FetchInventory:
4132 if (OnFetchInventory != null)
4133 {
4134 FetchInventoryPacket FetchInventoryx = (FetchInventoryPacket)Pack;
4135
4136 handlerFetchInventory = null;
4137
4138 for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++)
4139 {
4140 handlerFetchInventory = OnFetchInventory;
4141
4142 if (handlerFetchInventory != null)
4143 {
4144 OnFetchInventory(this, FetchInventoryx.InventoryData[i].ItemID,
4145 FetchInventoryx.InventoryData[i].OwnerID);
4146 }
4147 }
4148 }
4149 break;
4150 case PacketType.FetchInventoryDescendents:
4151 FetchInventoryDescendentsPacket Fetch = (FetchInventoryDescendentsPacket)Pack;
4152
4153 handlerFetchInventoryDescendents = OnFetchInventoryDescendents;
4154 if (handlerFetchInventoryDescendents != null)
4155 {
4156 handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID,
4157 Fetch.InventoryData.FetchFolders, Fetch.InventoryData.FetchItems,
4158 Fetch.InventoryData.SortOrder);
4159 }
4160 break;
4161 case PacketType.PurgeInventoryDescendents:
4162 PurgeInventoryDescendentsPacket Purge = (PurgeInventoryDescendentsPacket)Pack;
4163
4164 handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents;
4165 if (handlerPurgeInventoryDescendents != null)
4166 {
4167 handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID);
4168 }
4169 break;
4170 case PacketType.UpdateInventoryItem:
4171 UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)Pack;
4172 if (OnUpdateInventoryItem != null)
4173 {
4174 handlerUpdateInventoryItem = null;
4175 for (int i = 0; i < update.InventoryData.Length; i++)
4176 {
4177 handlerUpdateInventoryItem = OnUpdateInventoryItem;
4178
4179 if (handlerUpdateInventoryItem != null)
4180 {
4181 InventoryItemBase itemUpd = new InventoryItemBase();
4182 itemUpd.ID = update.InventoryData[i].ItemID;
4183 itemUpd.Name = Util.FieldToString(update.InventoryData[i].Name);
4184 itemUpd.Description = Util.FieldToString(update.InventoryData[i].Description);
4185 itemUpd.GroupID = update.InventoryData[i].GroupID;
4186 itemUpd.GroupOwned = update.InventoryData[i].GroupOwned;
4187 itemUpd.NextPermissions = update.InventoryData[i].NextOwnerMask;
4188 itemUpd.EveryOnePermissions = update.InventoryData[i].EveryoneMask;
4189 itemUpd.CreationDate = update.InventoryData[i].CreationDate;
4190 itemUpd.Folder = update.InventoryData[i].FolderID;
4191 itemUpd.InvType = update.InventoryData[i].InvType;
4192 itemUpd.SalePrice = update.InventoryData[i].SalePrice;
4193 itemUpd.SaleType = update.InventoryData[i].SaleType;
4194 itemUpd.Flags = update.InventoryData[i].Flags;
4195 /*
4196 OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID,
4197 update.InventoryData[i].ItemID,
4198 Util.FieldToString(update.InventoryData[i].Name),
4199 Util.FieldToString(update.InventoryData[i].Description),
4200 update.InventoryData[i].NextOwnerMask);
4201 */
4202 OnUpdateInventoryItem(this, update.InventoryData[i].TransactionID,
4203 update.InventoryData[i].ItemID,
4204 itemUpd);
4205 }
4206 }
4207 }
4208 //Console.WriteLine(Pack.ToString());
4209 /*for (int i = 0; i < update.InventoryData.Length; i++)
4210 {
4211 if (update.InventoryData[i].TransactionID != LLUUID.Zero)
4212 {
4213 AssetBase asset = m_assetCache.GetAsset(update.InventoryData[i].TransactionID.Combine(this.SecureSessionId));
4214 if (asset != null)
4215 {
4216 // Console.WriteLine("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache");
4217 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
4218 }
4219 else
4220 {
4221 asset = this.UploadAssets.AddUploadToAssetCache(update.InventoryData[i].TransactionID);
4222 if (asset != null)
4223 {
4224 //Console.WriteLine("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache");
4225 m_inventoryCache.UpdateInventoryItemAsset(this, update.InventoryData[i].ItemID, asset);
4226 }
4227 else
4228 {
4229 //Console.WriteLine("trying to update inventory item, but asset is null");
4230 }
4231 }
4232 }
4233 else
4234 {
4235 m_inventoryCache.UpdateInventoryItemDetails(this, update.InventoryData[i].ItemID, update.InventoryData[i]); ;
4236 }
4237 }*/
4238 break;
4239 case PacketType.CopyInventoryItem:
4240 CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack;
4241
4242 handlerCopyInventoryItem = null;
4243 if (OnCopyInventoryItem != null)
4244 {
4245 foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData)
4246 {
4247 handlerCopyInventoryItem = OnCopyInventoryItem;
4248 if (handlerCopyInventoryItem != null)
4249 {
4250 handlerCopyInventoryItem(this, datablock.CallbackID, datablock.OldAgentID,
4251 datablock.OldItemID, datablock.NewFolderID,
4252 Util.FieldToString(datablock.NewName));
4253 }
4254 }
4255 }
4256 break;
4257 case PacketType.MoveInventoryItem:
4258 MoveInventoryItemPacket moveitem = (MoveInventoryItemPacket)Pack;
4259 if (OnMoveInventoryItem != null)
4260 {
4261 handlerMoveInventoryItem = null;
4262 foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData)
4263 {
4264 handlerMoveInventoryItem = OnMoveInventoryItem;
4265 if (handlerMoveInventoryItem != null)
4266 {
4267 handlerMoveInventoryItem(this, datablock.FolderID, datablock.ItemID, datablock.Length,
4268 Util.FieldToString(datablock.NewName));
4269 }
4270 }
4271 }
4272 break;
4273 case PacketType.RemoveInventoryItem:
4274 RemoveInventoryItemPacket removeItem = (RemoveInventoryItemPacket)Pack;
4275 if (OnRemoveInventoryItem != null)
4276 {
4277 handlerRemoveInventoryItem = null;
4278 foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData)
4279 {
4280 handlerRemoveInventoryItem = OnRemoveInventoryItem;
4281 if (handlerRemoveInventoryItem != null)
4282 {
4283 handlerRemoveInventoryItem(this, datablock.ItemID);
4284 }
4285 }
4286 }
4287 break;
4288 case PacketType.RemoveInventoryFolder:
4289 RemoveInventoryFolderPacket removeFolder = (RemoveInventoryFolderPacket)Pack;
4290 if (OnRemoveInventoryFolder != null)
4291 {
4292 handlerRemoveInventoryFolder = null;
4293 foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData)
4294 {
4295 handlerRemoveInventoryFolder = OnRemoveInventoryFolder;
4296
4297 if (handlerRemoveInventoryFolder != null)
4298 {
4299 handlerRemoveInventoryFolder(this, datablock.FolderID);
4300 }
4301 }
4302 }
4303 break;
4304 case PacketType.RequestTaskInventory:
4305 RequestTaskInventoryPacket requesttask = (RequestTaskInventoryPacket)Pack;
4306
4307 handlerRequestTaskInventory = OnRequestTaskInventory;
4308 if (handlerRequestTaskInventory != null)
4309 {
4310 handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID);
4311 }
4312 break;
4313 case PacketType.UpdateTaskInventory:
4314 UpdateTaskInventoryPacket updatetask = (UpdateTaskInventoryPacket)Pack;
4315 if (OnUpdateTaskInventory != null)
4316 {
4317 if (updatetask.UpdateData.Key == 0)
4318 {
4319 handlerUpdateTaskInventory = OnUpdateTaskInventory;
4320 if (handlerUpdateTaskInventory != null)
4321 {
4322 handlerUpdateTaskInventory(this, updatetask.InventoryData.ItemID,
4323 updatetask.InventoryData.FolderID, updatetask.UpdateData.LocalID);
4324 }
4325 }
4326 }
4327
4328 break;
4329
4330 case PacketType.RemoveTaskInventory:
4331
4332 RemoveTaskInventoryPacket removeTask = (RemoveTaskInventoryPacket)Pack;
4333
4334 handlerRemoveTaskItem = OnRemoveTaskItem;
4335
4336 if (handlerRemoveTaskItem != null)
4337 {
4338 handlerRemoveTaskItem(this, removeTask.InventoryData.ItemID, removeTask.InventoryData.LocalID);
4339 }
4340
4341 break;
4342
4343 case PacketType.MoveTaskInventory:
4344
4345 MoveTaskInventoryPacket moveTaskInventoryPacket = (MoveTaskInventoryPacket)Pack;
4346
4347 handlerMoveTaskItem = OnMoveTaskItem;
4348
4349 if (handlerMoveTaskItem != null)
4350 {
4351 handlerMoveTaskItem(
4352 this, moveTaskInventoryPacket.AgentData.FolderID,
4353 moveTaskInventoryPacket.InventoryData.LocalID,
4354 moveTaskInventoryPacket.InventoryData.ItemID);
4355 }
4356
4357 break;
4358
4359 case PacketType.RezScript:
4360
4361 //Console.WriteLine(Pack.ToString());
4362 RezScriptPacket rezScriptx = (RezScriptPacket)Pack;
4363
4364 handlerRezScript = OnRezScript;
4365
4366 if (handlerRezScript != null)
4367 {
4368 handlerRezScript(this, rezScriptx.InventoryBlock.ItemID, rezScriptx.UpdateBlock.ObjectLocalID);
4369 }
4370 break;
4371
4372 case PacketType.MapLayerRequest:
4373 RequestMapLayer();
4374 break;
4375 case PacketType.MapBlockRequest:
4376 MapBlockRequestPacket MapRequest = (MapBlockRequestPacket)Pack;
4377
4378 handlerRequestMapBlocks = OnRequestMapBlocks;
4379 if (handlerRequestMapBlocks != null)
4380 {
4381 handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY,
4382 MapRequest.PositionData.MaxX, MapRequest.PositionData.MaxY);
4383 }
4384 break;
4385 case PacketType.MapNameRequest:
4386 MapNameRequestPacket map = (MapNameRequestPacket)Pack;
4387 string mapName = UTF8Encoding.UTF8.GetString(map.NameData.Name, 0,
4388 map.NameData.Name.Length - 1);
4389 handlerMapNameRequest = OnMapNameRequest;
4390 if (handlerMapNameRequest != null)
4391 {
4392 handlerMapNameRequest(this, mapName);
4393 }
4394 break;
4395 case PacketType.TeleportLandmarkRequest:
4396 TeleportLandmarkRequestPacket tpReq = (TeleportLandmarkRequestPacket)Pack;
4397 LLUUID lmid = tpReq.Info.LandmarkID;
4398 AssetLandmark lm;
4399 if (lmid != LLUUID.Zero)
4400 {
4401 AssetBase lma = m_assetCache.GetAsset(lmid, false);
4402
4403 if (lma == null)
4404 {
4405 // Failed to find landmark
4406
4407 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
4408 tpCancel.Info.SessionID = tpReq.Info.SessionID;
4409 tpCancel.Info.AgentID = tpReq.Info.AgentID;
4410 OutPacket(tpCancel, ThrottleOutPacketType.Task);
4411 }
4412
4413
4414 try
4415 {
4416 lm = new AssetLandmark(lma);
4417 }
4418 catch (NullReferenceException)
4419 {
4420 // asset not found generates null ref inside the assetlandmark constructor.
4421 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
4422 tpCancel.Info.SessionID = tpReq.Info.SessionID;
4423 tpCancel.Info.AgentID = tpReq.Info.AgentID;
4424 OutPacket(tpCancel, ThrottleOutPacketType.Task);
4425 break;
4426 }
4427 }
4428 else
4429 {
4430
4431 // Teleport home request
4432 handlerTeleportHomeRequest = OnTeleportHomeRequest;
4433 if (handlerTeleportHomeRequest != null)
4434 {
4435 handlerTeleportHomeRequest(this.AgentId,this);
4436 }
4437 break;
4438 }
4439
4440 handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest;
4441 if (handlerTeleportLandmarkRequest != null)
4442 {
4443 handlerTeleportLandmarkRequest(this, lm.RegionHandle, lm.Position);
4444 }
4445 else
4446 {
4447 //no event handler so cancel request
4448
4449
4450 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
4451 tpCancel.Info.AgentID = tpReq.Info.AgentID;
4452 tpCancel.Info.SessionID = tpReq.Info.SessionID;
4453 OutPacket(tpCancel, ThrottleOutPacketType.Task);
4454
4455 }
4456 break;
4457 case PacketType.TeleportLocationRequest:
4458 TeleportLocationRequestPacket tpLocReq = (TeleportLocationRequestPacket)Pack;
4459 // Console.WriteLine(tpLocReq.ToString());
4460
4461 handlerTeleportLocationRequest = OnTeleportLocationRequest;
4462 if (handlerTeleportLocationRequest != null)
4463 {
4464 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
4465 tpLocReq.Info.LookAt, 16);
4466 }
4467 else
4468 {
4469 //no event handler so cancel request
4470 TeleportCancelPacket tpCancel = (TeleportCancelPacket)PacketPool.Instance.GetPacket(PacketType.TeleportCancel);
4471 tpCancel.Info.SessionID = tpLocReq.AgentData.SessionID;
4472 tpCancel.Info.AgentID = tpLocReq.AgentData.AgentID;
4473 OutPacket(tpCancel, ThrottleOutPacketType.Task);
4474 }
4475 break;
4476
4477 #endregion
4478
4479
4480 case PacketType.UUIDNameRequest:
4481 UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack;
4482 foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock)
4483 {
4484 handlerNameRequest = OnNameFromUUIDRequest;
4485 if (handlerNameRequest != null)
4486 {
4487 handlerNameRequest(UUIDBlock.ID, this);
4488 }
4489 }
4490 break;
4491
4492 #region Parcel related packets
4493
4494 case PacketType.ParcelAccessListRequest:
4495 ParcelAccessListRequestPacket requestPacket = (ParcelAccessListRequestPacket)Pack;
4496
4497 handlerParcelAccessListRequest = OnParcelAccessListRequest;
4498
4499 if (handlerParcelAccessListRequest != null)
4500 {
4501 handlerParcelAccessListRequest(requestPacket.AgentData.AgentID, requestPacket.AgentData.SessionID,
4502 requestPacket.Data.Flags, requestPacket.Data.SequenceID,
4503 requestPacket.Data.LocalID, this);
4504 }
4505 break;
4506
4507 case PacketType.ParcelAccessListUpdate:
4508 ParcelAccessListUpdatePacket updatePacket = (ParcelAccessListUpdatePacket)Pack;
4509 List<ParcelManager.ParcelAccessEntry> entries = new List<ParcelManager.ParcelAccessEntry>();
4510 foreach (ParcelAccessListUpdatePacket.ListBlock block in updatePacket.List)
4511 {
4512 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
4513 entry.AgentID = block.ID;
4514 entry.Flags = (ParcelManager.AccessList)block.Flags;
4515 entry.Time = new DateTime();
4516 entries.Add(entry);
4517 }
4518
4519 handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest;
4520 if (handlerParcelAccessListUpdateRequest != null)
4521 {
4522 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID,
4523 updatePacket.AgentData.SessionID, updatePacket.Data.Flags,
4524 updatePacket.Data.LocalID, entries, this);
4525 }
4526 break;
4527 case PacketType.ParcelPropertiesRequest:
4528
4529 ParcelPropertiesRequestPacket propertiesRequest = (ParcelPropertiesRequestPacket)Pack;
4530
4531 handlerParcelPropertiesRequest = OnParcelPropertiesRequest;
4532 if (handlerParcelPropertiesRequest != null)
4533 {
4534 handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West),
4535 (int)Math.Round(propertiesRequest.ParcelData.South),
4536 (int)Math.Round(propertiesRequest.ParcelData.East),
4537 (int)Math.Round(propertiesRequest.ParcelData.North),
4538 propertiesRequest.ParcelData.SequenceID,
4539 propertiesRequest.ParcelData.SnapSelection, this);
4540 }
4541 break;
4542 case PacketType.ParcelDivide:
4543 ParcelDividePacket landDivide = (ParcelDividePacket)Pack;
4544
4545 handlerParcelDivideRequest = OnParcelDivideRequest;
4546 if (handlerParcelDivideRequest != null)
4547 {
4548 handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West),
4549 (int)Math.Round(landDivide.ParcelData.South),
4550 (int)Math.Round(landDivide.ParcelData.East),
4551 (int)Math.Round(landDivide.ParcelData.North), this);
4552 }
4553 break;
4554 case PacketType.ParcelJoin:
4555 ParcelJoinPacket landJoin = (ParcelJoinPacket)Pack;
4556
4557 handlerParcelJoinRequest = OnParcelJoinRequest;
4558
4559 if (handlerParcelJoinRequest != null)
4560 {
4561 handlerParcelJoinRequest((int)Math.Round(landJoin.ParcelData.West),
4562 (int)Math.Round(landJoin.ParcelData.South),
4563 (int)Math.Round(landJoin.ParcelData.East),
4564 (int)Math.Round(landJoin.ParcelData.North), this);
4565 }
4566 break;
4567 case PacketType.ParcelPropertiesUpdate:
4568 ParcelPropertiesUpdatePacket parcelPropertiesPacket = (ParcelPropertiesUpdatePacket)Pack;
4569
4570 handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest;
4571
4572 if (handlerParcelPropertiesUpdateRequest != null)
4573 {
4574 handlerParcelPropertiesUpdateRequest(parcelPropertiesPacket, this);
4575 }
4576 break;
4577 case PacketType.ParcelSelectObjects:
4578 ParcelSelectObjectsPacket selectPacket = (ParcelSelectObjectsPacket)Pack;
4579
4580 handlerParcelSelectObjects = OnParcelSelectObjects;
4581
4582 if (handlerParcelSelectObjects != null)
4583 {
4584 handlerParcelSelectObjects(selectPacket.ParcelData.LocalID,
4585 Convert.ToInt32(selectPacket.ParcelData.ReturnType), this);
4586 }
4587 break;
4588 case PacketType.ParcelObjectOwnersRequest:
4589 //Console.WriteLine(Pack.ToString());
4590 ParcelObjectOwnersRequestPacket reqPacket = (ParcelObjectOwnersRequestPacket)Pack;
4591
4592 handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest;
4593
4594 if (handlerParcelObjectOwnerRequest != null)
4595 {
4596 handlerParcelObjectOwnerRequest(reqPacket.ParcelData.LocalID, this);
4597 }
4598 break;
4599
4600 #endregion
4601
4602 #region Estate Packets
4603
4604 case PacketType.EstateOwnerMessage:
4605 EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack;
4606
4607 handlerEstateOwnerMessage = OnEstateOwnerMessage;
4608
4609 if (handlerEstateOwnerMessage != null)
4610 {
4611 handlerEstateOwnerMessage(messagePacket, this);
4612 }
4613 break;
4614 case PacketType.RequestRegionInfo:
4615 RequestRegionInfoPacket.AgentDataBlock mPacket = ((RequestRegionInfoPacket)Pack).AgentData;
4616
4617 handlerRegionInfoRequest = OnRegionInfoRequest;
4618 if (handlerRegionInfoRequest != null)
4619 {
4620 handlerRegionInfoRequest(this, mPacket.SessionID);
4621 }
4622 break;
4623 case PacketType.EstateCovenantRequest:
4624
4625 EstateCovenantRequestPacket.AgentDataBlock epack =
4626 ((EstateCovenantRequestPacket)Pack).AgentData;
4627
4628 handlerEstateCovenantRequest = OnEstateCovenantRequest;
4629 if (handlerEstateCovenantRequest != null)
4630 {
4631 handlerEstateCovenantRequest(this, epack.SessionID);
4632 }
4633 break;
4634
4635 #endregion
4636
4637 #region GodPackets
4638
4639 case PacketType.RequestGodlikePowers:
4640 RequestGodlikePowersPacket rglpPack = (RequestGodlikePowersPacket)Pack;
4641 RequestGodlikePowersPacket.RequestBlockBlock rblock = rglpPack.RequestBlock;
4642 LLUUID token = rblock.Token;
4643
4644 RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData;
4645
4646 handlerReqGodlikePowers = OnRequestGodlikePowers;
4647
4648 if (handlerReqGodlikePowers != null)
4649 {
4650 handlerReqGodlikePowers(ablock.AgentID, ablock.SessionID, token, rblock.Godlike, this);
4651 }
4652
4653 break;
4654 case PacketType.GodKickUser:
4655 m_log.Warn("[CLIENT]: unhandled GodKickUser packet");
4656
4657 GodKickUserPacket gkupack = (GodKickUserPacket)Pack;
4658
4659 if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID)
4660 {
4661 handlerGodKickUser = OnGodKickUser;
4662 if (handlerGodKickUser != null)
4663 {
4664 handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID,
4665 gkupack.UserInfo.AgentID, (uint)0, gkupack.UserInfo.Reason);
4666 }
4667 }
4668 else
4669 {
4670 SendAgentAlertMessage("Kick request denied", false);
4671 }
4672 //KickUserPacket kupack = new KickUserPacket();
4673 //KickUserPacket.UserInfoBlock kupackib = kupack.UserInfo;
4674
4675 //kupack.UserInfo.AgentID = gkupack.UserInfo.AgentID;
4676 //kupack.UserInfo.SessionID = gkupack.UserInfo.GodSessionID;
4677
4678 //kupack.TargetBlock.TargetIP = (uint)0;
4679 //kupack.TargetBlock.TargetPort = (ushort)0;
4680 //kupack.UserInfo.Reason = gkupack.UserInfo.Reason;
4681
4682 //OutPacket(kupack, ThrottleOutPacketType.Task);
4683 break;
4684
4685 #endregion
4686
4687 #region Economy/Transaction Packets
4688
4689 case PacketType.MoneyBalanceRequest:
4690 MoneyBalanceRequestPacket moneybalancerequestpacket = (MoneyBalanceRequestPacket)Pack;
4691
4692 handlerMoneyBalanceRequest = OnMoneyBalanceRequest;
4693
4694 if (handlerMoneyBalanceRequest != null)
4695 {
4696 handlerMoneyBalanceRequest(this, moneybalancerequestpacket.AgentData.AgentID, moneybalancerequestpacket.AgentData.SessionID, moneybalancerequestpacket.MoneyData.TransactionID);
4697 }
4698
4699 break;
4700 case PacketType.EconomyDataRequest:
4701
4702 handlerEconomoyDataRequest = OnEconomyDataRequest;
4703 if (handlerEconomoyDataRequest != null)
4704 {
4705 handlerEconomoyDataRequest(AgentId);
4706 }
4707 // TODO: handle this packet
4708 //m_log.Warn("[CLIENT]: unhandled EconomyDataRequest packet");
4709 break;
4710 case PacketType.RequestPayPrice:
4711 RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack;
4712 handlerRequestPayPrice = OnRequestPayPrice;
4713 if (handlerRequestPayPrice != null)
4714 {
4715 handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID);
4716 }
4717 break;
4718
4719 #endregion
4720
4721 #region unimplemented handlers
4722
4723 case PacketType.StartPingCheck:
4724 // Send the client the ping response back
4725 // Pass the same PingID in the matching packet
4726 // Handled In the packet processing
4727 //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet");
4728 break;
4729 case PacketType.CompletePingCheck:
4730 // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client
4731 //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet");
4732 break;
4733 case PacketType.ObjectScale:
4734 // TODO: handle this packet
4735 m_log.Warn("[CLIENT]: unhandled ObjectScale packet");
4736 break;
4737 case PacketType.ViewerStats:
4738 // TODO: handle this packet
4739 m_log.Warn("[CLIENT]: unhandled ViewerStats packet");
4740 break;
4741
4742 case PacketType.CreateGroupRequest:
4743 // TODO: handle this packet
4744 m_log.Warn("[CLIENT]: unhandled CreateGroupRequest packet");
4745 break;
4746 case PacketType.GenericMessage:
4747 // TODO: handle this packet
4748 m_log.Warn("[CLIENT]: unhandled GenericMessage packet");
4749 break;
4750 case PacketType.MapItemRequest:
4751 // TODO: handle this packet
4752 m_log.Warn("[CLIENT]: unhandled MapItemRequest packet");
4753 break;
4754 case PacketType.TransferAbort:
4755 // TODO: handle this packet
4756 m_log.Warn("[CLIENT]: unhandled TransferAbort packet");
4757 break;
4758 case PacketType.MuteListRequest:
4759 // TODO: handle this packet
4760 m_log.Warn("[CLIENT]: unhandled MuteListRequest packet");
4761 break;
4762 case PacketType.ParcelDwellRequest:
4763 // TODO: handle this packet
4764 m_log.Warn("[CLIENT]: unhandled ParcelDwellRequest packet");
4765 break;
4766 case PacketType.UseCircuitCode:
4767 // TODO: Don't display this one, we handle it at a lower level
4768 //m_log.Warn("[CLIENT]: unhandled UseCircuitCode packet");
4769 break;
4770
4771 case PacketType.AgentHeightWidth:
4772 // TODO: handle this packet
4773 m_log.Warn("[CLIENT]: unhandled AgentHeightWidth packet");
4774 break;
4775 case PacketType.ObjectSpinStop:
4776 // TODO: handle this packet
4777 m_log.Warn("[CLIENT]: unhandled ObjectSpinStop packet");
4778 break;
4779 case PacketType.SoundTrigger:
4780 // TODO: handle this packet
4781 m_log.Warn("[CLIENT]: unhandled SoundTrigger packet");
4782 break;
4783 case PacketType.InventoryDescendents:
4784 // TODO: handle this packet
4785 m_log.Warn("[CLIENT]: unhandled InventoryDescent packet");
4786 break;
4787 case PacketType.GetScriptRunning:
4788 m_log.Warn("[CLIENT]: unhandled GetScriptRunning packet");
4789 break;
4790 default:
4791 m_log.Warn("[CLIENT]: unhandled packet " + Pack.ToString());
4792 break;
4793
4794 #endregion
4795 }
4796 }
4797
4798 PacketPool.Instance.ReturnPacket(Pack);
4799 }
4800
4801 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
4802 {
4803 PrimitiveBaseShape shape = new PrimitiveBaseShape();
4804
4805 shape.PCode = addPacket.ObjectData.PCode;
4806 shape.State = addPacket.ObjectData.State;
4807 shape.PathBegin = addPacket.ObjectData.PathBegin;
4808 shape.PathEnd = addPacket.ObjectData.PathEnd;
4809 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
4810 shape.PathScaleY = addPacket.ObjectData.PathScaleY;
4811 shape.PathShearX = addPacket.ObjectData.PathShearX;
4812 shape.PathShearY = addPacket.ObjectData.PathShearY;
4813 shape.PathSkew = addPacket.ObjectData.PathSkew;
4814 shape.ProfileBegin = addPacket.ObjectData.ProfileBegin;
4815 shape.ProfileEnd = addPacket.ObjectData.ProfileEnd;
4816 shape.Scale = addPacket.ObjectData.Scale;
4817 shape.PathCurve = addPacket.ObjectData.PathCurve;
4818 shape.ProfileCurve = addPacket.ObjectData.ProfileCurve;
4819 shape.ProfileHollow = addPacket.ObjectData.ProfileHollow;
4820 shape.PathRadiusOffset = addPacket.ObjectData.PathRadiusOffset;
4821 shape.PathRevolutions = addPacket.ObjectData.PathRevolutions;
4822 shape.PathTaperX = addPacket.ObjectData.PathTaperX;
4823 shape.PathTaperY = addPacket.ObjectData.PathTaperY;
4824 shape.PathTwist = addPacket.ObjectData.PathTwist;
4825 shape.PathTwistBegin = addPacket.ObjectData.PathTwistBegin;
4826 LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("89556747-24cb-43ed-920b-47caed15465f"));
4827 shape.TextureEntry = ntex.ToBytes();
4828 //shape.Textures = ntex;
4829 return shape;
4830 }
4831
4832 public void SendBlueBoxMessage(LLUUID FromAvatarID, LLUUID fromSessionID, String FromAvatarName, String Message)
4833 {
4834 if (!ChildAgentStatus())
4835 SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)1, (uint)Util.UnixTimeSinceEpoch());
4836
4837 //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
4838 }
4839
4840 public void SendLogoutPacket()
4841 {
4842 LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
4843 // TODO: don't create new blocks if recycling an old packet
4844 logReply.AgentData.AgentID = AgentId;
4845 logReply.AgentData.SessionID = SessionId;
4846 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
4847 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
4848 logReply.InventoryData[0].ItemID = LLUUID.Zero;
4849
4850 OutPacket(logReply, ThrottleOutPacketType.Task);
4851 }
4852
4853 public ClientInfo GetClientInfo()
4854 {
4855 //MainLog.Instance.Verbose("CLIENT", "GetClientInfo BGN");
4856
4857 ClientInfo info = new ClientInfo();
4858 info.userEP = this.m_userEndPoint;
4859 info.proxyEP = this.m_proxyEndPoint;
4860 info.agentcircuit = new sAgentCircuitData(RequestClientInfo());
4861
4862 info.pendingAcks = m_pendingAcks;
4863
4864 info.needAck = new Dictionary<uint,byte[]>();
4865
4866 lock (m_needAck)
4867 {
4868 foreach (uint key in m_needAck.Keys)
4869 {
4870 info.needAck.Add(key, m_needAck[key].ToBytes());
4871 }
4872 }
4873
4874/* pending
4875 QueItem[] queitems = m_packetQueue.GetQueueArray();
4876
4877 MainLog.Instance.Verbose("CLIENT", "Queue Count : [{0}]", queitems.Length);
4878
4879 for (int i = 0; i < queitems.Length; i++)
4880 {
4881 if (queitems[i].Incoming == false)
4882 {
4883 info.out_packets.Add(queitems[i].Packet.ToBytes());
4884 MainLog.Instance.Verbose("CLIENT", "Add OutPacket [{0}]", queitems[i].Packet.Type.ToString());
4885 }
4886 }
4887*/
4888
4889 info.sequence = m_sequence;
4890
4891 //MainLog.Instance.Verbose("CLIENT", "GetClientInfo END");
4892
4893 return info;
4894 }
4895
4896 public void SetClientInfo(ClientInfo info)
4897 {
4898 m_pendingAcks = info.pendingAcks;
4899
4900 m_needAck = new Dictionary<uint,Packet>();
4901
4902 Packet packet = null;
4903 int packetEnd = 0;
4904 byte[] zero = new byte[3000];
4905
4906 foreach (uint key in info.needAck.Keys)
4907 {
4908 byte[] buff = info.needAck[key];
4909
4910 packetEnd = buff.Length - 1;
4911
4912 try
4913 {
4914 packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero);
4915 }
4916 catch (Exception)
4917 {
4918 //MainLog.Instance.Debug("UDPSERVER", e.ToString());
4919 }
4920
4921 m_needAck.Add(key, packet);
4922 }
4923
4924 m_sequence = info.sequence;
4925 }
4926 }
4927} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
new file mode 100644
index 0000000..5dd1da6
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
@@ -0,0 +1,532 @@
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 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44
45 private bool m_enabled = true;
46
47 private BlockingQueue<LLQueItem> SendQueue;
48
49 private Queue<LLQueItem> IncomingPacketQueue;
50 private Queue<LLQueItem> OutgoingPacketQueue;
51 private Queue<LLQueItem> ResendOutgoingPacketQueue;
52 private Queue<LLQueItem> LandOutgoingPacketQueue;
53 private Queue<LLQueItem> WindOutgoingPacketQueue;
54 private Queue<LLQueItem> CloudOutgoingPacketQueue;
55 private Queue<LLQueItem> TaskOutgoingPacketQueue;
56 private Queue<LLQueItem> TextureOutgoingPacketQueue;
57 private Queue<LLQueItem> AssetOutgoingPacketQueue;
58
59 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
60 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
61
62 // All throttle times and number of bytes are calculated by dividing by this value
63 // This value also determines how many times per throttletimems the timer will run
64 // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds
65
66 private int throttleTimeDivisor = 7;
67
68 private int throttletimems = 1000;
69
70 private LLPacketThrottle ResendThrottle;
71 private LLPacketThrottle LandThrottle;
72 private LLPacketThrottle WindThrottle;
73 private LLPacketThrottle CloudThrottle;
74 private LLPacketThrottle TaskThrottle;
75 private LLPacketThrottle AssetThrottle;
76 private LLPacketThrottle TextureThrottle;
77 private LLPacketThrottle TotalThrottle;
78
79 // private long LastThrottle;
80 // private long ThrottleInterval;
81 private Timer throttleTimer;
82
83 private LLUUID m_agentId;
84
85 public LLPacketQueue(LLUUID agentId)
86 {
87 // While working on this, the BlockingQueue had me fooled for a bit.
88 // The Blocking queue causes the thread to stop until there's something
89 // in it to process. it's an on-purpose threadlock though because
90 // without it, the clientloop will suck up all sim resources.
91
92 SendQueue = new BlockingQueue<LLQueItem>();
93
94 IncomingPacketQueue = new Queue<LLQueItem>();
95 OutgoingPacketQueue = new Queue<LLQueItem>();
96 ResendOutgoingPacketQueue = new Queue<LLQueItem>();
97 LandOutgoingPacketQueue = new Queue<LLQueItem>();
98 WindOutgoingPacketQueue = new Queue<LLQueItem>();
99 CloudOutgoingPacketQueue = new Queue<LLQueItem>();
100 TaskOutgoingPacketQueue = new Queue<LLQueItem>();
101 TextureOutgoingPacketQueue = new Queue<LLQueItem>();
102 AssetOutgoingPacketQueue = new Queue<LLQueItem>();
103
104
105 // Set up the throttle classes (min, max, current) in bytes
106 ResendThrottle = new LLPacketThrottle(5000, 100000, 16000);
107 LandThrottle = new LLPacketThrottle(1000, 100000, 2000);
108 WindThrottle = new LLPacketThrottle(1000, 100000, 1000);
109 CloudThrottle = new LLPacketThrottle(1000, 100000, 1000);
110 TaskThrottle = new LLPacketThrottle(1000, 800000, 3000);
111 AssetThrottle = new LLPacketThrottle(1000, 800000, 1000);
112 TextureThrottle = new LLPacketThrottle(1000, 800000, 4000);
113 // Total Throttle trumps all
114 // Number of bytes allowed to go out per second. (256kbps per client)
115 TotalThrottle = new LLPacketThrottle(0, 1500000, 28000);
116
117 throttleTimer = new Timer((int) (throttletimems/throttleTimeDivisor));
118 throttleTimer.Elapsed += new ElapsedEventHandler(ThrottleTimerElapsed);
119 throttleTimer.Start();
120
121 // TIMERS needed for this
122 // LastThrottle = DateTime.Now.Ticks;
123 // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor);
124
125 m_agentId = agentId;
126
127 if (StatsManager.SimExtraStats != null)
128 {
129 StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this);
130 }
131 }
132
133 /* STANDARD QUEUE MANIPULATION INTERFACES */
134
135
136 public void Enqueue(LLQueItem item)
137 {
138 if (!m_enabled)
139 {
140 return;
141 }
142 // We could micro lock, but that will tend to actually
143 // probably be worse than just synchronizing on SendQueue
144
145 if (item == null)
146 {
147 SendQueue.Enqueue(item);
148 return;
149 }
150
151 lock (this) {
152 switch (item.throttleType)
153 {
154 case ThrottleOutPacketType.Resend:
155 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item);
156 break;
157 case ThrottleOutPacketType.Texture:
158 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item);
159 break;
160 case ThrottleOutPacketType.Task:
161 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item);
162 break;
163 case ThrottleOutPacketType.Land:
164 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item);
165 break;
166 case ThrottleOutPacketType.Asset:
167 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item);
168 break;
169 case ThrottleOutPacketType.Cloud:
170 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item);
171 break;
172 case ThrottleOutPacketType.Wind:
173 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item);
174 break;
175
176 default:
177 // Acknowledgements and other such stuff should go directly to the blocking Queue
178 // Throttling them may and likely 'will' be problematic
179 SendQueue.Enqueue(item);
180 break;
181 }
182 }
183 }
184
185 public LLQueItem Dequeue()
186 {
187 return SendQueue.Dequeue();
188 }
189
190 public void Flush()
191 {
192 lock (this)
193 {
194 while (PacketsWaiting())
195 {
196 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
197 if (ResendOutgoingPacketQueue.Count > 0)
198 {
199 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue());
200 }
201 if (LandOutgoingPacketQueue.Count > 0)
202 {
203 SendQueue.Enqueue(LandOutgoingPacketQueue.Dequeue());
204 }
205 if (WindOutgoingPacketQueue.Count > 0)
206 {
207 SendQueue.Enqueue(WindOutgoingPacketQueue.Dequeue());
208 }
209 if (CloudOutgoingPacketQueue.Count > 0)
210 {
211 SendQueue.Enqueue(CloudOutgoingPacketQueue.Dequeue());
212 }
213 if (TaskOutgoingPacketQueue.Count > 0)
214 {
215 SendQueue.Enqueue(TaskOutgoingPacketQueue.Dequeue());
216 }
217 if (TextureOutgoingPacketQueue.Count > 0)
218 {
219 SendQueue.Enqueue(TextureOutgoingPacketQueue.Dequeue());
220 }
221 if (AssetOutgoingPacketQueue.Count > 0)
222 {
223 SendQueue.Enqueue(AssetOutgoingPacketQueue.Dequeue());
224 }
225 }
226 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
227 }
228 }
229
230 public void Close()
231 {
232 Flush();
233
234 m_enabled = false;
235 throttleTimer.Stop();
236
237 if (StatsManager.SimExtraStats != null)
238 {
239 StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId);
240 }
241 }
242
243 private void ResetCounters()
244 {
245 ResendThrottle.Reset();
246 LandThrottle.Reset();
247 WindThrottle.Reset();
248 CloudThrottle.Reset();
249 TaskThrottle.Reset();
250 AssetThrottle.Reset();
251 TextureThrottle.Reset();
252 TotalThrottle.Reset();
253 }
254
255 private bool PacketsWaiting()
256 {
257 return (ResendOutgoingPacketQueue.Count > 0 ||
258 LandOutgoingPacketQueue.Count > 0 ||
259 WindOutgoingPacketQueue.Count > 0 ||
260 CloudOutgoingPacketQueue.Count > 0 ||
261 TaskOutgoingPacketQueue.Count > 0 ||
262 AssetOutgoingPacketQueue.Count > 0 ||
263 TextureOutgoingPacketQueue.Count > 0);
264 }
265
266 public void ProcessThrottle()
267 {
268 // I was considering this.. Will an event fire if the thread it's on is blocked?
269
270 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
271 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
272 // so This'll pick up about around the right time.
273
274 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
275 int throttleLoops = 0;
276
277 // We're going to dequeue all of the saved up packets until
278 // we've hit the throttle limit or there's no more packets to send
279 lock (this)
280 {
281 ResetCounters();
282 // m_log.Info("[THROTTLE]: Entering Throttle");
283 while (TotalThrottle.UnderLimit() && PacketsWaiting() &&
284 (throttleLoops <= MaxThrottleLoops))
285 {
286 throttleLoops++;
287 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
288 if (ResendThrottle.UnderLimit() && ResendOutgoingPacketQueue.Count > 0)
289 {
290 LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue();
291
292 SendQueue.Enqueue(qpack);
293 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
294 ResendThrottle.Add(qpack.Packet.ToBytes().Length);
295 }
296 if (LandThrottle.UnderLimit() && LandOutgoingPacketQueue.Count > 0)
297 {
298 LLQueItem qpack = LandOutgoingPacketQueue.Dequeue();
299
300 SendQueue.Enqueue(qpack);
301 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
302 LandThrottle.Add(qpack.Packet.ToBytes().Length);
303 }
304 if (WindThrottle.UnderLimit() && WindOutgoingPacketQueue.Count > 0)
305 {
306 LLQueItem qpack = WindOutgoingPacketQueue.Dequeue();
307
308 SendQueue.Enqueue(qpack);
309 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
310 WindThrottle.Add(qpack.Packet.ToBytes().Length);
311 }
312 if (CloudThrottle.UnderLimit() && CloudOutgoingPacketQueue.Count > 0)
313 {
314 LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue();
315
316 SendQueue.Enqueue(qpack);
317 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
318 CloudThrottle.Add(qpack.Packet.ToBytes().Length);
319 }
320 if (TaskThrottle.UnderLimit() && TaskOutgoingPacketQueue.Count > 0)
321 {
322 LLQueItem qpack = TaskOutgoingPacketQueue.Dequeue();
323
324 SendQueue.Enqueue(qpack);
325 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
326 TaskThrottle.Add(qpack.Packet.ToBytes().Length);
327 }
328 if (TextureThrottle.UnderLimit() && TextureOutgoingPacketQueue.Count > 0)
329 {
330 LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue();
331
332 SendQueue.Enqueue(qpack);
333 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
334 TextureThrottle.Add(qpack.Packet.ToBytes().Length);
335 }
336 if (AssetThrottle.UnderLimit() && AssetOutgoingPacketQueue.Count > 0)
337 {
338 LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue();
339
340 SendQueue.Enqueue(qpack);
341 TotalThrottle.Add(qpack.Packet.ToBytes().Length);
342 AssetThrottle.Add(qpack.Packet.ToBytes().Length);
343 }
344 }
345 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
346 }
347 }
348
349 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
350 {
351 // just to change the signature, and that ProcessThrottle
352 // will be used elsewhere possibly
353 ProcessThrottle();
354 }
355
356 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item)
357 {
358 // The idea.. is if the packet throttle queues are empty
359 // and the client is under throttle for the type. Queue
360 // it up directly. This basically short cuts having to
361 // wait for the timer to fire to put things into the
362 // output queue
363
364 if ((q.Count == 0) && (throttle.UnderLimit()))
365 {
366 Monitor.Enter(this);
367 throttle.Add(item.Packet.ToBytes().Length);
368 TotalThrottle.Add(item.Packet.ToBytes().Length);
369 SendQueue.Enqueue(item);
370 Monitor.Pulse(this);
371 Monitor.Exit(this);
372 }
373 else
374 {
375 q.Enqueue(item);
376 }
377 }
378
379
380 private static int ScaleThrottle(int value, int curmax, int newmax)
381 {
382 return (value / curmax) * newmax;
383 }
384
385 public byte[] GetThrottlesPacked(float multiplier)
386 {
387 int singlefloat = 4;
388 float tResend = ResendThrottle.Throttle*multiplier;
389 float tLand = LandThrottle.Throttle*multiplier;
390 float tWind = WindThrottle.Throttle*multiplier;
391 float tCloud = CloudThrottle.Throttle*multiplier;
392 float tTask = TaskThrottle.Throttle*multiplier;
393 float tTexture = TextureThrottle.Throttle*multiplier;
394 float tAsset = AssetThrottle.Throttle*multiplier;
395
396 byte[] throttles = new byte[singlefloat*7];
397 int i = 0;
398 Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat);
399 i++;
400 Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat);
401 i++;
402 Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat);
403 i++;
404 Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat);
405 i++;
406 Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat);
407 i++;
408 Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat);
409 i++;
410 Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat);
411
412 return throttles;
413 }
414
415 public void SetThrottleFromClient(byte[] throttle)
416 {
417 int tResend = -1;
418 int tLand = -1;
419 int tWind = -1;
420 int tCloud = -1;
421 int tTask = -1;
422 int tTexture = -1;
423 int tAsset = -1;
424 int tall = -1;
425 int singlefloat = 4;
426
427 //Agent Throttle Block contains 7 single floatingpoint values.
428 int j = 0;
429
430 // Some Systems may be big endian...
431 // it might be smart to do this check more often...
432 if (!BitConverter.IsLittleEndian)
433 for (int i = 0; i < 7; i++)
434 Array.Reverse(throttle, j + i*singlefloat, singlefloat);
435
436 // values gotten from libsecondlife.org/wiki/Throttle. Thanks MW_
437 // bytes
438 // Convert to integer, since.. the full fp space isn't used.
439 tResend = (int) BitConverter.ToSingle(throttle, j);
440 j += singlefloat;
441 tLand = (int) BitConverter.ToSingle(throttle, j);
442 j += singlefloat;
443 tWind = (int) BitConverter.ToSingle(throttle, j);
444 j += singlefloat;
445 tCloud = (int) BitConverter.ToSingle(throttle, j);
446 j += singlefloat;
447 tTask = (int) BitConverter.ToSingle(throttle, j);
448 j += singlefloat;
449 tTexture = (int) BitConverter.ToSingle(throttle, j);
450 j += singlefloat;
451 tAsset = (int) BitConverter.ToSingle(throttle, j);
452
453 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
454 /*
455 m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbytes=" + tResend +
456 " landbytes=" + tLand +
457 " windbytes=" + tWind +
458 " cloudbytes=" + tCloud +
459 " taskbytes=" + tTask +
460 " texturebytes=" + tTexture +
461 " Assetbytes=" + tAsset +
462 " Allbytes=" + tall);
463 */
464
465 // Total Sanity
466 // Make sure that the client sent sane total values.
467
468 // If the client didn't send acceptable values....
469 // Scale the clients values down until they are acceptable.
470
471 if (tall <= TotalThrottle.Max)
472 {
473 ResendThrottle.Throttle = tResend;
474 LandThrottle.Throttle = tLand;
475 WindThrottle.Throttle = tWind;
476 CloudThrottle.Throttle = tCloud;
477 TaskThrottle.Throttle = tTask;
478 TextureThrottle.Throttle = tTexture;
479 AssetThrottle.Throttle = tAsset;
480 TotalThrottle.Throttle = tall;
481 }
482 else if (tall < 1)
483 {
484 // client is stupid, penalize him by minning everything
485 ResendThrottle.Throttle = ResendThrottle.Min;
486 LandThrottle.Throttle = LandThrottle.Min;
487 WindThrottle.Throttle = WindThrottle.Min;
488 CloudThrottle.Throttle = CloudThrottle.Min;
489 TaskThrottle.Throttle = TaskThrottle.Min;
490 TextureThrottle.Throttle = TextureThrottle.Min;
491 AssetThrottle.Throttle = AssetThrottle.Min;
492 TotalThrottle.Throttle = TotalThrottle.Min;
493 }
494 else
495 {
496 // we're over so figure out percentages and use those
497 ResendThrottle.Throttle = tResend;
498
499 LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max);
500 WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max);
501 CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max);
502 TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max);
503 TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max);
504 AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max);
505 TotalThrottle.Throttle = TotalThrottle.Max;
506 }
507 // effectively wiggling the slider causes things reset
508 ResetCounters();
509 }
510
511 // See IPullStatsProvider
512 public string GetStats()
513 {
514 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
515 SendQueue.Count(),
516 IncomingPacketQueue.Count,
517 OutgoingPacketQueue.Count,
518 ResendOutgoingPacketQueue.Count,
519 LandOutgoingPacketQueue.Count,
520 WindOutgoingPacketQueue.Count,
521 CloudOutgoingPacketQueue.Count,
522 TaskOutgoingPacketQueue.Count,
523 TextureOutgoingPacketQueue.Count,
524 AssetOutgoingPacketQueue.Count);
525 }
526
527 public LLQueItem[] GetQueueArray()
528 {
529 return SendQueue.GetQueueArray();
530 }
531 }
532} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs
new file mode 100644
index 0000000..48afa84
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/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 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/LindenUDP/LLPacketThrottle.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs
new file mode 100644
index 0000000..792429a
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/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 int max; // max allowable throttle
33 private int min; // min allowable throttle
34 private int throttle; // current throttle setting
35 private static int divisor = 7; // the throttle time divisor, this probably should factor out
36 private int sent; // current number of bytes sent
37
38 public LLPacketThrottle(int Min, int Max, int Throttle)
39 {
40 max = Max;
41 min = Min;
42 throttle = Throttle;
43 sent = 0;
44 }
45
46 public void Reset()
47 {
48 sent = 0;
49 }
50
51 public bool UnderLimit()
52 {
53 return (sent < (throttle/divisor));
54 }
55
56 public int Add(int bytes)
57 {
58 sent += bytes;
59 return sent;
60 }
61
62 // Properties
63 public int Max
64 {
65 get { return max; }
66 }
67
68 public int Min
69 {
70 get { return min; }
71 }
72
73 public int Throttle
74 {
75 get { return throttle; }
76 set
77 {
78 if (value > max)
79 {
80 throttle = max;
81 }
82 else if (value < min)
83 {
84 throttle = min;
85 }
86 else
87 {
88 throttle = value;
89 }
90 }
91 }
92 }
93} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs b/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs
new file mode 100644
index 0000000..4253378
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs
@@ -0,0 +1,43 @@
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 libsecondlife.Packets;
29using OpenSim.Framework;
30
31namespace OpenSim.Region.ClientStack.LindenUDP
32{
33 public class LLQueItem
34 {
35 public LLQueItem()
36 {
37 }
38
39 public Packet Packet;
40 public bool Incoming;
41 public ThrottleOutPacketType throttleType;
42 }
43} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
new file mode 100644
index 0000000..f85dcc2
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -0,0 +1,499 @@
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 libsecondlife.Packets;
34using log4net;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications.Cache;
37using OpenSim.Region.ClientStack.LindenUDP;
38
39namespace OpenSim.Region.ClientStack.LindenUDP
40{
41 public class LLUDPServer : LLClientStackNetworkHandler, IClientNetworkServer
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
46 public Dictionary<uint, EndPoint> clientCircuits_reverse = new Dictionary<uint, EndPoint>();
47 protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>();
48 private Socket m_socket;
49 protected IPEndPoint ServerIncoming;
50 protected byte[] RecvBuffer = new byte[4096];
51 protected byte[] ZeroBuffer = new byte[8192];
52 protected IPEndPoint ipeSender;
53 protected EndPoint epSender;
54 protected EndPoint epProxy;
55 protected int proxyPortOffset;
56 protected AsyncCallback ReceivedData;
57 protected LLPacketServer m_packetServer;
58 protected Location m_location;
59
60 protected uint listenPort;
61 protected bool Allow_Alternate_Port;
62 protected IPAddress listenIP = IPAddress.Parse("0.0.0.0");
63 protected IScene m_localScene;
64 protected AssetCache m_assetCache;
65 protected AgentCircuitManager m_authenticateSessionsClass;
66
67 public LLPacketServer PacketServer
68 {
69 get { return m_packetServer; }
70 set { m_packetServer = value; }
71 }
72
73 public IScene LocalScene
74 {
75 set
76 {
77 m_localScene = value;
78 m_packetServer.LocalScene = m_localScene;
79 m_location = new Location(m_localScene.RegionInfo.RegionHandle);
80 }
81 }
82
83 public ulong RegionHandle
84 {
85 get { return m_location.RegionHandle; }
86 }
87
88 Socket IClientNetworkServer.Server
89 {
90 get { return m_socket; }
91 }
92
93 public bool HandlesRegion(Location x)
94 {
95 return x == m_location;
96 }
97
98 public LLUDPServer()
99 {
100 }
101
102 public LLUDPServer(IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AssetCache assetCache, AgentCircuitManager authenticateClass)
103 {
104 this.proxyPortOffset = proxyPortOffset;
105 listenPort = (uint) (port + proxyPortOffset);
106 listenIP = _listenIP;
107 Allow_Alternate_Port = allow_alternate_port;
108 m_assetCache = assetCache;
109 m_authenticateSessionsClass = authenticateClass;
110 CreatePacketServer();
111
112 // Return new port
113 // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered.
114 // So the option allow_alternate_ports="true" was added to default.xml
115 port = (uint)(listenPort - proxyPortOffset);
116 }
117
118 protected virtual void CreatePacketServer()
119 {
120 LLPacketServer packetServer = new LLPacketServer(this);
121 }
122
123 protected virtual void OnReceivedData(IAsyncResult result)
124 {
125 ipeSender = new IPEndPoint(listenIP, 0);
126 epSender = (EndPoint) ipeSender;
127 Packet packet = null;
128
129 int numBytes = 1;
130
131 try
132 {
133 numBytes = m_socket.EndReceiveFrom(result, ref epSender);
134 }
135 catch (SocketException e)
136 {
137 // TODO : Actually only handle those states that we have control over, re-throw everything else,
138 // TODO: implement cases as we encounter them.
139 //m_log.Error("[UDPSERVER]: Connection Error! - " + e.ToString());
140 switch (e.SocketErrorCode)
141 {
142 case SocketError.AlreadyInProgress:
143 case SocketError.NetworkReset:
144 case SocketError.ConnectionReset:
145 try
146 {
147 CloseEndPoint(epSender);
148 }
149 catch (Exception a)
150 {
151 m_log.Info("[UDPSERVER]: " + a.ToString());
152 }
153 try
154 {
155 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
156 ReceivedData, null);
157
158 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
159 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
160 // This will happen over and over until we've gone through all packets
161 // sent to and from this particular user.
162 // Stupid I know..
163 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
164 }
165 catch (SocketException)
166 {
167 }
168 break;
169 default:
170 try
171 {
172 CloseEndPoint(epSender);
173 }
174 catch (Exception)
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 e2)
191 {
192 m_log.Error("[UDPSERVER]: " + e2.ToString());
193 }
194
195 // Here's some reference code! :D
196 // Shutdown and restart the UDP listener! hehe
197 // Shiny
198
199 //Server.Shutdown(SocketShutdown.Both);
200 //CloseEndPoint(epSender);
201 //ServerListener();
202 break;
203 }
204
205 //return;
206 }
207 catch (ObjectDisposedException e)
208 {
209 m_log.Debug("[UDPSERVER]: " + e.ToString());
210 try
211 {
212 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
213 ReceivedData, null);
214
215 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
216 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
217 // This will happen over and over until we've gone through all packets
218 // sent to and from this particular user.
219 // Stupid I know..
220 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
221 }
222
223 catch (SocketException e2)
224 {
225 m_log.Error("[UDPSERVER]: " + e2.ToString());
226 }
227 catch (ObjectDisposedException)
228 {
229 }
230 //return;
231 }
232
233 //System.Console.WriteLine("UDPServer : recieved message from {0}", epSender.ToString());
234 epProxy = epSender;
235 if (proxyPortOffset != 0)
236 {
237 epSender = PacketPool.DecodeProxyMessage(RecvBuffer, ref numBytes);
238 }
239
240 int packetEnd = numBytes - 1;
241
242 try
243 {
244 packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
245 }
246 catch (Exception e)
247 {
248 m_log.Debug("[UDPSERVER]: " + e.ToString());
249 }
250
251 try
252 {
253 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
254 }
255 catch (SocketException)
256 {
257 try
258 {
259 CloseEndPoint(epSender);
260 }
261 catch (Exception a)
262 {
263 m_log.Info("[UDPSERVER]: " + a.ToString());
264 }
265 try
266 {
267 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
268 ReceivedData, null);
269
270 // Ter: For some stupid reason ConnectionReset basically kills our async event structure..
271 // so therefore.. we've got to tell the server to BeginReceiveFrom again.
272 // This will happen over and over until we've gone through all packets
273 // sent to and from this particular user.
274 // Stupid I know..
275 // but Flusing the buffer would be even more stupid... so, we're stuck with this ugly method.
276 }
277 catch (SocketException e5)
278 {
279 m_log.Error("[UDPSERVER]: " + e5.ToString());
280 }
281 }
282 catch (ObjectDisposedException)
283 {
284 }
285
286 if (packet != null)
287 {
288 try
289 {
290 // do we already have a circuit for this endpoint
291 uint circuit;
292
293 bool ret = false;
294 lock (clientCircuits)
295 {
296 ret = clientCircuits.TryGetValue(epSender, out circuit);
297 }
298 if (ret)
299 {
300 //if so then send packet to the packetserver
301 //m_log.Warn("[UDPSERVER]: ALREADY HAVE Circuit!");
302 m_packetServer.InPacket(circuit, packet);
303 }
304 else if (packet.Type == PacketType.UseCircuitCode)
305 {
306 // new client
307 m_log.Debug("[UDPSERVER]: Adding New Client");
308 AddNewClient(packet);
309
310 UseCircuitCodePacket p = (UseCircuitCodePacket)packet;
311
312 // Ack the first UseCircuitCode packet
313 PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
314 // TODO: don't create new blocks if recycling an old packet
315 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
316 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
317 ack_it.Packets[0].ID = packet.Header.Sequence;
318 ack_it.Header.Reliable = false;
319 SendPacketTo(ack_it.ToBytes(),ack_it.ToBytes().Length,SocketFlags.None,p.CircuitCode.Code);
320 }
321 else
322 {
323 // invalid client
324 //CFK: This message seems to have served its usefullness as of 12-15 so I am commenting it out for now
325 //m_log.Warn("[UDPSERVER]: Got a packet from an invalid client - " + packet.ToString());
326 }
327 }
328 catch (Exception)
329 {
330 m_log.Error("[UDPSERVER]: Exception in processing packet.");
331 m_log.Debug("[UDPSERVER]: Adding New Client");
332 try
333 {
334 AddNewClient(packet);
335 }
336 catch (Exception e3)
337 {
338 m_log.Error("[UDPSERVER]: Adding New Client threw exception " + e3.ToString());
339 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender,
340 ReceivedData, null);
341 }
342 }
343 }
344
345 }
346
347 private void CloseEndPoint(EndPoint sender)
348 {
349 uint circuit;
350 lock (clientCircuits)
351 {
352 if (clientCircuits.TryGetValue(sender, out circuit))
353 {
354 m_packetServer.CloseCircuit(circuit);
355 }
356 }
357 }
358
359 protected virtual void AddNewClient(Packet packet)
360 {
361 //Slave regions don't accept new clients
362 if(m_localScene.Region_Status != RegionStatus.SlaveScene)
363 {
364 UseCircuitCodePacket useCircuit = (UseCircuitCodePacket) packet;
365 lock (clientCircuits)
366 {
367 if (!clientCircuits.ContainsKey(epSender))
368 clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
369 else
370 m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
371 }
372 lock (clientCircuits_reverse)
373 {
374 if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
375 clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, epSender);
376 else
377 m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
378 }
379
380 lock (proxyCircuits)
381 {
382 if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
383 proxyCircuits.Add(useCircuit.CircuitCode.Code, epProxy);
384 else
385 m_log.Error("[UDPSERVER]: proxyCircuits already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
386 }
387
388 PacketServer.AddNewClient(epSender, useCircuit, m_assetCache, m_authenticateSessionsClass, epProxy);
389 }
390 PacketPool.Instance.ReturnPacket(packet);
391 }
392
393 public void ServerListener()
394 {
395 uint newPort = listenPort;
396 m_log.Info("[SERVER]: Opening UDP socket on " + listenIP.ToString() + " " + newPort + ".");
397
398 ServerIncoming = new IPEndPoint(listenIP, (int)newPort);
399 m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
400 m_socket.Bind(ServerIncoming);
401 listenPort = newPort;
402
403 m_log.Info("[SERVER]: UDP socket bound, getting ready to listen");
404
405 ipeSender = new IPEndPoint(listenIP, 0);
406 epSender = (EndPoint)ipeSender;
407 ReceivedData = new AsyncCallback(OnReceivedData);
408 m_socket.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null);
409
410 m_log.Info("[SERVER]: Listening on port " + newPort);
411 }
412
413 public virtual void RegisterPacketServer(LLPacketServer server)
414 {
415 m_packetServer = server;
416 }
417
418 public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
419 //EndPoint packetSender)
420 {
421 // find the endpoint for this circuit
422 EndPoint sendto = null;
423 lock (clientCircuits_reverse)
424 {
425 if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
426 {
427 //we found the endpoint so send the packet to it
428 if (proxyPortOffset != 0)
429 {
430 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString());
431 PacketPool.EncodeProxyMessage(buffer, ref size, sendto);
432 m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]);
433 }
434 else
435 {
436 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString());
437 m_socket.SendTo(buffer, size, flags, sendto);
438 }
439 }
440 }
441 }
442
443 public virtual void RemoveClientCircuit(uint circuitcode)
444 {
445 EndPoint sendto = null;
446 lock (clientCircuits_reverse)
447 {
448 if (clientCircuits_reverse.TryGetValue(circuitcode, out sendto))
449 {
450 clientCircuits.Remove(sendto);
451
452 clientCircuits_reverse.Remove(circuitcode);
453 proxyCircuits.Remove(circuitcode);
454 }
455 }
456 }
457
458 public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP)
459 {
460 //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient");
461
462 UseCircuitCodePacket useCircuit = new UseCircuitCodePacket();
463 useCircuit.CircuitCode.Code = circuit.circuitcode;
464 useCircuit.CircuitCode.ID = circuit.AgentID;
465 useCircuit.CircuitCode.SessionID = circuit.SessionID;
466
467 lock (clientCircuits)
468 {
469 if (!clientCircuits.ContainsKey(userEP))
470 clientCircuits.Add(userEP, useCircuit.CircuitCode.Code);
471 else
472 m_log.Error("[UDPSERVER]: clientCircuits already contans entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
473 }
474 lock (clientCircuits_reverse)
475 {
476 if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
477 clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP);
478 else
479 m_log.Error("[UDPSERVER]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code.ToString() + ". NOT adding.");
480 }
481
482 lock (proxyCircuits)
483 {
484 if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code))
485 {
486 proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
487 }
488 else
489 {
490 // re-set proxy endpoint
491 proxyCircuits.Remove(useCircuit.CircuitCode.Code);
492 proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
493 }
494 }
495
496 PacketServer.AddNewClient(userEP, useCircuit, m_assetCache, m_authenticateSessionsClass, proxyEP);
497 }
498 }
499} \ No newline at end of file