aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs1
-rw-r--r--OpenSim/Data/MySQL/MySQLAssetData.cs6
-rw-r--r--OpenSim/Framework/Parallel.cs207
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs27
-rw-r--r--OpenSim/Framework/Tests/ThreadTrackerTests.cs140
-rw-r--r--OpenSim/Framework/ThreadTracker.cs127
-rw-r--r--OpenSim/Framework/ThrottleOutPacketType.cs8
-rw-r--r--OpenSim/Framework/Util.cs40
-rw-r--r--OpenSim/Region/Application/Application.cs12
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs2
-rw-r--r--OpenSim/Region/ClientStack/IClientNetworkServer.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs38
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs83
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs (renamed from OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs)34
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs (renamed from OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs)60
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs31
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs3230
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs870
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs742
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs206
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs128
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs442
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs185
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs1055
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs (renamed from OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs)47
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs99
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs160
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs1
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs1
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs1
-rw-r--r--OpenSim/TestSuite/BotManager.cs1
-rw-r--r--OpenSim/Tools/pCampBot/BotManager.cs1
42 files changed, 3210 insertions, 4802 deletions
diff --git a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
index 332ff70..4910ab1 100644
--- a/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
+++ b/OpenSim/Client/MXP/PacketHandler/MXPPacketServer.cs
@@ -89,7 +89,6 @@ namespace OpenSim.Client.MXP.PacketHandler
89 m_clientThread.Name = "MXPThread"; 89 m_clientThread.Name = "MXPThread";
90 m_clientThread.IsBackground = true; 90 m_clientThread.IsBackground = true;
91 m_clientThread.Start(); 91 m_clientThread.Start();
92 ThreadTracker.Add(m_clientThread);
93 } 92 }
94 93
95 public void StartListener() 94 public void StartListener()
diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs
index 8f97440..259e186 100644
--- a/OpenSim/Data/MySQL/MySQLAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLAssetData.cs
@@ -239,10 +239,8 @@ namespace OpenSim.Data.MySQL
239 } 239 }
240 catch (Exception e) 240 catch (Exception e)
241 { 241 {
242 m_log.ErrorFormat( 242 m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Attempting reconnect. Error: {2}",
243 "[ASSETS DB]: " + 243 asset.FullID, asset.Name, e.Message);
244 "MySql failure creating asset {0} with name {1}" + Environment.NewLine + e.ToString()
245 + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name);
246 _dbConnection.Reconnect(); 244 _dbConnection.Reconnect();
247 } 245 }
248 } 246 }
diff --git a/OpenSim/Framework/Parallel.cs b/OpenSim/Framework/Parallel.cs
new file mode 100644
index 0000000..74537ba
--- /dev/null
+++ b/OpenSim/Framework/Parallel.cs
@@ -0,0 +1,207 @@
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 OpenSimulator 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;
31
32namespace OpenSim.Framework
33{
34 /// <summary>
35 /// Provides helper methods for parallelizing loops
36 /// </summary>
37 public static class Parallel
38 {
39 private static readonly int processorCount = System.Environment.ProcessorCount;
40
41 /// <summary>
42 /// Executes a for loop in which iterations may run in parallel
43 /// </summary>
44 /// <param name="fromInclusive">The loop will be started at this index</param>
45 /// <param name="toExclusive">The loop will be terminated before this index is reached</param>
46 /// <param name="body">Method body to run for each iteration of the loop</param>
47 public static void For(int fromInclusive, int toExclusive, Action<int> body)
48 {
49 For(processorCount, fromInclusive, toExclusive, body);
50 }
51
52 /// <summary>
53 /// Executes a for loop in which iterations may run in parallel
54 /// </summary>
55 /// <param name="threadCount">The number of concurrent execution threads to run</param>
56 /// <param name="fromInclusive">The loop will be started at this index</param>
57 /// <param name="toExclusive">The loop will be terminated before this index is reached</param>
58 /// <param name="body">Method body to run for each iteration of the loop</param>
59 public static void For(int threadCount, int fromInclusive, int toExclusive, Action<int> body)
60 {
61 int counter = threadCount;
62 AutoResetEvent threadFinishEvent = new AutoResetEvent(false);
63 Exception exception = null;
64
65 --fromInclusive;
66
67 for (int i = 0; i < threadCount; i++)
68 {
69 ThreadPool.QueueUserWorkItem(
70 delegate(object o)
71 {
72 int threadIndex = (int)o;
73
74 while (exception == null)
75 {
76 int currentIndex = Interlocked.Increment(ref fromInclusive);
77
78 if (currentIndex >= toExclusive)
79 break;
80
81 try { body(currentIndex); }
82 catch (Exception ex) { exception = ex; break; }
83 }
84
85 if (Interlocked.Decrement(ref counter) == 0)
86 threadFinishEvent.Set();
87 }, i
88 );
89 }
90
91 threadFinishEvent.WaitOne();
92
93 if (exception != null)
94 throw new Exception(exception.Message, exception);
95 }
96
97 /// <summary>
98 /// Executes a foreach loop in which iterations may run in parallel
99 /// </summary>
100 /// <typeparam name="T">Object type that the collection wraps</typeparam>
101 /// <param name="enumerable">An enumerable collection to iterate over</param>
102 /// <param name="body">Method body to run for each object in the collection</param>
103 public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> body)
104 {
105 ForEach<T>(processorCount, enumerable, body);
106 }
107
108 /// <summary>
109 /// Executes a foreach loop in which iterations may run in parallel
110 /// </summary>
111 /// <typeparam name="T">Object type that the collection wraps</typeparam>
112 /// <param name="threadCount">The number of concurrent execution threads to run</param>
113 /// <param name="enumerable">An enumerable collection to iterate over</param>
114 /// <param name="body">Method body to run for each object in the collection</param>
115 public static void ForEach<T>(int threadCount, IEnumerable<T> enumerable, Action<T> body)
116 {
117 int counter = threadCount;
118 AutoResetEvent threadFinishEvent = new AutoResetEvent(false);
119 IEnumerator<T> enumerator = enumerable.GetEnumerator();
120 Exception exception = null;
121
122 for (int i = 0; i < threadCount; i++)
123 {
124 ThreadPool.QueueUserWorkItem(
125 delegate(object o)
126 {
127 int threadIndex = (int)o;
128
129 while (exception == null)
130 {
131 T entry;
132
133 lock (enumerator)
134 {
135 if (!enumerator.MoveNext())
136 break;
137 entry = (T)enumerator.Current; // Explicit typecast for Mono's sake
138 }
139
140 try { body(entry); }
141 catch (Exception ex) { exception = ex; break; }
142 }
143
144 if (Interlocked.Decrement(ref counter) == 0)
145 threadFinishEvent.Set();
146 }, i
147 );
148 }
149
150 threadFinishEvent.WaitOne();
151
152 if (exception != null)
153 throw new Exception(exception.Message, exception);
154 }
155
156 /// <summary>
157 /// Executes a series of tasks in parallel
158 /// </summary>
159 /// <param name="actions">A series of method bodies to execute</param>
160 public static void Invoke(params Action[] actions)
161 {
162 Invoke(processorCount, actions);
163 }
164
165 /// <summary>
166 /// Executes a series of tasks in parallel
167 /// </summary>
168 /// <param name="threadCount">The number of concurrent execution threads to run</param>
169 /// <param name="actions">A series of method bodies to execute</param>
170 public static void Invoke(int threadCount, params Action[] actions)
171 {
172 int counter = threadCount;
173 AutoResetEvent threadFinishEvent = new AutoResetEvent(false);
174 int index = -1;
175 Exception exception = null;
176
177 for (int i = 0; i < threadCount; i++)
178 {
179 ThreadPool.QueueUserWorkItem(
180 delegate(object o)
181 {
182 int threadIndex = (int)o;
183
184 while (exception == null)
185 {
186 int currentIndex = Interlocked.Increment(ref index);
187
188 if (currentIndex >= actions.Length)
189 break;
190
191 try { actions[currentIndex](); }
192 catch (Exception ex) { exception = ex; break; }
193 }
194
195 if (Interlocked.Decrement(ref counter) == 0)
196 threadFinishEvent.Set();
197 }, i
198 );
199 }
200
201 threadFinishEvent.WaitOne();
202
203 if (exception != null)
204 throw new Exception(exception.Message, exception);
205 }
206 }
207}
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 56155dd..8e58980 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Diagnostics;
30using System.IO; 31using System.IO;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
@@ -109,9 +110,8 @@ namespace OpenSim.Framework.Servers
109 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 110 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
110 m_periodicDiagnosticsTimer.Enabled = true; 111 m_periodicDiagnosticsTimer.Enabled = true;
111 112
112 // Add ourselves to thread monitoring. This thread will go on to become the console listening thread 113 // This thread will go on to become the console listening thread
113 Thread.CurrentThread.Name = "ConsoleThread"; 114 Thread.CurrentThread.Name = "ConsoleThread";
114 ThreadTracker.Add(Thread.CurrentThread);
115 115
116 ILoggerRepository repository = LogManager.GetRepository(); 116 ILoggerRepository repository = LogManager.GetRepository();
117 IAppender[] appenders = repository.GetAppenders(); 117 IAppender[] appenders = repository.GetAppenders();
@@ -235,7 +235,7 @@ namespace OpenSim.Framework.Servers
235 { 235 {
236 StringBuilder sb = new StringBuilder(); 236 StringBuilder sb = new StringBuilder();
237 237
238 List<Thread> threads = ThreadTracker.GetThreads(); 238 ProcessThreadCollection threads = ThreadTracker.GetThreads();
239 if (threads == null) 239 if (threads == null)
240 { 240 {
241 sb.Append("OpenSim thread tracking is only enabled in DEBUG mode."); 241 sb.Append("OpenSim thread tracking is only enabled in DEBUG mode.");
@@ -243,25 +243,10 @@ namespace OpenSim.Framework.Servers
243 else 243 else
244 { 244 {
245 sb.Append(threads.Count + " threads are being tracked:" + Environment.NewLine); 245 sb.Append(threads.Count + " threads are being tracked:" + Environment.NewLine);
246 foreach (Thread t in threads) 246 foreach (ProcessThread t in threads)
247 { 247 {
248 if (t.IsAlive) 248 sb.Append("ID: " + t.Id + ", TotalProcessorTime: " + t.TotalProcessorTime + ", TimeRunning: " +
249 { 249 (DateTime.Now - t.StartTime) + ", Pri: " + t.CurrentPriority + ", State: " + t.ThreadState + Environment.NewLine);
250 sb.Append(
251 "ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", Alive: " + t.IsAlive
252 + ", Pri: " + t.Priority + ", State: " + t.ThreadState + Environment.NewLine);
253 }
254 else
255 {
256 try
257 {
258 sb.Append("ID: " + t.ManagedThreadId + ", Name: " + t.Name + ", DEAD" + Environment.NewLine);
259 }
260 catch
261 {
262 sb.Append("THREAD ERROR" + Environment.NewLine);
263 }
264 }
265 } 250 }
266 } 251 }
267 int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0; 252 int workers = 0, ports = 0, maxWorkers = 0, maxPorts = 0;
diff --git a/OpenSim/Framework/Tests/ThreadTrackerTests.cs b/OpenSim/Framework/Tests/ThreadTrackerTests.cs
index 15d5b73..7eb83e6 100644
--- a/OpenSim/Framework/Tests/ThreadTrackerTests.cs
+++ b/OpenSim/Framework/Tests/ThreadTrackerTests.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Framework.Tests
41 [Test] 41 [Test]
42 public void DefaultThreadTrackerTest() 42 public void DefaultThreadTrackerTest()
43 { 43 {
44 List<Thread> lThread = ThreadTracker.GetThreads(); 44 System.Diagnostics.ProcessThreadCollection lThread = ThreadTracker.GetThreads();
45 45
46 /* 46 /*
47 foreach (Thread t in lThread) 47 foreach (Thread t in lThread)
@@ -50,143 +50,7 @@ namespace OpenSim.Framework.Tests
50 } 50 }
51 */ 51 */
52 52
53 Assert.That(lThread.Count == 1); 53 Assert.That(lThread.Count > 0);
54 Assert.That(lThread[0].Name == "ThreadTrackerThread");
55 } 54 }
56
57 /// <summary>
58 /// Validate that adding a thread to the thread tracker works
59 /// Validate that removing a thread from the thread tracker also works.
60 /// </summary>
61 [Test]
62 public void AddThreadToThreadTrackerTestAndRemoveTest()
63 {
64 Thread t = new Thread(run);
65 t.Name = "TestThread";
66 t.Priority = ThreadPriority.BelowNormal;
67 t.IsBackground = true;
68 t.SetApartmentState(ApartmentState.MTA);
69 t.Start();
70 ThreadTracker.Add(t);
71
72 List<Thread> lThread = ThreadTracker.GetThreads();
73
74 Assert.That(lThread.Count == 2);
75
76 foreach (Thread tr in lThread)
77 {
78 Assert.That((tr.Name == "ThreadTrackerThread" || tr.Name == "TestThread"));
79 }
80 running = false;
81 ThreadTracker.Remove(t);
82
83 lThread = ThreadTracker.GetThreads();
84
85 Assert.That(lThread.Count == 1);
86
87 foreach (Thread tr in lThread)
88 {
89 Assert.That((tr.Name == "ThreadTrackerThread"));
90 }
91
92
93 }
94
95 /// <summary>
96 /// Test a dead thread removal by aborting it and setting it's last seen active date to 50 seconds
97 /// </summary>
98 [Test]
99 public void DeadThreadTest()
100 {
101 Thread t = new Thread(run2);
102 t.Name = "TestThread";
103 t.Priority = ThreadPriority.BelowNormal;
104 t.IsBackground = true;
105 t.SetApartmentState(ApartmentState.MTA);
106 t.Start();
107 ThreadTracker.Add(t);
108 t.Abort();
109 Thread.Sleep(5000);
110 ThreadTracker.m_Threads[1].LastSeenActive = DateTime.Now.Ticks - (50*10000000);
111 ThreadTracker.CleanUp();
112 List<Thread> lThread = ThreadTracker.GetThreads();
113
114 Assert.That(lThread.Count == 1);
115
116 foreach (Thread tr in lThread)
117 {
118 Assert.That((tr.Name == "ThreadTrackerThread"));
119 }
120 }
121
122 [Test]
123 public void UnstartedThreadTest()
124 {
125 Thread t = new Thread(run2);
126 t.Name = "TestThread";
127 t.Priority = ThreadPriority.BelowNormal;
128 t.IsBackground = true;
129 t.SetApartmentState(ApartmentState.MTA);
130 ThreadTracker.Add(t);
131 ThreadTracker.m_Threads[1].LastSeenActive = DateTime.Now.Ticks - (50 * 10000000);
132 ThreadTracker.CleanUp();
133 List<Thread> lThread = ThreadTracker.GetThreads();
134
135 Assert.That(lThread.Count == 1);
136
137 foreach (Thread tr in lThread)
138 {
139 Assert.That((tr.Name == "ThreadTrackerThread"));
140 }
141 }
142
143 [Test]
144 public void NullThreadTest()
145 {
146 Thread t = null;
147 ThreadTracker.Add(t);
148
149 List<Thread> lThread = ThreadTracker.GetThreads();
150
151 Assert.That(lThread.Count == 1);
152
153 foreach (Thread tr in lThread)
154 {
155 Assert.That((tr.Name == "ThreadTrackerThread"));
156 }
157 }
158
159
160 /// <summary>
161 /// Worker thread 0
162 /// </summary>
163 /// <param name="o"></param>
164 public void run(object o)
165 {
166 while (running)
167 {
168 Thread.Sleep(5000);
169 }
170 }
171
172 /// <summary>
173 /// Worker thread 1
174 /// </summary>
175 /// <param name="o"></param>
176 public void run2(object o)
177 {
178 try
179 {
180 while (running2)
181 {
182 Thread.Sleep(5000);
183 }
184
185 }
186 catch (ThreadAbortException)
187 {
188 }
189 }
190
191 } 55 }
192} 56}
diff --git a/OpenSim/Framework/ThreadTracker.cs b/OpenSim/Framework/ThreadTracker.cs
index d3a239d..b68d9b3 100644
--- a/OpenSim/Framework/ThreadTracker.cs
+++ b/OpenSim/Framework/ThreadTracker.cs
@@ -26,138 +26,21 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic; 29using System.Collections.Generic;
31using System.Reflection; 30using System.Reflection;
32using System.Threading; 31using System.Diagnostics;
33using log4net; 32using log4net;
34 33
35namespace OpenSim.Framework 34namespace OpenSim.Framework
36{ 35{
37 public static class ThreadTracker 36 public static class ThreadTracker
38 { 37 {
39 private static readonly ILog m_log 38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 private static readonly long ThreadTimeout = 30 * 10000000;
43 public static List<ThreadTrackerItem> m_Threads;
44 public static Thread ThreadTrackerThread;
45 39
46 static ThreadTracker() 40 public static ProcessThreadCollection GetThreads()
47 { 41 {
48#if DEBUG 42 Process thisProc = Process.GetCurrentProcess();
49 m_Threads = new List<ThreadTrackerItem>(); 43 return thisProc.Threads;
50 ThreadTrackerThread = new Thread(ThreadTrackerThreadLoop);
51 ThreadTrackerThread.Name = "ThreadTrackerThread";
52 ThreadTrackerThread.IsBackground = true;
53 ThreadTrackerThread.Priority = ThreadPriority.BelowNormal;
54 ThreadTrackerThread.Start();
55 Add(ThreadTrackerThread);
56#endif
57 } 44 }
58
59 private static void ThreadTrackerThreadLoop()
60 {
61 try
62 {
63 while (true)
64 {
65 Thread.Sleep(5000);
66 CleanUp();
67 }
68 }
69 catch (Exception e)
70 {
71 m_log.ErrorFormat(
72 "[THREAD TRACKER]: Thread tracker cleanup thread terminating with exception. Please report this error. Exception is {0}",
73 e);
74 }
75 }
76
77 public static void Add(Thread thread)
78 {
79#if DEBUG
80 if (thread != null)
81 {
82 lock (m_Threads)
83 {
84 ThreadTrackerItem tti = new ThreadTrackerItem();
85 tti.Thread = thread;
86 tti.LastSeenActive = DateTime.Now.Ticks;
87 m_Threads.Add(tti);
88 }
89 }
90#endif
91 }
92
93 public static void Remove(Thread thread)
94 {
95#if DEBUG
96 lock (m_Threads)
97 {
98 foreach (ThreadTrackerItem tti in new ArrayList(m_Threads))
99 {
100 if (tti.Thread == thread)
101 m_Threads.Remove(tti);
102 }
103 }
104#endif
105 }
106
107 public static void CleanUp()
108 {
109 lock (m_Threads)
110 {
111 foreach (ThreadTrackerItem tti in new ArrayList(m_Threads))
112 {
113 try
114 {
115
116
117 if (tti.Thread.IsAlive)
118 {
119 // Its active
120 tti.LastSeenActive = DateTime.Now.Ticks;
121 }
122 else
123 {
124 // Its not active -- if its expired then remove it
125 if (tti.LastSeenActive + ThreadTimeout < DateTime.Now.Ticks)
126 m_Threads.Remove(tti);
127 }
128 }
129 catch (NullReferenceException)
130 {
131 m_Threads.Remove(tti);
132 }
133 }
134 }
135 }
136
137 public static List<Thread> GetThreads()
138 {
139 if (m_Threads == null)
140 return null;
141
142 List<Thread> threads = new List<Thread>();
143 lock (m_Threads)
144 {
145 foreach (ThreadTrackerItem tti in new ArrayList(m_Threads))
146 {
147 threads.Add(tti.Thread);
148 }
149 }
150 return threads;
151 }
152
153 #region Nested type: ThreadTrackerItem
154
155 public class ThreadTrackerItem
156 {
157 public long LastSeenActive;
158 public Thread Thread;
159 }
160
161 #endregion
162 } 45 }
163} 46}
diff --git a/OpenSim/Framework/ThrottleOutPacketType.cs b/OpenSim/Framework/ThrottleOutPacketType.cs
index 0843757..fd490a5 100644
--- a/OpenSim/Framework/ThrottleOutPacketType.cs
+++ b/OpenSim/Framework/ThrottleOutPacketType.cs
@@ -29,9 +29,9 @@ using System;
29 29
30namespace OpenSim.Framework 30namespace OpenSim.Framework
31{ 31{
32 [Flags]
33 public enum ThrottleOutPacketType : int 32 public enum ThrottleOutPacketType : int
34 { 33 {
34 Unknown = -1, // Also doubles as 'do not throttle'
35 Resend = 0, 35 Resend = 0,
36 Land = 1, 36 Land = 1,
37 Wind = 2, 37 Wind = 2,
@@ -39,11 +39,5 @@ namespace OpenSim.Framework
39 Task = 4, 39 Task = 4,
40 Texture = 5, 40 Texture = 5,
41 Asset = 6, 41 Asset = 6,
42 Unknown = 7, // Also doubles as 'do not throttle'
43 Back = 8,
44
45 TypeMask = 15, // The mask to mask off the flags
46
47 LowPriority = 128 // Additional flags
48 } 42 }
49} 43}
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 0851d26..38729c6 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1231,6 +1231,42 @@ namespace OpenSim.Framework
1231 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; 1231 return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri;
1232 } 1232 }
1233 1233
1234 public static byte[] StringToBytes256(string str)
1235 {
1236 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
1237 if (str.Length > 254) str = str.Remove(254);
1238 if (!str.EndsWith("\0")) { str += "\0"; }
1239
1240 // Because this is UTF-8 encoding and not ASCII, it's possible we
1241 // might have gotten an oversized array even after the string trim
1242 byte[] data = UTF8.GetBytes(str);
1243 if (data.Length > 256)
1244 {
1245 Array.Resize<byte>(ref data, 256);
1246 data[255] = 0;
1247 }
1248
1249 return data;
1250 }
1251
1252 public static byte[] StringToBytes1024(string str)
1253 {
1254 if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
1255 if (str.Length > 1023) str = str.Remove(1023);
1256 if (!str.EndsWith("\0")) { str += "\0"; }
1257
1258 // Because this is UTF-8 encoding and not ASCII, it's possible we
1259 // might have gotten an oversized array even after the string trim
1260 byte[] data = UTF8.GetBytes(str);
1261 if (data.Length > 1024)
1262 {
1263 Array.Resize<byte>(ref data, 1024);
1264 data[1023] = 0;
1265 }
1266
1267 return data;
1268 }
1269
1234 #region FireAndForget Threading Pattern 1270 #region FireAndForget Threading Pattern
1235 1271
1236 public static void FireAndForget(System.Threading.WaitCallback callback) 1272 public static void FireAndForget(System.Threading.WaitCallback callback)
@@ -1247,7 +1283,9 @@ namespace OpenSim.Framework
1247 { 1283 {
1248 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; 1284 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
1249 1285
1250 callback.EndInvoke(ar); 1286 try { callback.EndInvoke(ar); }
1287 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
1288
1251 ar.AsyncWaitHandle.Close(); 1289 ar.AsyncWaitHandle.Close();
1252 } 1290 }
1253 1291
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index 33b01e5..555baa4 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -91,6 +91,18 @@ namespace OpenSim
91 m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config"); 91 m_log.Info("[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config");
92 } 92 }
93 93
94 // Increase the number of IOCP threads available. Mono defaults to a tragically low number
95 int workerThreads, iocpThreads;
96 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
97 m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads);
98 if (workerThreads < 500 || iocpThreads < 1000)
99 {
100 workerThreads = 500;
101 iocpThreads = 1000;
102 m_log.Info("[OPENSIM MAIN]: Bumping up to 500 worker threads and 1000 IOCP threads");
103 System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads);
104 }
105
94 // Check if the system is compatible with OpenSimulator. 106 // Check if the system is compatible with OpenSimulator.
95 // Ensures that the minimum system requirements are met 107 // Ensures that the minimum system requirements are met
96 m_log.Info("Performing compatibility checks... "); 108 m_log.Info("Performing compatibility checks... ");
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 6e7a2a0..4592c31 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -675,7 +675,7 @@ namespace OpenSim
675 675
676 if (foundClientServer) 676 if (foundClientServer)
677 { 677 {
678 m_clientServers[clientServerElement].Server.Close(); 678 m_clientServers[clientServerElement].NetworkStop();
679 m_clientServers.RemoveAt(clientServerElement); 679 m_clientServers.RemoveAt(clientServerElement);
680 } 680 }
681 IScene scene; 681 IScene scene;
diff --git a/OpenSim/Region/ClientStack/IClientNetworkServer.cs b/OpenSim/Region/ClientStack/IClientNetworkServer.cs
index a71ad4d..54a441b 100644
--- a/OpenSim/Region/ClientStack/IClientNetworkServer.cs
+++ b/OpenSim/Region/ClientStack/IClientNetworkServer.cs
@@ -38,7 +38,7 @@ namespace OpenSim.Region.ClientStack
38 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, 38 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource,
39 AgentCircuitManager authenticateClass); 39 AgentCircuitManager authenticateClass);
40 40
41 Socket Server { get; } 41 void NetworkStop();
42 bool HandlesRegion(Location x); 42 bool HandlesRegion(Location x);
43 void AddScene(IScene x); 43 void AddScene(IScene x);
44 44
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs
deleted file mode 100644
index ee15171..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/ILLClientStackNetworkHandler.cs
+++ /dev/null
@@ -1,38 +0,0 @@
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 OpenSimulator 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 ILLClientStackNetworkHandler
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}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs
deleted file mode 100644
index 31f9580..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/ILLPacketHandler.cs
+++ /dev/null
@@ -1,83 +0,0 @@
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 OpenSimulator 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 OpenMetaverse;
30using OpenMetaverse.Packets;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.ClientStack.LindenUDP
34{
35 public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes);
36 public delegate void PacketDrop(Packet pack, Object id);
37 public delegate void QueueEmpty(ThrottleOutPacketType queue);
38 public delegate bool SynchronizeClientHandler(IScene scene, Packet packet, UUID agentID, ThrottleOutPacketType throttlePacketType);
39
40 /// <summary>
41 /// Interface to a class that handles all the activity involved with maintaining the client circuit (handling acks,
42 /// resends, pings, etc.)
43 /// </summary>
44 public interface ILLPacketHandler : IDisposable
45 {
46 event PacketStats OnPacketStats;
47 event PacketDrop OnPacketDrop;
48 event QueueEmpty OnQueueEmpty;
49 SynchronizeClientHandler SynchronizeClient { set; }
50
51 int PacketsReceived { get; }
52 int PacketsReceivedReported { get; }
53 uint ResendTimeout { get; set; }
54 bool ReliableIsImportant { get; set; }
55 int MaxReliableResends { get; set; }
56
57 /// <summary>
58 /// Initial handling of a received packet. It will be processed later in ProcessInPacket()
59 /// </summary>
60 /// <param name="packet"></param>
61 void InPacket(Packet packet);
62
63 /// <summary>
64 /// Take action depending on the type and contents of an received packet.
65 /// </summary>
66 /// <param name="item"></param>
67 void ProcessInPacket(LLQueItem item);
68
69 void ProcessOutPacket(LLQueItem item);
70 void OutPacket(Packet NewPack,
71 ThrottleOutPacketType throttlePacketType);
72 void OutPacket(Packet NewPack,
73 ThrottleOutPacketType throttlePacketType, Object id);
74 LLPacketQueue PacketQueue { get; }
75 void Flush();
76 void Clear();
77 ClientInfo GetClientInfo();
78 void SetClientInfo(ClientInfo info);
79 void AddImportantPacket(PacketType type);
80 void RemoveImportantPacket(PacketType type);
81 int GetQueueCount(ThrottleOutPacketType queue);
82 }
83}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs
index 0ed2bc1..90b3ede 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLQueItem.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacket.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -26,24 +26,32 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse.Packets;
30using OpenSim.Framework; 29using OpenSim.Framework;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
31 32
32namespace OpenSim.Region.ClientStack.LindenUDP 33namespace OpenSim.Region.ClientStack.LindenUDP
33{ 34{
34 public class LLQueItem 35 /// <summary>
36 /// Holds a reference to a <seealso cref="LLUDPClient"/> and a <seealso cref="Packet"/>
37 /// for incoming packets
38 /// </summary>
39 public sealed class IncomingPacket
35 { 40 {
36 public LLQueItem() 41 /// <summary>Client this packet came from</summary>
42 public LLUDPClient Client;
43 /// <summary>Packet data that has been received</summary>
44 public Packet Packet;
45
46 /// <summary>
47 /// Default constructor
48 /// </summary>
49 /// <param name="client">Reference to the client this packet came from</param>
50 /// <param name="packet">Packet data</param>
51 public IncomingPacket(LLUDPClient client, Packet packet)
37 { 52 {
53 Client = client;
54 Packet = packet;
38 } 55 }
39
40 public Packet Packet;
41 public bool Incoming;
42 public ThrottleOutPacketType throttleType;
43 public int TickCount;
44 public Object Identifier;
45 public int Resends;
46 public int Length;
47 public uint Sequence;
48 } 56 }
49} 57}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs
index a80c1f0..1f73a1d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/KillPacket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/IncomingPacketHistoryCollection.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -25,47 +25,49 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using OpenMetaverse.Packets; 28using System;
29using System.Collections.Generic;
29 30
30namespace OpenSim.Region.ClientStack.LindenUDP 31namespace OpenSim.Region.ClientStack.LindenUDP
31{ 32{
32 /// <summary> 33 /// <summary>
33 /// When packetqueue dequeues this packet in the outgoing stream, it thread aborts 34 /// A circular buffer and hashset for tracking incoming packet sequence
34 /// Ensures that the thread abort happens from within the client thread 35 /// numbers
35 /// regardless of where the close method is called
36 /// </summary> 36 /// </summary>
37 class KillPacket : Packet 37 public sealed class IncomingPacketHistoryCollection
38 { 38 {
39 public override int Length 39 private readonly uint[] m_items;
40 { 40 private HashSet<uint> m_hashSet;
41 get { return 0; } 41 private int m_first;
42 } 42 private int m_next;
43 private int m_capacity;
43 44
44 public override void FromBytes(Header header, byte[] bytes, ref int i, ref int packetEnd) 45 public IncomingPacketHistoryCollection(int capacity)
45 { 46 {
47 this.m_capacity = capacity;
48 m_items = new uint[capacity];
49 m_hashSet = new HashSet<uint>();
46 } 50 }
47 51
48 public override void FromBytes(byte[] bytes, ref int i, ref int packetEnd, byte[] zeroBuffer) 52 public bool TryEnqueue(uint ack)
49 { 53 {
50 } 54 lock (m_hashSet)
55 {
56 if (m_hashSet.Add(ack))
57 {
58 m_items[m_next] = ack;
59 m_next = (m_next + 1) % m_capacity;
60 if (m_next == m_first)
61 {
62 m_hashSet.Remove(m_items[m_first]);
63 m_first = (m_first + 1) % m_capacity;
64 }
51 65
52 public override byte[] ToBytes() 66 return true;
53 { 67 }
54 return new byte[0]; 68 }
55 }
56 69
57 public override byte[][] ToBytesMultiple() 70 return false;
58 {
59 return new byte[][] { new byte[0] };
60 }
61
62 public KillPacket()
63 {
64 Type = PacketType.UseCircuitCode;
65 Header = new Header();
66 Header.Frequency = OpenMetaverse.PacketFrequency.Low;
67 Header.ID = 65531;
68 Header.Reliable = true;
69 } 71 }
70 } 72 }
71} 73}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index 19ad0b4..2f1face 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -76,27 +76,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
76 { 76 {
77 if (m_currentPacket <= m_stopPacket) 77 if (m_currentPacket <= m_stopPacket)
78 { 78 {
79 bool SendMore = true; 79 int count = 0;
80 bool sendMore = true;
81
80 if (!m_sentInfo || (m_currentPacket == 0)) 82 if (!m_sentInfo || (m_currentPacket == 0))
81 { 83 {
82 if (SendFirstPacket(client)) 84 sendMore = !SendFirstPacket(client);
83 { 85
84 SendMore = false;
85 }
86 m_sentInfo = true; 86 m_sentInfo = true;
87 m_currentPacket++; 87 ++m_currentPacket;
88 ++count;
88 } 89 }
89 if (m_currentPacket < 2) 90 if (m_currentPacket < 2)
90 { 91 {
91 m_currentPacket = 2; 92 m_currentPacket = 2;
92 } 93 }
93 94
94 int count = 0; 95 while (sendMore && count < maxpack && m_currentPacket <= m_stopPacket)
95 while (SendMore && count < maxpack && m_currentPacket <= m_stopPacket)
96 { 96 {
97 count++; 97 sendMore = SendPacket(client);
98 SendMore = SendPacket(client); 98 ++m_currentPacket;
99 m_currentPacket++; 99 ++count;
100 } 100 }
101 101
102 if (m_currentPacket > m_stopPacket) 102 if (m_currentPacket > m_stopPacket)
@@ -196,13 +196,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
196 196
197 m_currentPacket = StartPacket; 197 m_currentPacket = StartPacket;
198 } 198 }
199
200 if ((m_imageManager != null) && (m_imageManager.Client != null) && (m_imageManager.Client.PacketHandler != null))
201 if (m_imageManager.Client.PacketHandler.GetQueueCount(ThrottleOutPacketType.Texture) == 0)
202 {
203 //m_log.Debug("No textures queued, sending one packet to kickstart it");
204 SendPacket(m_imageManager.Client);
205 }
206 } 199 }
207 } 200 }
208 } 201 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index fe37a08..60dab5f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -58,526 +58,180 @@ namespace OpenSim.Region.ClientStack.LindenUDP
58 /// </summary> 58 /// </summary>
59 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector 59 public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector
60 { 60 {
61 // LLClientView Only
62 public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
63
64 /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary>
65 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
66
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
68 protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
62 69
63 /* static variables */ 70 private readonly LLUDPServer m_udpServer;
64 public static SynchronizeClientHandler SynchronizeClient; 71 private readonly LLUDPClient m_udpClient;
65 /* private variables */
66 private readonly UUID m_sessionId; 72 private readonly UUID m_sessionId;
67 private readonly UUID m_secureSessionId = UUID.Zero; 73 private readonly UUID m_secureSessionId;
68 74 private readonly UUID m_agentId;
69 private int m_debugPacketLevel; 75 private readonly uint m_circuitCode;
76 private readonly byte[] m_channelVersion = Utils.EmptyBytes;
77 private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>();
78 private readonly IGroupsModule m_GroupsModule;
70 79
71 //private readonly IAssetCache m_assetCache;
72 private int m_cachedTextureSerial; 80 private int m_cachedTextureSerial;
73 private Timer m_clientPingTimer;
74
75 private Timer m_avatarTerseUpdateTimer; 81 private Timer m_avatarTerseUpdateTimer;
76 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 82 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
77
78 private Timer m_primTerseUpdateTimer; 83 private Timer m_primTerseUpdateTimer;
79 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 84 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
80 private Timer m_primFullUpdateTimer; 85 private Timer m_primFullUpdateTimer;
81 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = 86 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = new List<ObjectUpdatePacket.ObjectDataBlock>();
82 new List<ObjectUpdatePacket.ObjectDataBlock>();
83
84 private bool m_clientBlocked;
85
86 private int m_probesWithNoIngressPackets;
87
88 private readonly UUID m_agentId;
89 private readonly uint m_circuitCode;
90 private int m_moneyBalance; 87 private int m_moneyBalance;
91 private readonly ILLPacketHandler m_PacketHandler;
92
93 private int m_animationSequenceNumber = 1; 88 private int m_animationSequenceNumber = 1;
94
95 private readonly byte[] m_channelVersion = Utils.StringToBytes("OpenSimulator Server"); // Dummy value needed by libSL
96
97 private readonly Dictionary<string, UUID> m_defaultAnimations = new Dictionary<string, UUID>();
98
99 private bool m_SendLogoutPacketWhenClosing = true; 89 private bool m_SendLogoutPacketWhenClosing = true;
100 90 private AgentUpdateArgs lastarg;
101 private int m_inPacketsChecked; 91 private bool m_IsActive = true;
102
103 // Used to adjust Sun Orbit values so Linden based viewers properly position sun
104 private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f;
105
106
107 /* protected variables */
108
109 protected static Dictionary<PacketType, PacketMethod> PacketHandlers =
110 new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients
111 92
112 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); 93 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
113 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 94 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
114
115 protected IScene m_scene; 95 protected IScene m_scene;
116
117 protected LLPacketServer m_networkServer;
118
119 protected LLImageManager m_imageManager; 96 protected LLImageManager m_imageManager;
120
121 /* public variables */
122 protected string m_firstName; 97 protected string m_firstName;
123 protected string m_lastName; 98 protected string m_lastName;
124 protected Thread m_clientThread; 99 protected Thread m_clientThread;
125 protected Vector3 m_startpos; 100 protected Vector3 m_startpos;
126 protected EndPoint m_userEndPoint; 101 protected EndPoint m_userEndPoint;
127 protected EndPoint m_proxyEndPoint;
128 protected UUID m_activeGroupID = UUID.Zero; 102 protected UUID m_activeGroupID = UUID.Zero;
129 protected string m_activeGroupName = String.Empty; 103 protected string m_activeGroupName = String.Empty;
130 protected ulong m_activeGroupPowers; 104 protected ulong m_activeGroupPowers;
131 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); 105 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
132 protected int m_avatarTerseUpdateRate = 50; 106 protected int m_terrainCheckerCount;
133 protected int m_avatarTerseUpdatesPerPacket = 5;
134 107
135 // LL uses these limits, apparently. Compressed terse would be 108 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet
136 // 23, but we don't have that yet
137 //
138 protected int m_primTerseUpdatesPerPacket = 10; 109 protected int m_primTerseUpdatesPerPacket = 10;
139 protected int m_primFullUpdatesPerPacket = 14; 110 protected int m_primFullUpdatesPerPacket = 14;
140
141 protected int m_primTerseUpdateRate = 10; 111 protected int m_primTerseUpdateRate = 10;
142 protected int m_primFullUpdateRate = 14; 112 protected int m_primFullUpdateRate = 14;
143
144 protected int m_textureSendLimit = 20; 113 protected int m_textureSendLimit = 20;
145 protected int m_textureDataLimit = 10; 114 protected int m_textureDataLimit = 10;
146 115 protected int m_avatarTerseUpdateRate = 50;
116 protected int m_avatarTerseUpdatesPerPacket = 5;
147 protected int m_packetMTU = 1400; 117 protected int m_packetMTU = 1400;
148
149 protected IAssetService m_assetService; 118 protected IAssetService m_assetService;
150 119
151 // LLClientView Only 120 #region Properties
152 public delegate void BinaryGenericMessage(Object sender, string method, byte[][] args);
153
154 /* Instantiated Designated Event Delegates */
155 //- used so we don't create new objects for each incoming packet and then toss it out later */
156
157 private GenericMessage handlerGenericMessage;
158 private RequestAvatarProperties handlerRequestAvatarProperties; //OnRequestAvatarProperties;
159 private UpdateAvatarProperties handlerUpdateAvatarProperties; // OnUpdateAvatarProperties;
160 private ChatMessage handlerChatFromClient; //OnChatFromClient;
161 private ChatMessage handlerChatFromClient2; //OnChatFromClient;
162 private ImprovedInstantMessage handlerInstantMessage; //OnInstantMessage;
163 private FriendActionDelegate handlerApproveFriendRequest; //OnApproveFriendRequest;
164 private FriendshipTermination handlerTerminateFriendship; //OnTerminateFriendship;
165 private RezObject handlerRezObject; //OnRezObject;
166 private DeRezObject handlerDeRezObject; //OnDeRezObject;
167 private ModifyTerrain handlerModifyTerrain;
168 private BakeTerrain handlerBakeTerrain;
169 private EstateChangeInfo handlerEstateChangeInfo;
170 private Action<IClientAPI> handlerRegionHandShakeReply; //OnRegionHandShakeReply;
171 private GenericCall2 handlerRequestWearables; //OnRequestWearables;
172 private Action<IClientAPI> handlerRequestAvatarsData; //OnRequestAvatarsData;
173 private SetAppearance handlerSetAppearance; //OnSetAppearance;
174 private AvatarNowWearing handlerAvatarNowWearing; //OnAvatarNowWearing;
175 private RezSingleAttachmentFromInv handlerRezSingleAttachment; //OnRezSingleAttachmentFromInv;
176 private RezMultipleAttachmentsFromInv handlerRezMultipleAttachments; //OnRezMultipleAttachmentsFromInv;
177 private UUIDNameRequest handlerDetachAttachmentIntoInv; // Detach attachment!
178 private ObjectAttach handlerObjectAttach; //OnObjectAttach;
179 private SetAlwaysRun handlerSetAlwaysRun; //OnSetAlwaysRun;
180 private GenericCall2 handlerCompleteMovementToRegion; //OnCompleteMovementToRegion;
181 private UpdateAgent handlerAgentUpdate; //OnAgentUpdate;
182 private StartAnim handlerStartAnim;
183 private StopAnim handlerStopAnim;
184 private AgentRequestSit handlerAgentRequestSit; //OnAgentRequestSit;
185 private AgentSit handlerAgentSit; //OnAgentSit;
186 private AvatarPickerRequest handlerAvatarPickerRequest; //OnAvatarPickerRequest;
187 private FetchInventory handlerAgentDataUpdateRequest; //OnAgentDataUpdateRequest;
188 private TeleportLocationRequest handlerSetStartLocationRequest; //OnSetStartLocationRequest;
189 private TeleportLandmarkRequest handlerTeleportLandmarkRequest; //OnTeleportLandmarkRequest;
190 private LinkObjects handlerLinkObjects; //OnLinkObjects;
191 private DelinkObjects handlerDelinkObjects; //OnDelinkObjects;
192 private AddNewPrim handlerAddPrim; //OnAddPrim;
193 private UpdateShape handlerUpdatePrimShape; //null;
194 private ObjectExtraParams handlerUpdateExtraParams; //OnUpdateExtraParams;
195 private ObjectDuplicate handlerObjectDuplicate;
196 private ObjectDuplicateOnRay handlerObjectDuplicateOnRay;
197 private ObjectRequest handlerObjectRequest;
198 private ObjectSelect handlerObjectSelect;
199 private ObjectDeselect handlerObjectDeselect;
200 private ObjectIncludeInSearch handlerObjectIncludeInSearch;
201 private UpdatePrimFlags handlerUpdatePrimFlags; //OnUpdatePrimFlags;
202 private UpdatePrimTexture handlerUpdatePrimTexture;
203 private GrabObject handlerGrabObject; //OnGrabObject;
204 private MoveObject handlerGrabUpdate; //OnGrabUpdate;
205 private DeGrabObject handlerDeGrabObject; //OnDeGrabObject;
206 private SpinStart handlerSpinStart; //OnSpinStart;
207 private SpinObject handlerSpinUpdate; //OnSpinUpdate;
208 private SpinStop handlerSpinStop; //OnSpinStop;
209 private GenericCall7 handlerObjectDescription;
210 private GenericCall7 handlerObjectName;
211 private GenericCall7 handlerObjectClickAction;
212 private GenericCall7 handlerObjectMaterial;
213 private ObjectPermissions handlerObjectPermissions;
214 private RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily; //OnRequestObjectPropertiesFamily;
215 //private TextureRequest handlerTextureRequest;
216 private UDPAssetUploadRequest handlerAssetUploadRequest; //OnAssetUploadRequest;
217 private RequestXfer handlerRequestXfer; //OnRequestXfer;
218 private XferReceive handlerXferReceive; //OnXferReceive;
219 private ConfirmXfer handlerConfirmXfer; //OnConfirmXfer;
220 private AbortXfer handlerAbortXfer;
221 private CreateInventoryFolder handlerCreateInventoryFolder; //OnCreateNewInventoryFolder;
222 private UpdateInventoryFolder handlerUpdateInventoryFolder;
223 private MoveInventoryFolder handlerMoveInventoryFolder;
224 private CreateNewInventoryItem handlerCreateNewInventoryItem; //OnCreateNewInventoryItem;
225 private FetchInventory handlerFetchInventory;
226 private FetchInventoryDescendents handlerFetchInventoryDescendents; //OnFetchInventoryDescendents;
227 private PurgeInventoryDescendents handlerPurgeInventoryDescendents; //OnPurgeInventoryDescendents;
228 private UpdateInventoryItem handlerUpdateInventoryItem;
229 private CopyInventoryItem handlerCopyInventoryItem;
230 private MoveInventoryItem handlerMoveInventoryItem;
231 private RemoveInventoryItem handlerRemoveInventoryItem;
232 private RemoveInventoryFolder handlerRemoveInventoryFolder;
233 private RequestTaskInventory handlerRequestTaskInventory; //OnRequestTaskInventory;
234 private UpdateTaskInventory handlerUpdateTaskInventory; //OnUpdateTaskInventory;
235 private MoveTaskInventory handlerMoveTaskItem;
236 private RemoveTaskInventory handlerRemoveTaskItem; //OnRemoveTaskItem;
237 private RezScript handlerRezScript; //OnRezScript;
238 private RequestMapBlocks handlerRequestMapBlocks; //OnRequestMapBlocks;
239 private RequestMapName handlerMapNameRequest; //OnMapNameRequest;
240 private TeleportLocationRequest handlerTeleportLocationRequest; //OnTeleportLocationRequest;
241 private MoneyBalanceRequest handlerMoneyBalanceRequest; //OnMoneyBalanceRequest;
242 private UUIDNameRequest handlerNameRequest;
243 private ParcelAccessListRequest handlerParcelAccessListRequest; //OnParcelAccessListRequest;
244 private ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest; //OnParcelAccessListUpdateRequest;
245 private ParcelPropertiesRequest handlerParcelPropertiesRequest; //OnParcelPropertiesRequest;
246 private ParcelDivideRequest handlerParcelDivideRequest; //OnParcelDivideRequest;
247 private ParcelJoinRequest handlerParcelJoinRequest; //OnParcelJoinRequest;
248 private ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest; //OnParcelPropertiesUpdateRequest;
249 private ParcelSelectObjects handlerParcelSelectObjects; //OnParcelSelectObjects;
250 private ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest; //OnParcelObjectOwnerRequest;
251 private ParcelAbandonRequest handlerParcelAbandonRequest;
252 private ParcelGodForceOwner handlerParcelGodForceOwner;
253 private ParcelReclaim handlerParcelReclaim;
254 private RequestTerrain handlerRequestTerrain;
255 private RequestTerrain handlerUploadTerrain;
256 private ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest;
257 private RegionInfoRequest handlerRegionInfoRequest; //OnRegionInfoRequest;
258 private EstateCovenantRequest handlerEstateCovenantRequest; //OnEstateCovenantRequest;
259 private RequestGodlikePowers handlerReqGodlikePowers; //OnRequestGodlikePowers;
260 private GodKickUser handlerGodKickUser; //OnGodKickUser;
261 private ViewerEffectEventHandler handlerViewerEffect; //OnViewerEffect;
262 private Action<IClientAPI> handlerLogout; //OnLogout;
263 private MoneyTransferRequest handlerMoneyTransferRequest; //OnMoneyTransferRequest;
264 private ParcelBuy handlerParcelBuy;
265 private EconomyDataRequest handlerEconomoyDataRequest;
266
267 private UpdateVector handlerUpdatePrimSinglePosition; //OnUpdatePrimSinglePosition;
268 private UpdatePrimSingleRotation handlerUpdatePrimSingleRotation; //OnUpdatePrimSingleRotation;
269 private UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition; //OnUpdatePrimSingleRotation;
270 private UpdateVector handlerUpdatePrimScale; //OnUpdatePrimScale;
271 private UpdateVector handlerUpdatePrimGroupScale; //OnUpdateGroupScale;
272 private UpdateVector handlerUpdateVector; //OnUpdatePrimGroupPosition;
273 private UpdatePrimRotation handlerUpdatePrimRotation; //OnUpdatePrimGroupRotation;
274 // private UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; //OnUpdatePrimGroupMouseRotation;
275 // private RequestAsset handlerRequestAsset; // OnRequestAsset;
276 private UUIDNameRequest handlerTeleportHomeRequest;
277
278 private RegionHandleRequest handlerRegionHandleRequest; // OnRegionHandleRequest
279 private ParcelInfoRequest handlerParcelInfoRequest; // OnParcelInfoRequest
280
281 private ScriptAnswer handlerScriptAnswer;
282 private RequestPayPrice handlerRequestPayPrice;
283 private ObjectSaleInfo handlerObjectSaleInfo;
284 private ObjectBuy handlerObjectBuy;
285 //private BuyObjectInventory handlerBuyObjectInventory;
286 private ObjectDeselect handlerObjectDetach;
287 private ObjectDrop handlerObjectDrop;
288 private AgentSit handlerOnUndo;
289
290 private ForceReleaseControls handlerForceReleaseControls;
291
292 private GodLandStatRequest handlerLandStatRequest;
293
294 private UUIDNameRequest handlerUUIDGroupNameRequest;
295
296 private ParcelDeedToGroup handlerParcelDeedToGroup;
297
298 private RequestObjectPropertiesFamily handlerObjectGroupRequest;
299 private ScriptReset handlerScriptReset;
300 private GetScriptRunning handlerGetScriptRunning;
301 private SetScriptRunning handlerSetScriptRunning;
302 private UpdateVector handlerAutoPilotGo;
303 //Gesture
304 private ActivateGesture handlerActivateGesture;
305 private DeactivateGesture handlerDeactivateGesture;
306 //Sound
307 private SoundTrigger handlerSoundTrigger;
308 private ObjectOwner handlerObjectOwner;
309
310 private DirPlacesQuery handlerDirPlacesQuery;
311 private DirFindQuery handlerDirFindQuery;
312 private DirLandQuery handlerDirLandQuery;
313 private DirPopularQuery handlerDirPopularQuery;
314 private DirClassifiedQuery handlerDirClassifiedQuery;
315 private ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime;
316
317 private MapItemRequest handlerMapItemRequest;
318
319 private StartLure handlerStartLure;
320 private TeleportLureRequest handlerTeleportLureRequest;
321
322 private NetworkStats handlerNetworkStatsUpdate;
323
324 private ClassifiedInfoRequest handlerClassifiedInfoRequest;
325 private ClassifiedInfoUpdate handlerClassifiedInfoUpdate;
326 private ClassifiedDelete handlerClassifiedDelete;
327 private ClassifiedDelete handlerClassifiedGodDelete;
328
329 private EventNotificationAddRequest handlerEventNotificationAddRequest;
330 private EventNotificationRemoveRequest handlerEventNotificationRemoveRequest;
331 private EventGodDelete handlerEventGodDelete;
332
333 private ParcelDwellRequest handlerParcelDwellRequest;
334
335 private UserInfoRequest handlerUserInfoRequest;
336 private UpdateUserInfo handlerUpdateUserInfo;
337
338 private RetrieveInstantMessages handlerRetrieveInstantMessages;
339
340 private PickDelete handlerPickDelete;
341 private PickGodDelete handlerPickGodDelete;
342 private PickInfoUpdate handlerPickInfoUpdate;
343 private AvatarNotesUpdate handlerAvatarNotesUpdate;
344
345 private MuteListRequest handlerMuteListRequest;
346
347 //private AvatarInterestUpdate handlerAvatarInterestUpdate;
348
349 private PlacesQuery handlerPlacesQuery;
350
351 private readonly IGroupsModule m_GroupsModule;
352
353 private AgentUpdateArgs lastarg = null;
354
355 //private TerrainUnacked handlerUnackedTerrain = null;
356
357 //**
358
359 /* Properties */
360
361 public UUID SecureSessionId
362 {
363 get { return m_secureSessionId; }
364 }
365
366 public IScene Scene
367 {
368 get { return m_scene; }
369 }
370
371 public UUID SessionId
372 {
373 get { return m_sessionId; }
374 }
375 121
122 public UUID SecureSessionId { get { return m_secureSessionId; } }
123 public IScene Scene { get { return m_scene; } }
124 public UUID SessionId { get { return m_sessionId; } }
376 public Vector3 StartPos 125 public Vector3 StartPos
377 { 126 {
378 get { return m_startpos; } 127 get { return m_startpos; }
379 set { m_startpos = value; } 128 set { m_startpos = value; }
380 } 129 }
381 130 public UUID AgentId { get { return m_agentId; } }
382 public UUID AgentId 131 public UUID ActiveGroupId { get { return m_activeGroupID; } }
383 { 132 public string ActiveGroupName { get { return m_activeGroupName; } }
384 get { return m_agentId; } 133 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
385 } 134 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
386
387 public UUID ActiveGroupId
388 {
389 get { return m_activeGroupID; }
390 }
391
392 public string ActiveGroupName
393 {
394 get { return m_activeGroupName; }
395 }
396
397 public ulong ActiveGroupPowers
398 {
399 get { return m_activeGroupPowers; }
400 }
401
402 public bool IsGroupMember(UUID groupID)
403 {
404 return m_groupPowers.ContainsKey(groupID);
405 }
406
407 public ulong GetGroupPowers(UUID groupID)
408 {
409 if (groupID == m_activeGroupID)
410 return m_activeGroupPowers;
411
412 if (m_groupPowers.ContainsKey(groupID))
413 return m_groupPowers[groupID];
414
415 return 0;
416 }
417
418 /// <summary>
419 /// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
420 /// </summary>
421 public bool ChildAgentStatus()
422 {
423 return m_scene.PresenceChildStatus(AgentId);
424 }
425
426 /// <summary> 135 /// <summary>
427 /// First name of the agent/avatar represented by the client 136 /// First name of the agent/avatar represented by the client
428 /// </summary> 137 /// </summary>
429 public string FirstName 138 public string FirstName { get { return m_firstName; } }
430 {
431 get { return m_firstName; }
432 }
433
434 /// <summary> 139 /// <summary>
435 /// Last name of the agent/avatar represented by the client 140 /// Last name of the agent/avatar represented by the client
436 /// </summary> 141 /// </summary>
437 public string LastName 142 public string LastName { get { return m_lastName; } }
438 {
439 get { return m_lastName; }
440 }
441
442 /// <summary> 143 /// <summary>
443 /// Full name of the client (first name and last name) 144 /// Full name of the client (first name and last name)
444 /// </summary> 145 /// </summary>
445 public string Name 146 public string Name { get { return FirstName + " " + LastName; } }
446 { 147 public uint CircuitCode { get { return m_circuitCode; } }
447 get { return FirstName + " " + LastName; } 148 public int MoneyBalance { get { return m_moneyBalance; } }
448 } 149 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
449
450 public uint CircuitCode
451 {
452 get { return m_circuitCode; }
453 }
454
455 public int MoneyBalance
456 {
457 get { return m_moneyBalance; }
458 }
459
460 public int NextAnimationSequenceNumber
461 {
462 get { return m_animationSequenceNumber++; }
463 }
464
465 public ILLPacketHandler PacketHandler
466 {
467 get { return m_PacketHandler; }
468 }
469
470 bool m_IsActive = true;
471
472 public bool IsActive 150 public bool IsActive
473 { 151 {
474 get { return m_IsActive; } 152 get { return m_IsActive; }
475 set { m_IsActive = value; } 153 set { m_IsActive = value; }
476 } 154 }
155 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
477 156
478 public bool SendLogoutPacketWhenClosing 157 #endregion Properties
479 {
480 set { m_SendLogoutPacketWhenClosing = value; }
481 }
482
483 /* METHODS */
484 158
485 /// <summary> 159 /// <summary>
486 /// Constructor 160 /// Constructor
487 /// </summary> 161 /// </summary>
488 public LLClientView( 162 public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
489 EndPoint remoteEP, IScene scene, LLPacketServer packServer, 163 UUID agentId, UUID sessionId, uint circuitCode)
490 AuthenticateResponse sessionInfo, UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP,
491 ClientStackUserSettings userSettings)
492 { 164 {
493 // Should be called first? 165 RegisterInterface<IClientIM>(this);
494 RegisterInterfaces(); 166 RegisterInterface<IClientChat>(this);
495 167 RegisterInterface<IClientIPEndpoint>(this);
496 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); 168
497 m_moneyBalance = 1000;
498
499 m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion());
500
501 InitDefaultAnimations(); 169 InitDefaultAnimations();
502 170
503 m_scene = scene; 171 m_scene = scene;
504 //m_assetCache = assetCache;
505
506 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 172 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
507 173 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
508 m_networkServer = packServer; 174 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
509 175 m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion());
510 m_agentId = agentId; 176 m_agentId = agentId;
511 m_sessionId = sessionId; 177 m_sessionId = sessionId;
178 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
512 m_circuitCode = circuitCode; 179 m_circuitCode = circuitCode;
513
514 m_userEndPoint = remoteEP; 180 m_userEndPoint = remoteEP;
515 m_proxyEndPoint = proxyEP;
516
517 m_firstName = sessionInfo.LoginInfo.First; 181 m_firstName = sessionInfo.LoginInfo.First;
518 m_lastName = sessionInfo.LoginInfo.Last; 182 m_lastName = sessionInfo.LoginInfo.Last;
519 m_startpos = sessionInfo.LoginInfo.StartPos; 183 m_startpos = sessionInfo.LoginInfo.StartPos;
184 m_moneyBalance = 1000;
520 185
521 if (sessionInfo.LoginInfo.SecureSession != UUID.Zero) 186 m_udpServer = udpServer;
522 { 187 m_udpClient = udpClient;
523 m_secureSessionId = sessionInfo.LoginInfo.SecureSession; 188 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
524 } 189 m_udpClient.OnPacketStats += PopulateStats;
525
526 // While working on this, the BlockingQueue had me fooled for a bit.
527 // The Blocking queue causes the thread to stop until there's something
528 // in it to process. It's an on-purpose threadlock though because
529 // without it, the clientloop will suck up all sim resources.
530
531 m_PacketHandler = new LLPacketHandler(this, m_networkServer, userSettings);
532 m_PacketHandler.SynchronizeClient = SynchronizeClient;
533 m_PacketHandler.OnPacketStats += PopulateStats;
534 m_PacketHandler.OnQueueEmpty += HandleQueueEmpty;
535
536 if (scene.Config != null)
537 {
538 IConfig clientConfig = scene.Config.Configs["LLClient"];
539 if (clientConfig != null)
540 {
541 m_PacketHandler.ReliableIsImportant =
542 clientConfig.GetBoolean("ReliableIsImportant",
543 false);
544 m_PacketHandler.MaxReliableResends = clientConfig.GetInt("MaxReliableResends",
545 m_PacketHandler.MaxReliableResends);
546 m_primTerseUpdatesPerPacket = clientConfig.GetInt("TerseUpdatesPerPacket",
547 m_primTerseUpdatesPerPacket);
548 m_primFullUpdatesPerPacket = clientConfig.GetInt("FullUpdatesPerPacket",
549 m_primFullUpdatesPerPacket);
550
551 m_primTerseUpdateRate = clientConfig.GetInt("TerseUpdateRate",
552 m_primTerseUpdateRate);
553 m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate",
554 m_primFullUpdateRate);
555
556 m_textureSendLimit = clientConfig.GetInt("TextureSendLimit",
557 m_textureSendLimit);
558
559 m_textureDataLimit = clientConfig.GetInt("TextureDataLimit",
560 m_textureDataLimit);
561
562 m_packetMTU = clientConfig.GetInt("PacketMTU", 1400);
563 }
564 }
565 190
566 RegisterLocalPacketHandlers(); 191 RegisterLocalPacketHandlers();
567 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
568 } 192 }
569 193
570 public void SetDebugPacketLevel(int newDebugPacketLevel) 194 public void SetDebugPacketLevel(int newDebug)
571 { 195 {
572 m_debugPacketLevel = newDebugPacketLevel;
573 } 196 }
574 197
575 # region Client Methods 198 #region Client Methods
576 199
577 private void CloseCleanup(bool shutdownCircuit) 200 /// <summary>
201 /// Close down the client view. This *must* be the last method called, since the last #
202 /// statement of CloseCleanup() aborts the thread.
203 /// </summary>
204 /// <param name="shutdownCircuit"></param>
205 public void Close(bool shutdownCircuit)
578 { 206 {
207 m_log.DebugFormat(
208 "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}",
209 shutdownCircuit, Name, m_scene.RegionInfo.RegionName);
579 210
580 211 if (m_imageManager != null)
212 m_imageManager.Close();
213
214 if (m_udpServer != null)
215 m_udpServer.Flush();
216
217 // raise an event on the packet server to Shutdown the circuit
218 // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup
219 // here otherwise we'll end up calling it twice.
220 // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks
221 // horribly tangly. Hopefully it should be possible to greatly simplify it.
222 if (shutdownCircuit)
223 {
224 if (OnConnectionClosed != null)
225 OnConnectionClosed(this);
226 }
227 else
228 {
229 CloseCleanup(shutdownCircuit);
230 }
231 }
232
233 private void CloseCleanup(bool shutdownCircuit)
234 {
581 m_scene.RemoveClient(AgentId); 235 m_scene.RemoveClient(AgentId);
582 236
583 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 237 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
@@ -590,9 +244,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
590 Thread.Sleep(2000); 244 Thread.Sleep(2000);
591 245
592 // Shut down timers. Thread Context of this method is murky. Lock all timers 246 // Shut down timers. Thread Context of this method is murky. Lock all timers
593 if (m_clientPingTimer.Enabled)
594 lock (m_clientPingTimer)
595 m_clientPingTimer.Stop();
596 if (m_avatarTerseUpdateTimer.Enabled) 247 if (m_avatarTerseUpdateTimer.Enabled)
597 lock (m_avatarTerseUpdateTimer) 248 lock (m_avatarTerseUpdateTimer)
598 m_avatarTerseUpdateTimer.Stop(); 249 m_avatarTerseUpdateTimer.Stop();
@@ -625,43 +276,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
625 // of the client thread regardless of where Close() is called. 276 // of the client thread regardless of where Close() is called.
626 KillEndDone(); 277 KillEndDone();
627 } 278 }
628
629 Terminate();
630 }
631 279
632 /// <summary> 280 IsActive = false;
633 /// Close down the client view. This *must* be the last method called, since the last #
634 /// statement of CloseCleanup() aborts the thread.
635 /// </summary>
636 /// <param name="shutdownCircuit"></param>
637 public void Close(bool shutdownCircuit)
638 {
639 m_clientPingTimer.Enabled = false;
640 281
641 m_log.DebugFormat( 282 m_avatarTerseUpdateTimer.Close();
642 "[CLIENT]: Close has been called with shutdownCircuit = {0} for {1} attached to scene {2}", 283 m_primTerseUpdateTimer.Close();
643 shutdownCircuit, Name, m_scene.RegionInfo.RegionName); 284 m_primFullUpdateTimer.Close();
644 285
645 if (m_imageManager != null) 286 //m_udpServer.OnPacketStats -= PopulateStats;
646 m_imageManager.Close(); 287 m_udpClient.Shutdown();
647 288
648 if (m_PacketHandler != null) 289 // wait for thread stoped
649 m_PacketHandler.Flush(); 290 // m_clientThread.Join();
650 291
651 // raise an event on the packet server to Shutdown the circuit 292 // delete circuit code
652 // Now, if we raise the event then the packet server will call this method itself, so don't try cleanup 293 //m_networkServer.CloseClient(this);
653 // here otherwise we'll end up calling it twice.
654 // FIXME: In truth, I might be wrong but this whole business of calling this method twice (with different args) looks
655 // horribly tangly. Hopefully it should be possible to greatly simplify it.
656 if (shutdownCircuit)
657 {
658 if (OnConnectionClosed != null)
659 OnConnectionClosed(this);
660 }
661 else
662 {
663 CloseCleanup(shutdownCircuit);
664 }
665 } 294 }
666 295
667 public void Kick(string message) 296 public void Kick(string message)
@@ -683,10 +312,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
683 public void Stop() 312 public void Stop()
684 { 313 {
685 // Shut down timers. Thread Context is Murky, lock all timers! 314 // Shut down timers. Thread Context is Murky, lock all timers!
686 if (m_clientPingTimer.Enabled)
687 lock (m_clientPingTimer)
688 m_clientPingTimer.Stop();
689
690 if (m_avatarTerseUpdateTimer.Enabled) 315 if (m_avatarTerseUpdateTimer.Enabled)
691 lock (m_avatarTerseUpdateTimer) 316 lock (m_avatarTerseUpdateTimer)
692 m_avatarTerseUpdateTimer.Stop(); 317 m_avatarTerseUpdateTimer.Stop();
@@ -700,54 +325,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 m_primFullUpdateTimer.Stop(); 325 m_primFullUpdateTimer.Stop();
701 } 326 }
702 327
703 public void Restart() 328 #endregion Client Methods
704 {
705 // re-construct
706 m_PacketHandler.Clear();
707
708 m_clientPingTimer = new Timer(5000);
709 m_clientPingTimer.Elapsed += CheckClientConnectivity;
710 m_clientPingTimer.Enabled = true;
711
712 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
713 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
714 m_avatarTerseUpdateTimer.AutoReset = false;
715
716 m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
717 m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
718 m_primTerseUpdateTimer.AutoReset = false;
719
720 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
721 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
722 m_primFullUpdateTimer.AutoReset = false;
723 }
724
725 private void Terminate()
726 {
727 IsActive = false;
728
729 m_clientPingTimer.Close();
730 m_avatarTerseUpdateTimer.Close();
731 m_primTerseUpdateTimer.Close();
732 m_primFullUpdateTimer.Close();
733
734 m_PacketHandler.OnPacketStats -= PopulateStats;
735 m_PacketHandler.Dispose();
736
737 // wait for thread stoped
738 // m_clientThread.Join();
739
740 // delete circuit code
741 //m_networkServer.CloseClient(this);
742 }
743
744 #endregion
745 329
746 # region Packet Handling 330 #region Packet Handling
747 331
748 public void PopulateStats(int inPackets, int outPackets, int unAckedBytes) 332 public void PopulateStats(int inPackets, int outPackets, int unAckedBytes)
749 { 333 {
750 handlerNetworkStatsUpdate = OnNetworkStatsUpdate; 334 NetworkStats handlerNetworkStatsUpdate = OnNetworkStatsUpdate;
751 if (handlerNetworkStatsUpdate != null) 335 if (handlerNetworkStatsUpdate != null)
752 { 336 {
753 handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes); 337 handlerNetworkStatsUpdate(inPackets, outPackets, unAckedBytes);
@@ -828,7 +412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
828 return result; 412 return result;
829 } 413 }
830 414
831 protected void DebugPacket(string direction, Packet packet) 415 /*protected void DebugPacket(string direction, Packet packet)
832 { 416 {
833 string info; 417 string info;
834 418
@@ -854,88 +438,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
854 } 438 }
855 439
856 Console.WriteLine(m_circuitCode + ":" + direction + ": " + info); 440 Console.WriteLine(m_circuitCode + ":" + direction + ": " + info);
857 } 441 }*/
858 442
859 /// <summary> 443 #endregion Packet Handling
860 /// Main packet processing loop for the UDP component of the client session. Both incoming and outgoing
861 /// packets are processed here.
862 /// </summary>
863 protected virtual void ClientLoop()
864 {
865 m_log.DebugFormat(
866 "[CLIENT]: Entered main packet processing loop for {0} in {1}", Name, Scene.RegionInfo.RegionName);
867
868 while (IsActive)
869 {
870 LLQueItem nextPacket = m_PacketHandler.PacketQueue.Dequeue();
871
872 if (nextPacket == null) {
873 m_log.DebugFormat("[CLIENT]: PacketQueue return null LLQueItem");
874 continue;
875 }
876
877 if (nextPacket.Incoming)
878 {
879 if (m_debugPacketLevel > 0)
880 DebugPacket("IN", nextPacket.Packet);
881 m_PacketHandler.ProcessInPacket(nextPacket);
882 }
883 else
884 {
885 if (m_debugPacketLevel > 0)
886 DebugPacket("OUT", nextPacket.Packet);
887 m_PacketHandler.ProcessOutPacket(nextPacket);
888 }
889 }
890 }
891
892 # endregion
893
894 protected int m_terrainCheckerCount;
895
896 /// <summary>
897 /// Event handler for check client timer
898 /// Checks to ensure that the client is still connected. If the client has failed to respond to many pings
899 /// in succession then close down the connection.
900 /// </summary>
901 /// <param name="sender"></param>
902 /// <param name="e"></param>
903 protected void CheckClientConnectivity(object sender, ElapsedEventArgs e)
904 {
905 if (m_PacketHandler.PacketsReceived == m_inPacketsChecked)
906 {
907 // no packet came in since the last time we checked...
908
909 m_probesWithNoIngressPackets++;
910 if ((m_probesWithNoIngressPackets > 30 && !m_clientBlocked) // agent active
911 || (m_probesWithNoIngressPackets > 90 && m_clientBlocked)) // agent paused
912 {
913 m_clientPingTimer.Enabled = false;
914
915 m_log.WarnFormat(
916 "[CLIENT]: Client for agent {0} {1} has stopped responding to pings. Closing connection",
917 Name, AgentId);
918
919 if (OnConnectionClosed != null)
920 {
921 OnConnectionClosed(this);
922 }
923 }
924 else
925 {
926 // this will normally trigger at least one packet (ping response)
927 SendStartPingCheck(0);
928 }
929 }
930 else
931 {
932 // Something received in the meantime - we can reset the counters
933 m_probesWithNoIngressPackets = 0;
934 // ... and store the current number of packets received to find out if another one got in on the next cycle
935 m_inPacketsChecked = m_PacketHandler.PacketsReceived;
936 }
937
938 }
939 444
940 # region Setup 445 # region Setup
941 446
@@ -945,13 +450,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
945 /// </summary> 450 /// </summary>
946 protected virtual void InitNewClient() 451 protected virtual void InitNewClient()
947 { 452 {
948 //this.UploadAssets = new AgentAssetUpload(this, m_assetCache, m_inventoryCache);
949
950 // Ping the client regularly to check that it's still there
951 m_clientPingTimer = new Timer(5000);
952 m_clientPingTimer.Elapsed += CheckClientConnectivity;
953 m_clientPingTimer.Enabled = true;
954
955 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate); 453 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
956 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates); 454 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
957 m_avatarTerseUpdateTimer.AutoReset = false; 455 m_avatarTerseUpdateTimer.AutoReset = false;
@@ -971,27 +469,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
971 469
972 public virtual void Start() 470 public virtual void Start()
973 { 471 {
974 m_clientThread = new Thread(RunUserSession); 472 // This sets up all the timers
975 m_clientThread.Name = "ClientThread"; 473 InitNewClient();
976 m_clientThread.IsBackground = true;
977 m_clientThread.Start();
978 ThreadTracker.Add(m_clientThread);
979 } 474 }
980 475
981 /// <summary> 476 /// <summary>
982 /// Run a user session. This method lies at the base of the entire client thread. 477 /// Run a user session. This method lies at the base of the entire client thread.
983 /// </summary> 478 /// </summary>
984 protected virtual void RunUserSession() 479 protected void RunUserSession()
985 { 480 {
986 //tell this thread we are using the culture set up for the sim (currently hardcoded to en_US)
987 //otherwise it will override this and use the system default
988 Culture.SetCurrentCulture();
989
990 try 481 try
991 { 482 {
992 // This sets up all the timers 483
993 InitNewClient();
994 ClientLoop();
995 } 484 }
996 catch (Exception e) 485 catch (Exception e)
997 { 486 {
@@ -1015,11 +504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1015 + "Any further actions taken will not be processed.\n" 504 + "Any further actions taken will not be processed.\n"
1016 + "Please relog", true); 505 + "Please relog", true);
1017 506
1018 LLQueItem item = new LLQueItem(); 507 m_udpServer.SendPacket(m_agentId, packet, ThrottleOutPacketType.Unknown, false);
1019 item.Packet = packet;
1020 item.Sequence = packet.Header.Sequence;
1021
1022 m_PacketHandler.ProcessOutPacket(item);
1023 508
1024 // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to 509 // There may be a better way to do this. Perhaps kick? Not sure this propogates notifications to
1025 // listeners yet, though. 510 // listeners yet, though.
@@ -1037,7 +522,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1037 522
1038 # endregion 523 # endregion
1039 524
1040 // Previously ClientView.API partial class 525 #region Events
526
1041 public event GenericMessage OnGenericMessage; 527 public event GenericMessage OnGenericMessage;
1042 public event BinaryGenericMessage OnBinaryGenericMessage; 528 public event BinaryGenericMessage OnBinaryGenericMessage;
1043 public event Action<IClientAPI> OnLogout; 529 public event Action<IClientAPI> OnLogout;
@@ -1197,13 +683,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1197 public event GetScriptRunning OnGetScriptRunning; 683 public event GetScriptRunning OnGetScriptRunning;
1198 public event SetScriptRunning OnSetScriptRunning; 684 public event SetScriptRunning OnSetScriptRunning;
1199 public event UpdateVector OnAutoPilotGo; 685 public event UpdateVector OnAutoPilotGo;
1200
1201 public event TerrainUnacked OnUnackedTerrain; 686 public event TerrainUnacked OnUnackedTerrain;
1202
1203 public event ActivateGesture OnActivateGesture; 687 public event ActivateGesture OnActivateGesture;
1204 public event DeactivateGesture OnDeactivateGesture; 688 public event DeactivateGesture OnDeactivateGesture;
1205 public event ObjectOwner OnObjectOwner; 689 public event ObjectOwner OnObjectOwner;
1206
1207 public event DirPlacesQuery OnDirPlacesQuery; 690 public event DirPlacesQuery OnDirPlacesQuery;
1208 public event DirFindQuery OnDirFindQuery; 691 public event DirFindQuery OnDirFindQuery;
1209 public event DirLandQuery OnDirLandQuery; 692 public event DirLandQuery OnDirLandQuery;
@@ -1211,45 +694,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1211 public event DirClassifiedQuery OnDirClassifiedQuery; 694 public event DirClassifiedQuery OnDirClassifiedQuery;
1212 public event EventInfoRequest OnEventInfoRequest; 695 public event EventInfoRequest OnEventInfoRequest;
1213 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime; 696 public event ParcelSetOtherCleanTime OnParcelSetOtherCleanTime;
1214
1215 public event MapItemRequest OnMapItemRequest; 697 public event MapItemRequest OnMapItemRequest;
1216
1217 public event OfferCallingCard OnOfferCallingCard; 698 public event OfferCallingCard OnOfferCallingCard;
1218 public event AcceptCallingCard OnAcceptCallingCard; 699 public event AcceptCallingCard OnAcceptCallingCard;
1219 public event DeclineCallingCard OnDeclineCallingCard; 700 public event DeclineCallingCard OnDeclineCallingCard;
1220 public event SoundTrigger OnSoundTrigger; 701 public event SoundTrigger OnSoundTrigger;
1221
1222 public event StartLure OnStartLure; 702 public event StartLure OnStartLure;
1223 public event TeleportLureRequest OnTeleportLureRequest; 703 public event TeleportLureRequest OnTeleportLureRequest;
1224 public event NetworkStats OnNetworkStatsUpdate; 704 public event NetworkStats OnNetworkStatsUpdate;
1225
1226 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 705 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
1227 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 706 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
1228 public event ClassifiedDelete OnClassifiedDelete; 707 public event ClassifiedDelete OnClassifiedDelete;
1229 public event ClassifiedDelete OnClassifiedGodDelete; 708 public event ClassifiedDelete OnClassifiedGodDelete;
1230
1231 public event EventNotificationAddRequest OnEventNotificationAddRequest; 709 public event EventNotificationAddRequest OnEventNotificationAddRequest;
1232 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 710 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
1233 public event EventGodDelete OnEventGodDelete; 711 public event EventGodDelete OnEventGodDelete;
1234
1235 public event ParcelDwellRequest OnParcelDwellRequest; 712 public event ParcelDwellRequest OnParcelDwellRequest;
1236
1237 public event UserInfoRequest OnUserInfoRequest; 713 public event UserInfoRequest OnUserInfoRequest;
1238 public event UpdateUserInfo OnUpdateUserInfo; 714 public event UpdateUserInfo OnUpdateUserInfo;
1239
1240 public event RetrieveInstantMessages OnRetrieveInstantMessages; 715 public event RetrieveInstantMessages OnRetrieveInstantMessages;
1241
1242 public event PickDelete OnPickDelete; 716 public event PickDelete OnPickDelete;
1243 public event PickGodDelete OnPickGodDelete; 717 public event PickGodDelete OnPickGodDelete;
1244 public event PickInfoUpdate OnPickInfoUpdate; 718 public event PickInfoUpdate OnPickInfoUpdate;
1245 public event AvatarNotesUpdate OnAvatarNotesUpdate; 719 public event AvatarNotesUpdate OnAvatarNotesUpdate;
1246
1247 public event MuteListRequest OnMuteListRequest; 720 public event MuteListRequest OnMuteListRequest;
1248 721 public event AvatarInterestUpdate OnAvatarInterestUpdate;
1249 //public event AvatarInterestUpdate OnAvatarInterestUpdate;
1250
1251 public event PlacesQuery OnPlacesQuery; 722 public event PlacesQuery OnPlacesQuery;
1252 723
724 #endregion Events
725
1253 public void ActivateGesture(UUID assetId, UUID gestureId) 726 public void ActivateGesture(UUID assetId, UUID gestureId)
1254 { 727 {
1255 } 728 }
@@ -1850,8 +1323,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1850 public void SendStartPingCheck(byte seq) 1323 public void SendStartPingCheck(byte seq)
1851 { 1324 {
1852 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck); 1325 StartPingCheckPacket pc = (StartPingCheckPacket)PacketPool.Instance.GetPacket(PacketType.StartPingCheck);
1853 pc.PingID.PingID = seq;
1854 pc.Header.Reliable = false; 1326 pc.Header.Reliable = false;
1327
1328 OutgoingPacket oldestPacket = m_udpClient.NeedAcks.GetOldest();
1329
1330 pc.PingID.PingID = seq;
1331 pc.PingID.OldestUnacked = (oldestPacket != null) ? oldestPacket.SequenceNumber : 0;
1332
1855 OutPacket(pc, ThrottleOutPacketType.Unknown); 1333 OutPacket(pc, ThrottleOutPacketType.Unknown);
1856 } 1334 }
1857 1335
@@ -1927,12 +1405,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1927 descend.ItemData[i].AssetID = item.AssetID; 1405 descend.ItemData[i].AssetID = item.AssetID;
1928 descend.ItemData[i].CreatorID = item.CreatorIdAsUuid; 1406 descend.ItemData[i].CreatorID = item.CreatorIdAsUuid;
1929 descend.ItemData[i].BaseMask = item.BasePermissions; 1407 descend.ItemData[i].BaseMask = item.BasePermissions;
1930 descend.ItemData[i].Description = LLUtil.StringToPacketBytes(item.Description); 1408 descend.ItemData[i].Description = Util.StringToBytes256(item.Description);
1931 descend.ItemData[i].EveryoneMask = item.EveryOnePermissions; 1409 descend.ItemData[i].EveryoneMask = item.EveryOnePermissions;
1932 descend.ItemData[i].OwnerMask = item.CurrentPermissions; 1410 descend.ItemData[i].OwnerMask = item.CurrentPermissions;
1933 descend.ItemData[i].FolderID = item.Folder; 1411 descend.ItemData[i].FolderID = item.Folder;
1934 descend.ItemData[i].InvType = (sbyte)item.InvType; 1412 descend.ItemData[i].InvType = (sbyte)item.InvType;
1935 descend.ItemData[i].Name = LLUtil.StringToPacketBytes(item.Name); 1413 descend.ItemData[i].Name = Util.StringToBytes256(item.Name);
1936 descend.ItemData[i].NextOwnerMask = item.NextPermissions; 1414 descend.ItemData[i].NextOwnerMask = item.NextPermissions;
1937 descend.ItemData[i].OwnerID = item.Owner; 1415 descend.ItemData[i].OwnerID = item.Owner;
1938 descend.ItemData[i].Type = (sbyte)item.AssetType; 1416 descend.ItemData[i].Type = (sbyte)item.AssetType;
@@ -2013,7 +1491,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2013 { 1491 {
2014 descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock(); 1492 descend.FolderData[i] = new InventoryDescendentsPacket.FolderDataBlock();
2015 descend.FolderData[i].FolderID = folder.ID; 1493 descend.FolderData[i].FolderID = folder.ID;
2016 descend.FolderData[i].Name = LLUtil.StringToPacketBytes(folder.Name); 1494 descend.FolderData[i].Name = Util.StringToBytes256(folder.Name);
2017 descend.FolderData[i].ParentID = folder.ParentID; 1495 descend.FolderData[i].ParentID = folder.ParentID;
2018 descend.FolderData[i].Type = (sbyte)folder.Type; 1496 descend.FolderData[i].Type = (sbyte)folder.Type;
2019 1497
@@ -2128,11 +1606,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2128 inventoryReply.InventoryData[0].BaseMask = item.BasePermissions; 1606 inventoryReply.InventoryData[0].BaseMask = item.BasePermissions;
2129 inventoryReply.InventoryData[0].CreationDate = item.CreationDate; 1607 inventoryReply.InventoryData[0].CreationDate = item.CreationDate;
2130 1608
2131 inventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(item.Description); 1609 inventoryReply.InventoryData[0].Description = Util.StringToBytes256(item.Description);
2132 inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions; 1610 inventoryReply.InventoryData[0].EveryoneMask = item.EveryOnePermissions;
2133 inventoryReply.InventoryData[0].FolderID = item.Folder; 1611 inventoryReply.InventoryData[0].FolderID = item.Folder;
2134 inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType; 1612 inventoryReply.InventoryData[0].InvType = (sbyte)item.InvType;
2135 inventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(item.Name); 1613 inventoryReply.InventoryData[0].Name = Util.StringToBytes256(item.Name);
2136 inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions; 1614 inventoryReply.InventoryData[0].NextOwnerMask = item.NextPermissions;
2137 inventoryReply.InventoryData[0].OwnerID = item.Owner; 1615 inventoryReply.InventoryData[0].OwnerID = item.Owner;
2138 inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions; 1616 inventoryReply.InventoryData[0].OwnerMask = item.CurrentPermissions;
@@ -2257,7 +1735,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2257 folderBlock.FolderID = folder.ID; 1735 folderBlock.FolderID = folder.ID;
2258 folderBlock.ParentID = folder.ParentID; 1736 folderBlock.ParentID = folder.ParentID;
2259 folderBlock.Type = -1; 1737 folderBlock.Type = -1;
2260 folderBlock.Name = LLUtil.StringToPacketBytes(folder.Name); 1738 folderBlock.Name = Util.StringToBytes256(folder.Name);
2261 1739
2262 return folderBlock; 1740 return folderBlock;
2263 } 1741 }
@@ -2275,11 +1753,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2275 itemBlock.AssetID = item.AssetID; 1753 itemBlock.AssetID = item.AssetID;
2276 itemBlock.CreatorID = item.CreatorIdAsUuid; 1754 itemBlock.CreatorID = item.CreatorIdAsUuid;
2277 itemBlock.BaseMask = item.BasePermissions; 1755 itemBlock.BaseMask = item.BasePermissions;
2278 itemBlock.Description = LLUtil.StringToPacketBytes(item.Description); 1756 itemBlock.Description = Util.StringToBytes256(item.Description);
2279 itemBlock.EveryoneMask = item.EveryOnePermissions; 1757 itemBlock.EveryoneMask = item.EveryOnePermissions;
2280 itemBlock.FolderID = item.Folder; 1758 itemBlock.FolderID = item.Folder;
2281 itemBlock.InvType = (sbyte)item.InvType; 1759 itemBlock.InvType = (sbyte)item.InvType;
2282 itemBlock.Name = LLUtil.StringToPacketBytes(item.Name); 1760 itemBlock.Name = Util.StringToBytes256(item.Name);
2283 itemBlock.NextOwnerMask = item.NextPermissions; 1761 itemBlock.NextOwnerMask = item.NextPermissions;
2284 itemBlock.OwnerID = item.Owner; 1762 itemBlock.OwnerID = item.Owner;
2285 itemBlock.OwnerMask = item.CurrentPermissions; 1763 itemBlock.OwnerMask = item.CurrentPermissions;
@@ -2339,11 +1817,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2339 bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid; 1817 bulkUpdate.ItemData[0].CreatorID = item.CreatorIdAsUuid;
2340 bulkUpdate.ItemData[0].BaseMask = item.BasePermissions; 1818 bulkUpdate.ItemData[0].BaseMask = item.BasePermissions;
2341 bulkUpdate.ItemData[0].CreationDate = item.CreationDate; 1819 bulkUpdate.ItemData[0].CreationDate = item.CreationDate;
2342 bulkUpdate.ItemData[0].Description = LLUtil.StringToPacketBytes(item.Description); 1820 bulkUpdate.ItemData[0].Description = Util.StringToBytes256(item.Description);
2343 bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions; 1821 bulkUpdate.ItemData[0].EveryoneMask = item.EveryOnePermissions;
2344 bulkUpdate.ItemData[0].FolderID = item.Folder; 1822 bulkUpdate.ItemData[0].FolderID = item.Folder;
2345 bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType; 1823 bulkUpdate.ItemData[0].InvType = (sbyte)item.InvType;
2346 bulkUpdate.ItemData[0].Name = LLUtil.StringToPacketBytes(item.Name); 1824 bulkUpdate.ItemData[0].Name = Util.StringToBytes256(item.Name);
2347 bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions; 1825 bulkUpdate.ItemData[0].NextOwnerMask = item.NextPermissions;
2348 bulkUpdate.ItemData[0].OwnerID = item.Owner; 1826 bulkUpdate.ItemData[0].OwnerID = item.Owner;
2349 bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions; 1827 bulkUpdate.ItemData[0].OwnerMask = item.CurrentPermissions;
@@ -2386,11 +1864,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2386 InventoryReply.InventoryData[0].AssetID = Item.AssetID; 1864 InventoryReply.InventoryData[0].AssetID = Item.AssetID;
2387 InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid; 1865 InventoryReply.InventoryData[0].CreatorID = Item.CreatorIdAsUuid;
2388 InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions; 1866 InventoryReply.InventoryData[0].BaseMask = Item.BasePermissions;
2389 InventoryReply.InventoryData[0].Description = LLUtil.StringToPacketBytes(Item.Description); 1867 InventoryReply.InventoryData[0].Description = Util.StringToBytes256(Item.Description);
2390 InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions; 1868 InventoryReply.InventoryData[0].EveryoneMask = Item.EveryOnePermissions;
2391 InventoryReply.InventoryData[0].FolderID = Item.Folder; 1869 InventoryReply.InventoryData[0].FolderID = Item.Folder;
2392 InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType; 1870 InventoryReply.InventoryData[0].InvType = (sbyte)Item.InvType;
2393 InventoryReply.InventoryData[0].Name = LLUtil.StringToPacketBytes(Item.Name); 1871 InventoryReply.InventoryData[0].Name = Util.StringToBytes256(Item.Name);
2394 InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions; 1872 InventoryReply.InventoryData[0].NextOwnerMask = Item.NextPermissions;
2395 InventoryReply.InventoryData[0].OwnerID = Item.Owner; 1873 InventoryReply.InventoryData[0].OwnerID = Item.Owner;
2396 InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions; 1874 InventoryReply.InventoryData[0].OwnerMask = Item.CurrentPermissions;
@@ -2557,7 +2035,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2557 /// <param name="message"></param> 2035 /// <param name="message"></param>
2558 /// <param name="modal"></param> 2036 /// <param name="modal"></param>
2559 /// <returns></returns> 2037 /// <returns></returns>
2560 protected AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal) 2038 public AgentAlertMessagePacket BuildAgentAlertPacket(string message, bool modal)
2561 { 2039 {
2562 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); 2040 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
2563 alertPack.AgentData.AgentID = AgentId; 2041 alertPack.AgentData.AgentID = AgentId;
@@ -2768,7 +2246,953 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2768 OutPacket(avatarReply, ThrottleOutPacketType.Task); 2246 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2769 } 2247 }
2770 2248
2771 #endregion 2249 /// <summary>
2250 /// Send the client an Estate message blue box pop-down with a single OK button
2251 /// </summary>
2252 /// <param name="FromAvatarID"></param>
2253 /// <param name="fromSessionID"></param>
2254 /// <param name="FromAvatarName"></param>
2255 /// <param name="Message"></param>
2256 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
2257 {
2258 if (!ChildAgentStatus())
2259 SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3()));
2260
2261 //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
2262 }
2263
2264 public void SendLogoutPacket()
2265 {
2266 // I know this is a bit of a hack, however there are times when you don't
2267 // want to send this, but still need to do the rest of the shutdown process
2268 // this method gets called from the packet server.. which makes it practically
2269 // impossible to do any other way.
2270
2271 if (m_SendLogoutPacketWhenClosing)
2272 {
2273 LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
2274 // TODO: don't create new blocks if recycling an old packet
2275 logReply.AgentData.AgentID = AgentId;
2276 logReply.AgentData.SessionID = SessionId;
2277 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
2278 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
2279 logReply.InventoryData[0].ItemID = UUID.Zero;
2280
2281 OutPacket(logReply, ThrottleOutPacketType.Task);
2282 }
2283 }
2284
2285 public void SendHealth(float health)
2286 {
2287 HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage);
2288 healthpacket.HealthData.Health = health;
2289 OutPacket(healthpacket, ThrottleOutPacketType.Task);
2290 }
2291
2292 public void SendAgentOnline(UUID[] agentIDs)
2293 {
2294 OnlineNotificationPacket onp = new OnlineNotificationPacket();
2295 OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length];
2296 for (int i = 0; i < agentIDs.Length; i++)
2297 {
2298 OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
2299 onpbl.AgentID = agentIDs[i];
2300 onpb[i] = onpbl;
2301 }
2302 onp.AgentBlock = onpb;
2303 onp.Header.Reliable = true;
2304 OutPacket(onp, ThrottleOutPacketType.Task);
2305 }
2306
2307 public void SendAgentOffline(UUID[] agentIDs)
2308 {
2309 OfflineNotificationPacket offp = new OfflineNotificationPacket();
2310 OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length];
2311 for (int i = 0; i < agentIDs.Length; i++)
2312 {
2313 OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
2314 onpbl.AgentID = agentIDs[i];
2315 offpb[i] = onpbl;
2316 }
2317 offp.AgentBlock = offpb;
2318 offp.Header.Reliable = true;
2319 OutPacket(offp, ThrottleOutPacketType.Task);
2320 }
2321
2322 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
2323 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
2324 {
2325 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2326 avatarSitResponse.SitObject.ID = TargetID;
2327 if (CameraAtOffset != Vector3.Zero)
2328 {
2329 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2330 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2331 }
2332 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2333 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2334 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
2335 avatarSitResponse.SitTransform.SitRotation = SitOrientation;
2336
2337 OutPacket(avatarSitResponse, ThrottleOutPacketType.Task);
2338 }
2339
2340 public void SendAdminResponse(UUID Token, uint AdminLevel)
2341 {
2342 GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket();
2343 GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock();
2344 GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock();
2345
2346 adb.AgentID = AgentId;
2347 adb.SessionID = SessionId; // More security
2348 gdb.GodLevel = (byte)AdminLevel;
2349 gdb.Token = Token;
2350 //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock;
2351 respondPacket.GrantData = gdb;
2352 respondPacket.AgentData = adb;
2353 OutPacket(respondPacket, ThrottleOutPacketType.Task);
2354 }
2355
2356 public void SendGroupMembership(GroupMembershipData[] GroupMembership)
2357 {
2358 m_groupPowers.Clear();
2359
2360 AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket();
2361 AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length];
2362 for (int i = 0; i < GroupMembership.Length; i++)
2363 {
2364 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
2365
2366 AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock();
2367 Group.AcceptNotices = GroupMembership[i].AcceptNotices;
2368 Group.Contribution = GroupMembership[i].Contribution;
2369 Group.GroupID = GroupMembership[i].GroupID;
2370 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
2371 Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName);
2372 Group.GroupPowers = GroupMembership[i].GroupPowers;
2373 Groups[i] = Group;
2374
2375
2376 }
2377 Groupupdate.GroupData = Groups;
2378 Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock();
2379 Groupupdate.AgentData.AgentID = AgentId;
2380 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
2381
2382 try
2383 {
2384 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2385 if (eq != null)
2386 {
2387 eq.GroupMembership(Groupupdate, this.AgentId);
2388 }
2389 }
2390 catch (Exception ex)
2391 {
2392 m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString());
2393 m_log.Warn("sending group membership data via UDP");
2394 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
2395 }
2396 }
2397
2398
2399 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2400 {
2401 UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket();
2402 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
2403 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
2404 uidnamebloc.ID = groupLLUID;
2405 uidnamebloc.GroupName = Utils.StringToBytes(GroupName);
2406 uidnameblock[0] = uidnamebloc;
2407 pack.UUIDNameBlock = uidnameblock;
2408 OutPacket(pack, ThrottleOutPacketType.Task);
2409 }
2410
2411 public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
2412 {
2413 LandStatReplyPacket lsrp = new LandStatReplyPacket();
2414 // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock();
2415 LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length];
2416 //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
2417 // lsrepdb.
2418 lsrp.RequestData.ReportType = reportType;
2419 lsrp.RequestData.RequestFlags = requestFlags;
2420 lsrp.RequestData.TotalObjectCount = resultCount;
2421 for (int i = 0; i < lsrpia.Length; i++)
2422 {
2423 LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
2424 lsrepdb.LocationX = lsrpia[i].LocationX;
2425 lsrepdb.LocationY = lsrpia[i].LocationY;
2426 lsrepdb.LocationZ = lsrpia[i].LocationZ;
2427 lsrepdb.Score = lsrpia[i].Score;
2428 lsrepdb.TaskID = lsrpia[i].TaskID;
2429 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
2430 lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName);
2431 lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName);
2432 lsrepdba[i] = lsrepdb;
2433 }
2434 lsrp.ReportData = lsrepdba;
2435 OutPacket(lsrp, ThrottleOutPacketType.Task);
2436 }
2437
2438 public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running)
2439 {
2440 ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket();
2441 scriptRunningReply.Script.ObjectID = objectID;
2442 scriptRunningReply.Script.ItemID = itemID;
2443 scriptRunningReply.Script.Running = running;
2444
2445 OutPacket(scriptRunningReply, ThrottleOutPacketType.Task);
2446 }
2447
2448 public void SendAsset(AssetRequestToClient req)
2449 {
2450 //m_log.Debug("sending asset " + req.RequestAssetID);
2451 TransferInfoPacket Transfer = new TransferInfoPacket();
2452 Transfer.TransferInfo.ChannelType = 2;
2453 Transfer.TransferInfo.Status = 0;
2454 Transfer.TransferInfo.TargetType = 0;
2455 if (req.AssetRequestSource == 2)
2456 {
2457 Transfer.TransferInfo.Params = new byte[20];
2458 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
2459 int assType = req.AssetInf.Type;
2460 Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
2461 }
2462 else if (req.AssetRequestSource == 3)
2463 {
2464 Transfer.TransferInfo.Params = req.Params;
2465 // Transfer.TransferInfo.Params = new byte[100];
2466 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
2467 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
2468 }
2469 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2470 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2471 Transfer.Header.Zerocoded = true;
2472 OutPacket(Transfer, ThrottleOutPacketType.Asset);
2473
2474 if (req.NumPackets == 1)
2475 {
2476 TransferPacketPacket TransferPacket = new TransferPacketPacket();
2477 TransferPacket.TransferData.Packet = 0;
2478 TransferPacket.TransferData.ChannelType = 2;
2479 TransferPacket.TransferData.TransferID = req.TransferRequestID;
2480 TransferPacket.TransferData.Data = req.AssetInf.Data;
2481 TransferPacket.TransferData.Status = 1;
2482 TransferPacket.Header.Zerocoded = true;
2483 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
2484 }
2485 else
2486 {
2487 int processedLength = 0;
2488 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2489 int packetNumber = 0;
2490
2491 while (processedLength < req.AssetInf.Data.Length)
2492 {
2493 TransferPacketPacket TransferPacket = new TransferPacketPacket();
2494 TransferPacket.TransferData.Packet = packetNumber;
2495 TransferPacket.TransferData.ChannelType = 2;
2496 TransferPacket.TransferData.TransferID = req.TransferRequestID;
2497
2498 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
2499 byte[] chunk = new byte[chunkSize];
2500 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
2501
2502 TransferPacket.TransferData.Data = chunk;
2503
2504 // 0 indicates more packets to come, 1 indicates last packet
2505 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
2506 {
2507 TransferPacket.TransferData.Status = 0;
2508 }
2509 else
2510 {
2511 TransferPacket.TransferData.Status = 1;
2512 }
2513 TransferPacket.Header.Zerocoded = true;
2514 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
2515
2516 processedLength += chunkSize;
2517 packetNumber++;
2518 }
2519 }
2520 }
2521
2522 public void SendTexture(AssetBase TextureAsset)
2523 {
2524
2525 }
2526
2527 public void SendRegionHandle(UUID regionID, ulong handle)
2528 {
2529 RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply);
2530 reply.ReplyBlock.RegionID = regionID;
2531 reply.ReplyBlock.RegionHandle = handle;
2532 OutPacket(reply, ThrottleOutPacketType.Land);
2533 }
2534
2535 public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y)
2536 {
2537 ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply);
2538 reply.AgentData.AgentID = m_agentId;
2539 reply.Data.ParcelID = parcelID;
2540 reply.Data.OwnerID = land.OwnerID;
2541 reply.Data.Name = Utils.StringToBytes(land.Name);
2542 reply.Data.Desc = Utils.StringToBytes(land.Description);
2543 reply.Data.ActualArea = land.Area;
2544 reply.Data.BillableArea = land.Area; // TODO: what is this?
2545
2546 // Bit 0: Mature, bit 7: on sale, other bits: no idea
2547 reply.Data.Flags = (byte)(
2548 ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) +
2549 ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0));
2550
2551 Vector3 pos = land.UserLocation;
2552 if (pos.Equals(Vector3.Zero))
2553 {
2554 pos = (land.AABBMax + land.AABBMin) * 0.5f;
2555 }
2556 reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x;
2557 reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y;
2558 reply.Data.GlobalZ = pos.Z;
2559 reply.Data.SimName = Utils.StringToBytes(info.RegionName);
2560 reply.Data.SnapshotID = land.SnapshotID;
2561 reply.Data.Dwell = land.Dwell;
2562 reply.Data.SalePrice = land.SalePrice;
2563 reply.Data.AuctionID = (int)land.AuctionID;
2564
2565 OutPacket(reply, ThrottleOutPacketType.Land);
2566 }
2567
2568 public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt)
2569 {
2570 ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest);
2571
2572 packet.Data.ObjectName = Utils.StringToBytes(objName);
2573 packet.Data.SimName = Utils.StringToBytes(simName);
2574 packet.Data.SimPosition = pos;
2575 packet.Data.LookAt = lookAt;
2576
2577 OutPacket(packet, ThrottleOutPacketType.Task);
2578 }
2579
2580 public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data)
2581 {
2582 DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
2583
2584 packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
2585
2586 packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
2587 packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
2588
2589 packet.QueryReplies =
2590 new DirPlacesReplyPacket.QueryRepliesBlock[data.Length];
2591
2592 packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[
2593 data.Length];
2594
2595 packet.AgentData.AgentID = AgentId;
2596
2597 packet.QueryData[0].QueryID = queryID;
2598
2599 int i = 0;
2600 foreach (DirPlacesReplyData d in data)
2601 {
2602 packet.QueryReplies[i] =
2603 new DirPlacesReplyPacket.QueryRepliesBlock();
2604 packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock();
2605 packet.QueryReplies[i].ParcelID = d.parcelID;
2606 packet.QueryReplies[i].Name = Utils.StringToBytes(d.name);
2607 packet.QueryReplies[i].ForSale = d.forSale;
2608 packet.QueryReplies[i].Auction = d.auction;
2609 packet.QueryReplies[i].Dwell = d.dwell;
2610 packet.StatusData[i].Status = d.Status;
2611 i++;
2612 }
2613
2614 OutPacket(packet, ThrottleOutPacketType.Task);
2615 }
2616
2617 public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data)
2618 {
2619 DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply);
2620
2621 packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock();
2622 packet.AgentData.AgentID = AgentId;
2623
2624 packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock();
2625 packet.QueryData.QueryID = queryID;
2626
2627 packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[
2628 data.Length];
2629
2630 int i = 0;
2631 foreach (DirPeopleReplyData d in data)
2632 {
2633 packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock();
2634 packet.QueryReplies[i].AgentID = d.agentID;
2635 packet.QueryReplies[i].FirstName =
2636 Utils.StringToBytes(d.firstName);
2637 packet.QueryReplies[i].LastName =
2638 Utils.StringToBytes(d.lastName);
2639 packet.QueryReplies[i].Group =
2640 Utils.StringToBytes(d.group);
2641 packet.QueryReplies[i].Online = d.online;
2642 packet.QueryReplies[i].Reputation = d.reputation;
2643 i++;
2644 }
2645
2646 OutPacket(packet, ThrottleOutPacketType.Task);
2647 }
2648
2649 public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data)
2650 {
2651 DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply);
2652
2653 packet.AgentData = new DirEventsReplyPacket.AgentDataBlock();
2654 packet.AgentData.AgentID = AgentId;
2655
2656 packet.QueryData = new DirEventsReplyPacket.QueryDataBlock();
2657 packet.QueryData.QueryID = queryID;
2658
2659 packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[
2660 data.Length];
2661
2662 packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[
2663 data.Length];
2664
2665 int i = 0;
2666 foreach (DirEventsReplyData d in data)
2667 {
2668 packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock();
2669 packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock();
2670 packet.QueryReplies[i].OwnerID = d.ownerID;
2671 packet.QueryReplies[i].Name =
2672 Utils.StringToBytes(d.name);
2673 packet.QueryReplies[i].EventID = d.eventID;
2674 packet.QueryReplies[i].Date =
2675 Utils.StringToBytes(d.date);
2676 packet.QueryReplies[i].UnixTime = d.unixTime;
2677 packet.QueryReplies[i].EventFlags = d.eventFlags;
2678 packet.StatusData[i].Status = d.Status;
2679 i++;
2680 }
2681
2682 OutPacket(packet, ThrottleOutPacketType.Task);
2683 }
2684
2685 public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data)
2686 {
2687 DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply);
2688
2689 packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock();
2690 packet.AgentData.AgentID = AgentId;
2691
2692 packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock();
2693 packet.QueryData.QueryID = queryID;
2694
2695 packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[
2696 data.Length];
2697
2698 int i = 0;
2699 foreach (DirGroupsReplyData d in data)
2700 {
2701 packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock();
2702 packet.QueryReplies[i].GroupID = d.groupID;
2703 packet.QueryReplies[i].GroupName =
2704 Utils.StringToBytes(d.groupName);
2705 packet.QueryReplies[i].Members = d.members;
2706 packet.QueryReplies[i].SearchOrder = d.searchOrder;
2707 i++;
2708 }
2709
2710 OutPacket(packet, ThrottleOutPacketType.Task);
2711 }
2712
2713 public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data)
2714 {
2715 DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply);
2716
2717 packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock();
2718 packet.AgentData.AgentID = AgentId;
2719
2720 packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock();
2721 packet.QueryData.QueryID = queryID;
2722
2723 packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[
2724 data.Length];
2725 packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[
2726 data.Length];
2727
2728 int i = 0;
2729 foreach (DirClassifiedReplyData d in data)
2730 {
2731 packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock();
2732 packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock();
2733 packet.QueryReplies[i].ClassifiedID = d.classifiedID;
2734 packet.QueryReplies[i].Name =
2735 Utils.StringToBytes(d.name);
2736 packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags;
2737 packet.QueryReplies[i].CreationDate = d.creationDate;
2738 packet.QueryReplies[i].ExpirationDate = d.expirationDate;
2739 packet.QueryReplies[i].PriceForListing = d.price;
2740 packet.StatusData[i].Status = d.Status;
2741 i++;
2742 }
2743
2744 OutPacket(packet, ThrottleOutPacketType.Task);
2745 }
2746
2747 public void SendDirLandReply(UUID queryID, DirLandReplyData[] data)
2748 {
2749 DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply);
2750
2751 packet.AgentData = new DirLandReplyPacket.AgentDataBlock();
2752 packet.AgentData.AgentID = AgentId;
2753
2754 packet.QueryData = new DirLandReplyPacket.QueryDataBlock();
2755 packet.QueryData.QueryID = queryID;
2756
2757 packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[
2758 data.Length];
2759
2760 int i = 0;
2761 foreach (DirLandReplyData d in data)
2762 {
2763 packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock();
2764 packet.QueryReplies[i].ParcelID = d.parcelID;
2765 packet.QueryReplies[i].Name =
2766 Utils.StringToBytes(d.name);
2767 packet.QueryReplies[i].Auction = d.auction;
2768 packet.QueryReplies[i].ForSale = d.forSale;
2769 packet.QueryReplies[i].SalePrice = d.salePrice;
2770 packet.QueryReplies[i].ActualArea = d.actualArea;
2771 i++;
2772 }
2773
2774 OutPacket(packet, ThrottleOutPacketType.Task);
2775 }
2776
2777 public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data)
2778 {
2779 DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply);
2780
2781 packet.AgentData = new DirPopularReplyPacket.AgentDataBlock();
2782 packet.AgentData.AgentID = AgentId;
2783
2784 packet.QueryData = new DirPopularReplyPacket.QueryDataBlock();
2785 packet.QueryData.QueryID = queryID;
2786
2787 packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[
2788 data.Length];
2789
2790 int i = 0;
2791 foreach (DirPopularReplyData d in data)
2792 {
2793 packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock();
2794 packet.QueryReplies[i].ParcelID = d.parcelID;
2795 packet.QueryReplies[i].Name =
2796 Utils.StringToBytes(d.name);
2797 packet.QueryReplies[i].Dwell = d.dwell;
2798 i++;
2799 }
2800
2801 OutPacket(packet, ThrottleOutPacketType.Task);
2802 }
2803
2804 public void SendEventInfoReply(EventData data)
2805 {
2806 EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply);
2807
2808 packet.AgentData = new EventInfoReplyPacket.AgentDataBlock();
2809 packet.AgentData.AgentID = AgentId;
2810
2811 packet.EventData = new EventInfoReplyPacket.EventDataBlock();
2812 packet.EventData.EventID = data.eventID;
2813 packet.EventData.Creator = Utils.StringToBytes(data.creator);
2814 packet.EventData.Name = Utils.StringToBytes(data.name);
2815 packet.EventData.Category = Utils.StringToBytes(data.category);
2816 packet.EventData.Desc = Utils.StringToBytes(data.description);
2817 packet.EventData.Date = Utils.StringToBytes(data.date);
2818 packet.EventData.DateUTC = data.dateUTC;
2819 packet.EventData.Duration = data.duration;
2820 packet.EventData.Cover = data.cover;
2821 packet.EventData.Amount = data.amount;
2822 packet.EventData.SimName = Utils.StringToBytes(data.simName);
2823 packet.EventData.GlobalPos = new Vector3d(data.globalPos);
2824 packet.EventData.EventFlags = data.eventFlags;
2825
2826 OutPacket(packet, ThrottleOutPacketType.Task);
2827 }
2828
2829 public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags)
2830 {
2831 MapItemReplyPacket mirplk = new MapItemReplyPacket();
2832 mirplk.AgentData.AgentID = AgentId;
2833 mirplk.RequestData.ItemType = mapitemtype;
2834 mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length];
2835 for (int i = 0; i < replies.Length; i++)
2836 {
2837 MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock();
2838 mrdata.X = replies[i].x;
2839 mrdata.Y = replies[i].y;
2840 mrdata.ID = replies[i].id;
2841 mrdata.Extra = replies[i].Extra;
2842 mrdata.Extra2 = replies[i].Extra2;
2843 mrdata.Name = Utils.StringToBytes(replies[i].name);
2844 mirplk.Data[i] = mrdata;
2845 }
2846 //m_log.Debug(mirplk.ToString());
2847 OutPacket(mirplk, ThrottleOutPacketType.Task);
2848
2849 }
2850
2851 public void SendOfferCallingCard(UUID srcID, UUID transactionID)
2852 {
2853 // a bit special, as this uses AgentID to store the source instead
2854 // of the destination. The destination (the receiver) goes into destID
2855 OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard);
2856 p.AgentData.AgentID = srcID;
2857 p.AgentData.SessionID = UUID.Zero;
2858 p.AgentBlock.DestID = AgentId;
2859 p.AgentBlock.TransactionID = transactionID;
2860 OutPacket(p, ThrottleOutPacketType.Task);
2861 }
2862
2863 public void SendAcceptCallingCard(UUID transactionID)
2864 {
2865 AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard);
2866 p.AgentData.AgentID = AgentId;
2867 p.AgentData.SessionID = UUID.Zero;
2868 p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1];
2869 p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock();
2870 p.FolderData[0].FolderID = UUID.Zero;
2871 OutPacket(p, ThrottleOutPacketType.Task);
2872 }
2873
2874 public void SendDeclineCallingCard(UUID transactionID)
2875 {
2876 DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard);
2877 p.AgentData.AgentID = AgentId;
2878 p.AgentData.SessionID = UUID.Zero;
2879 p.TransactionBlock.TransactionID = transactionID;
2880 OutPacket(p, ThrottleOutPacketType.Task);
2881 }
2882
2883 public void SendTerminateFriend(UUID exFriendID)
2884 {
2885 TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship);
2886 p.AgentData.AgentID = AgentId;
2887 p.AgentData.SessionID = SessionId;
2888 p.ExBlock.OtherID = exFriendID;
2889 OutPacket(p, ThrottleOutPacketType.Task);
2890 }
2891
2892 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
2893 {
2894 AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply);
2895
2896 p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock();
2897 p.AgentData.AgentID = AgentId;
2898 p.AgentData.AvatarID = avatarID;
2899
2900 p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length];
2901 int i = 0;
2902 foreach (GroupMembershipData m in data)
2903 {
2904 p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock();
2905 p.GroupData[i].GroupPowers = m.GroupPowers;
2906 p.GroupData[i].AcceptNotices = m.AcceptNotices;
2907 p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle);
2908 p.GroupData[i].GroupID = m.GroupID;
2909 p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName);
2910 p.GroupData[i].GroupInsigniaID = m.GroupPicture;
2911 i++;
2912 }
2913
2914 p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock();
2915 p.NewGroupData.ListInProfile = true;
2916
2917 OutPacket(p, ThrottleOutPacketType.Task);
2918 }
2919
2920 public void SendJoinGroupReply(UUID groupID, bool success)
2921 {
2922 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
2923
2924 p.AgentData = new JoinGroupReplyPacket.AgentDataBlock();
2925 p.AgentData.AgentID = AgentId;
2926
2927 p.GroupData = new JoinGroupReplyPacket.GroupDataBlock();
2928 p.GroupData.GroupID = groupID;
2929 p.GroupData.Success = success;
2930
2931 OutPacket(p, ThrottleOutPacketType.Task);
2932 }
2933
2934 public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
2935 {
2936 EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply);
2937
2938 p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock();
2939 p.AgentData.AgentID = agentID;
2940
2941 p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock();
2942 p.GroupData.GroupID = groupID;
2943
2944 p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock();
2945 p.EjectData.Success = success;
2946
2947 OutPacket(p, ThrottleOutPacketType.Task);
2948 }
2949
2950 public void SendLeaveGroupReply(UUID groupID, bool success)
2951 {
2952 LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply);
2953
2954 p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock();
2955 p.AgentData.AgentID = AgentId;
2956
2957 p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock();
2958 p.GroupData.GroupID = groupID;
2959 p.GroupData.Success = success;
2960
2961 OutPacket(p, ThrottleOutPacketType.Task);
2962 }
2963
2964 public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name)
2965 {
2966 if (classifiedID.Length != name.Length)
2967 return;
2968
2969 AvatarClassifiedReplyPacket ac =
2970 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
2971 PacketType.AvatarClassifiedReply);
2972
2973 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
2974 ac.AgentData.AgentID = AgentId;
2975 ac.AgentData.TargetID = targetID;
2976
2977 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length];
2978 int i;
2979 for (i = 0; i < classifiedID.Length; i++)
2980 {
2981 ac.Data[i].ClassifiedID = classifiedID[i];
2982 ac.Data[i].Name = Utils.StringToBytes(name[i]);
2983 }
2984
2985 OutPacket(ac, ThrottleOutPacketType.Task);
2986 }
2987
2988 public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price)
2989 {
2990 ClassifiedInfoReplyPacket cr =
2991 (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket(
2992 PacketType.ClassifiedInfoReply);
2993
2994 cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock();
2995 cr.AgentData.AgentID = AgentId;
2996
2997 cr.Data = new ClassifiedInfoReplyPacket.DataBlock();
2998 cr.Data.ClassifiedID = classifiedID;
2999 cr.Data.CreatorID = creatorID;
3000 cr.Data.CreationDate = creationDate;
3001 cr.Data.ExpirationDate = expirationDate;
3002 cr.Data.Category = category;
3003 cr.Data.Name = Utils.StringToBytes(name);
3004 cr.Data.Desc = Utils.StringToBytes(description);
3005 cr.Data.ParcelID = parcelID;
3006 cr.Data.ParentEstate = parentEstate;
3007 cr.Data.SnapshotID = snapshotID;
3008 cr.Data.SimName = Utils.StringToBytes(simName);
3009 cr.Data.PosGlobal = new Vector3d(globalPos);
3010 cr.Data.ParcelName = Utils.StringToBytes(parcelName);
3011 cr.Data.ClassifiedFlags = classifiedFlags;
3012 cr.Data.PriceForListing = price;
3013
3014 OutPacket(cr, ThrottleOutPacketType.Task);
3015 }
3016
3017 public void SendAgentDropGroup(UUID groupID)
3018 {
3019 AgentDropGroupPacket dg =
3020 (AgentDropGroupPacket)PacketPool.Instance.GetPacket(
3021 PacketType.AgentDropGroup);
3022
3023 dg.AgentData = new AgentDropGroupPacket.AgentDataBlock();
3024 dg.AgentData.AgentID = AgentId;
3025 dg.AgentData.GroupID = groupID;
3026
3027 OutPacket(dg, ThrottleOutPacketType.Task);
3028 }
3029
3030 public void SendAvatarNotesReply(UUID targetID, string text)
3031 {
3032 AvatarNotesReplyPacket an =
3033 (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket(
3034 PacketType.AvatarNotesReply);
3035
3036 an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock();
3037 an.AgentData.AgentID = AgentId;
3038
3039 an.Data = new AvatarNotesReplyPacket.DataBlock();
3040 an.Data.TargetID = targetID;
3041 an.Data.Notes = Utils.StringToBytes(text);
3042
3043 OutPacket(an, ThrottleOutPacketType.Task);
3044 }
3045
3046 public void SendAvatarPicksReply(UUID targetID, Dictionary<UUID, string> picks)
3047 {
3048 AvatarPicksReplyPacket ap =
3049 (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket(
3050 PacketType.AvatarPicksReply);
3051
3052 ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock();
3053 ap.AgentData.AgentID = AgentId;
3054 ap.AgentData.TargetID = targetID;
3055
3056 ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count];
3057
3058 int i = 0;
3059 foreach (KeyValuePair<UUID, string> pick in picks)
3060 {
3061 ap.Data[i] = new AvatarPicksReplyPacket.DataBlock();
3062 ap.Data[i].PickID = pick.Key;
3063 ap.Data[i].PickName = Utils.StringToBytes(pick.Value);
3064 i++;
3065 }
3066
3067 OutPacket(ap, ThrottleOutPacketType.Task);
3068 }
3069
3070 public void SendAvatarClassifiedReply(UUID targetID, Dictionary<UUID, string> classifieds)
3071 {
3072 AvatarClassifiedReplyPacket ac =
3073 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
3074 PacketType.AvatarClassifiedReply);
3075
3076 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
3077 ac.AgentData.AgentID = AgentId;
3078 ac.AgentData.TargetID = targetID;
3079
3080 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count];
3081
3082 int i = 0;
3083 foreach (KeyValuePair<UUID, string> classified in classifieds)
3084 {
3085 ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock();
3086 ac.Data[i].ClassifiedID = classified.Key;
3087 ac.Data[i].Name = Utils.StringToBytes(classified.Value);
3088 i++;
3089 }
3090
3091 OutPacket(ac, ThrottleOutPacketType.Task);
3092 }
3093
3094 public void SendParcelDwellReply(int localID, UUID parcelID, float dwell)
3095 {
3096 ParcelDwellReplyPacket pd =
3097 (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket(
3098 PacketType.ParcelDwellReply);
3099
3100 pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock();
3101 pd.AgentData.AgentID = AgentId;
3102
3103 pd.Data = new ParcelDwellReplyPacket.DataBlock();
3104 pd.Data.LocalID = localID;
3105 pd.Data.ParcelID = parcelID;
3106 pd.Data.Dwell = dwell;
3107
3108 OutPacket(pd, ThrottleOutPacketType.Land);
3109 }
3110
3111 public void SendUserInfoReply(bool imViaEmail, bool visible, string email)
3112 {
3113 UserInfoReplyPacket ur =
3114 (UserInfoReplyPacket)PacketPool.Instance.GetPacket(
3115 PacketType.UserInfoReply);
3116
3117 string Visible = "hidden";
3118 if (visible)
3119 Visible = "default";
3120
3121 ur.AgentData = new UserInfoReplyPacket.AgentDataBlock();
3122 ur.AgentData.AgentID = AgentId;
3123
3124 ur.UserData = new UserInfoReplyPacket.UserDataBlock();
3125 ur.UserData.IMViaEMail = imViaEmail;
3126 ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible);
3127 ur.UserData.EMail = Utils.StringToBytes(email);
3128
3129 OutPacket(ur, ThrottleOutPacketType.Task);
3130 }
3131
3132 public void SendCreateGroupReply(UUID groupID, bool success, string message)
3133 {
3134 CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply);
3135
3136 createGroupReply.AgentData =
3137 new CreateGroupReplyPacket.AgentDataBlock();
3138 createGroupReply.ReplyData =
3139 new CreateGroupReplyPacket.ReplyDataBlock();
3140
3141 createGroupReply.AgentData.AgentID = AgentId;
3142 createGroupReply.ReplyData.GroupID = groupID;
3143
3144 createGroupReply.ReplyData.Success = success;
3145 createGroupReply.ReplyData.Message = Utils.StringToBytes(message);
3146 OutPacket(createGroupReply, ThrottleOutPacketType.Task);
3147 }
3148
3149 public void SendUseCachedMuteList()
3150 {
3151 UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList);
3152
3153 useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock();
3154 useCachedMuteList.AgentData.AgentID = AgentId;
3155
3156 OutPacket(useCachedMuteList, ThrottleOutPacketType.Task);
3157 }
3158
3159 public void SendMuteListUpdate(string filename)
3160 {
3161 MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate);
3162
3163 muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock();
3164 muteListUpdate.MuteData.AgentID = AgentId;
3165 muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename);
3166
3167 OutPacket(muteListUpdate, ThrottleOutPacketType.Task);
3168 }
3169
3170 public void SendPickInfoReply(UUID pickID, UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled)
3171 {
3172 PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply);
3173
3174 pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock();
3175 pickInfoReply.AgentData.AgentID = AgentId;
3176
3177 pickInfoReply.Data = new PickInfoReplyPacket.DataBlock();
3178 pickInfoReply.Data.PickID = pickID;
3179 pickInfoReply.Data.CreatorID = creatorID;
3180 pickInfoReply.Data.TopPick = topPick;
3181 pickInfoReply.Data.ParcelID = parcelID;
3182 pickInfoReply.Data.Name = Utils.StringToBytes(name);
3183 pickInfoReply.Data.Desc = Utils.StringToBytes(desc);
3184 pickInfoReply.Data.SnapshotID = snapshotID;
3185 pickInfoReply.Data.User = Utils.StringToBytes(user);
3186 pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName);
3187 pickInfoReply.Data.SimName = Utils.StringToBytes(simName);
3188 pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal);
3189 pickInfoReply.Data.SortOrder = sortOrder;
3190 pickInfoReply.Data.Enabled = enabled;
3191
3192 OutPacket(pickInfoReply, ThrottleOutPacketType.Task);
3193 }
3194
3195 #endregion Scene/Avatar to Client
2772 3196
2773 // Gesture 3197 // Gesture
2774 3198
@@ -3064,7 +3488,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3064 objectData.FullID = objectID; 3488 objectData.FullID = objectID;
3065 objectData.OwnerID = ownerID; 3489 objectData.OwnerID = ownerID;
3066 3490
3067 objectData.Text = LLUtil.StringToPacketBytes(text); 3491 objectData.Text = Util.StringToBytes256(text);
3068 objectData.TextColor[0] = color[0]; 3492 objectData.TextColor[0] = color[0];
3069 objectData.TextColor[1] = color[1]; 3493 objectData.TextColor[1] = color[1];
3070 objectData.TextColor[2] = color[2]; 3494 objectData.TextColor[2] = color[2];
@@ -3209,7 +3633,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3209 } 3633 }
3210 3634
3211 outPacket.Header.Zerocoded = true; 3635 outPacket.Header.Zerocoded = true;
3212 OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); 3636 OutPacket(outPacket, ThrottleOutPacketType.Task);
3213 3637
3214 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) 3638 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3215 stopTimer = true; 3639 stopTimer = true;
@@ -3311,7 +3735,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3311 3735
3312 outPacket.Header.Reliable = false; 3736 outPacket.Header.Reliable = false;
3313 outPacket.Header.Zerocoded = true; 3737 outPacket.Header.Zerocoded = true;
3314 OutPacket(outPacket, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority); 3738 OutPacket(outPacket, ThrottleOutPacketType.Task);
3315 3739
3316 if (m_primTerseUpdates.Count == 0) 3740 if (m_primTerseUpdates.Count == 0)
3317 stopTimer = true; 3741 stopTimer = true;
@@ -3464,8 +3888,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3464 objPropDB.SalePrice = SalePrice; 3888 objPropDB.SalePrice = SalePrice;
3465 objPropDB.Category = Category; 3889 objPropDB.Category = Category;
3466 objPropDB.LastOwnerID = LastOwnerID; 3890 objPropDB.LastOwnerID = LastOwnerID;
3467 objPropDB.Name = LLUtil.StringToPacketBytes(ObjectName); 3891 objPropDB.Name = Util.StringToBytes256(ObjectName);
3468 objPropDB.Description = LLUtil.StringToPacketBytes(Description); 3892 objPropDB.Description = Util.StringToBytes256(Description);
3469 objPropFamilyPack.ObjectData = objPropDB; 3893 objPropFamilyPack.ObjectData = objPropDB;
3470 objPropFamilyPack.Header.Zerocoded = true; 3894 objPropFamilyPack.Header.Zerocoded = true;
3471 OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); 3895 OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
@@ -3499,11 +3923,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3499 proper.ObjectData[0].OwnerID = UUID.Zero; 3923 proper.ObjectData[0].OwnerID = UUID.Zero;
3500 else 3924 else
3501 proper.ObjectData[0].OwnerID = OwnerUUID; 3925 proper.ObjectData[0].OwnerID = OwnerUUID;
3502 proper.ObjectData[0].TouchName = LLUtil.StringToPacketBytes(TouchTitle); 3926 proper.ObjectData[0].TouchName = Util.StringToBytes256(TouchTitle);
3503 proper.ObjectData[0].TextureID = TextureID; 3927 proper.ObjectData[0].TextureID = TextureID;
3504 proper.ObjectData[0].SitName = LLUtil.StringToPacketBytes(SitTitle); 3928 proper.ObjectData[0].SitName = Util.StringToBytes256(SitTitle);
3505 proper.ObjectData[0].Name = LLUtil.StringToPacketBytes(ItemName); 3929 proper.ObjectData[0].Name = Util.StringToBytes256(ItemName);
3506 proper.ObjectData[0].Description = LLUtil.StringToPacketBytes(ItemDescription); 3930 proper.ObjectData[0].Description = Util.StringToBytes256(ItemDescription);
3507 proper.ObjectData[0].OwnerMask = OwnerMask; 3931 proper.ObjectData[0].OwnerMask = OwnerMask;
3508 proper.ObjectData[0].NextOwnerMask = NextOwnerMask; 3932 proper.ObjectData[0].NextOwnerMask = NextOwnerMask;
3509 proper.ObjectData[0].GroupMask = GroupMask; 3933 proper.ObjectData[0].GroupMask = GroupMask;
@@ -3744,11 +4168,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3744 4168
3745 updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale; 4169 updatePacket.ParcelData.MediaAutoScale = landData.MediaAutoScale;
3746 updatePacket.ParcelData.MediaID = landData.MediaID; 4170 updatePacket.ParcelData.MediaID = landData.MediaID;
3747 updatePacket.ParcelData.MediaURL = LLUtil.StringToPacketBytes(landData.MediaURL); 4171 updatePacket.ParcelData.MediaURL = Util.StringToBytes256(landData.MediaURL);
3748 updatePacket.ParcelData.MusicURL = LLUtil.StringToPacketBytes(landData.MusicURL); 4172 updatePacket.ParcelData.MusicURL = Util.StringToBytes256(landData.MusicURL);
3749 updatePacket.ParcelData.Name = Utils.StringToBytes(landData.Name); 4173 updatePacket.ParcelData.Name = Util.StringToBytes256(landData.Name);
3750 updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime; 4174 updatePacket.ParcelData.OtherCleanTime = landData.OtherCleanTime;
3751 updatePacket.ParcelData.OtherCount = 0; //unemplemented 4175 updatePacket.ParcelData.OtherCount = 0; //TODO: Unimplemented
3752 updatePacket.ParcelData.OtherPrims = landData.OtherPrims; 4176 updatePacket.ParcelData.OtherPrims = landData.OtherPrims;
3753 updatePacket.ParcelData.OwnerID = landData.OwnerID; 4177 updatePacket.ParcelData.OwnerID = landData.OwnerID;
3754 updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims; 4178 updatePacket.ParcelData.OwnerPrims = landData.OwnerPrims;
@@ -3756,22 +4180,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3756 updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor; 4180 updatePacket.ParcelData.ParcelPrimBonus = simObjectBonusFactor;
3757 updatePacket.ParcelData.PassHours = landData.PassHours; 4181 updatePacket.ParcelData.PassHours = landData.PassHours;
3758 updatePacket.ParcelData.PassPrice = landData.PassPrice; 4182 updatePacket.ParcelData.PassPrice = landData.PassPrice;
3759 updatePacket.ParcelData.PublicCount = 0; //unemplemented 4183 updatePacket.ParcelData.PublicCount = 0; //TODO: Unimplemented
3760 4184
3761 updatePacket.ParcelData.RegionDenyAnonymous = ((regionFlags & (uint)RegionFlags.DenyAnonymous) > 4185 updatePacket.ParcelData.RegionDenyAnonymous = (regionFlags & (uint)RegionFlags.DenyAnonymous) > 0;
3762 0); 4186 updatePacket.ParcelData.RegionDenyIdentified = (regionFlags & (uint)RegionFlags.DenyIdentified) > 0;
3763 updatePacket.ParcelData.RegionDenyIdentified = ((regionFlags & (uint)RegionFlags.DenyIdentified) > 4187 updatePacket.ParcelData.RegionDenyTransacted = (regionFlags & (uint)RegionFlags.DenyTransacted) > 0;
3764 0); 4188 updatePacket.ParcelData.RegionPushOverride = (regionFlags & (uint)RegionFlags.RestrictPushObject) > 0;
3765 updatePacket.ParcelData.RegionDenyTransacted = ((regionFlags & (uint)RegionFlags.DenyTransacted) >
3766 0);
3767 updatePacket.ParcelData.RegionPushOverride = ((regionFlags & (uint)RegionFlags.RestrictPushObject) >
3768 0);
3769 4189
3770 updatePacket.ParcelData.RentPrice = 0; 4190 updatePacket.ParcelData.RentPrice = 0;
3771 updatePacket.ParcelData.RequestResult = request_result; 4191 updatePacket.ParcelData.RequestResult = request_result;
3772 updatePacket.ParcelData.SalePrice = landData.SalePrice; 4192 updatePacket.ParcelData.SalePrice = landData.SalePrice;
3773 updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims; 4193 updatePacket.ParcelData.SelectedPrims = landData.SelectedPrims;
3774 updatePacket.ParcelData.SelfCount = 0; //unemplemented 4194 updatePacket.ParcelData.SelfCount = 0; //TODO: Unimplemented
3775 updatePacket.ParcelData.SequenceID = sequence_id; 4195 updatePacket.ParcelData.SequenceID = sequence_id;
3776 if (landData.SimwideArea > 0) 4196 if (landData.SimwideArea > 0)
3777 { 4197 {
@@ -4264,6 +4684,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4264 OutPacket(packet, ThrottleOutPacketType.Task); 4684 OutPacket(packet, ThrottleOutPacketType.Task);
4265 } 4685 }
4266 4686
4687 public ulong GetGroupPowers(UUID groupID)
4688 {
4689 if (groupID == m_activeGroupID)
4690 return m_activeGroupPowers;
4691
4692 if (m_groupPowers.ContainsKey(groupID))
4693 return m_groupPowers[groupID];
4694
4695 return 0;
4696 }
4697
4698 /// <summary>
4699 /// This is a utility method used by single states to not duplicate kicks and blue card of death messages.
4700 /// </summary>
4701 public bool ChildAgentStatus()
4702 {
4703 return m_scene.PresenceChildStatus(AgentId);
4704 }
4705
4267 #endregion 4706 #endregion
4268 4707
4269 /// <summary> 4708 /// <summary>
@@ -4282,6 +4721,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4282 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 4721 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
4283 } 4722 }
4284 4723
4724 #region Packet Handlers
4725
4285 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack) 4726 private bool HandleMoneyTransferRequest(IClientAPI sender, Packet Pack)
4286 { 4727 {
4287 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack; 4728 MoneyTransferRequestPacket money = (MoneyTransferRequestPacket) Pack;
@@ -4289,7 +4730,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4289 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId && 4730 if (money.MoneyData.SourceID == sender.AgentId && money.AgentData.AgentID == sender.AgentId &&
4290 money.AgentData.SessionID == sender.SessionId) 4731 money.AgentData.SessionID == sender.SessionId)
4291 { 4732 {
4292 handlerMoneyTransferRequest = OnMoneyTransferRequest; 4733 MoneyTransferRequest handlerMoneyTransferRequest = OnMoneyTransferRequest;
4293 if (handlerMoneyTransferRequest != null) 4734 if (handlerMoneyTransferRequest != null)
4294 { 4735 {
4295 handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID, 4736 handlerMoneyTransferRequest(money.MoneyData.SourceID, money.MoneyData.DestID,
@@ -4308,7 +4749,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4308 ParcelBuyPacket parcel = (ParcelBuyPacket) Pack; 4749 ParcelBuyPacket parcel = (ParcelBuyPacket) Pack;
4309 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId) 4750 if (parcel.AgentData.AgentID == AgentId && parcel.AgentData.SessionID == SessionId)
4310 { 4751 {
4311 handlerParcelBuy = OnParcelBuy; 4752 ParcelBuy handlerParcelBuy = OnParcelBuy;
4312 if (handlerParcelBuy != null) 4753 if (handlerParcelBuy != null)
4313 { 4754 {
4314 handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final, 4755 handlerParcelBuy(parcel.AgentData.AgentID, parcel.Data.GroupID, parcel.Data.Final,
@@ -4329,7 +4770,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4329 4770
4330 for (int i = 0; i < upack.UUIDNameBlock.Length; i++) 4771 for (int i = 0; i < upack.UUIDNameBlock.Length; i++)
4331 { 4772 {
4332 handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest; 4773 UUIDNameRequest handlerUUIDGroupNameRequest = OnUUIDGroupNameRequest;
4333 if (handlerUUIDGroupNameRequest != null) 4774 if (handlerUUIDGroupNameRequest != null)
4334 { 4775 {
4335 handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this); 4776 handlerUUIDGroupNameRequest(upack.UUIDNameBlock[i].ID, this);
@@ -4345,7 +4786,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4345 if (m_genericPacketHandlers.Count == 0) return false; 4786 if (m_genericPacketHandlers.Count == 0) return false;
4346 if (gmpack.AgentData.SessionID != SessionId) return false; 4787 if (gmpack.AgentData.SessionID != SessionId) return false;
4347 4788
4348 handlerGenericMessage = null; 4789 GenericMessage handlerGenericMessage = null;
4349 4790
4350 string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim(); 4791 string method = Util.FieldToString(gmpack.MethodData.Method).ToLower().Trim();
4351 4792
@@ -4386,7 +4827,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4386 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack; 4827 ObjectGroupPacket ogpack = (ObjectGroupPacket)Pack;
4387 if (ogpack.AgentData.SessionID != SessionId) return false; 4828 if (ogpack.AgentData.SessionID != SessionId) return false;
4388 4829
4389 handlerObjectGroupRequest = OnObjectGroupRequest; 4830 RequestObjectPropertiesFamily handlerObjectGroupRequest = OnObjectGroupRequest;
4390 if (handlerObjectGroupRequest != null) 4831 if (handlerObjectGroupRequest != null)
4391 { 4832 {
4392 for (int i = 0; i < ogpack.ObjectData.Length; i++) 4833 for (int i = 0; i < ogpack.ObjectData.Length; i++)
@@ -4401,7 +4842,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4401 { 4842 {
4402 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack; 4843 ViewerEffectPacket viewer = (ViewerEffectPacket)Pack;
4403 if (viewer.AgentData.SessionID != SessionId) return false; 4844 if (viewer.AgentData.SessionID != SessionId) return false;
4404 handlerViewerEffect = OnViewerEffect; 4845 ViewerEffectEventHandler handlerViewerEffect = OnViewerEffect;
4405 if (handlerViewerEffect != null) 4846 if (handlerViewerEffect != null)
4406 { 4847 {
4407 int length = viewer.Effect.Length; 4848 int length = viewer.Effect.Length;
@@ -4425,6 +4866,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4425 return true; 4866 return true;
4426 } 4867 }
4427 4868
4869 #endregion Packet Handlers
4870
4428 public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question) 4871 public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question)
4429 { 4872 {
4430 ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion); 4873 ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
@@ -4490,7 +4933,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4490 { 4933 {
4491 m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName); 4934 m_log.InfoFormat("[CLIENT]: Got a logout request for {0} in {1}", Name, Scene.RegionInfo.RegionName);
4492 4935
4493 handlerLogout = OnLogout; 4936 Action<IClientAPI> handlerLogout = OnLogout;
4494 4937
4495 if (handlerLogout != null) 4938 if (handlerLogout != null)
4496 { 4939 {
@@ -4572,7 +5015,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4572 case 1: 5015 case 1:
4573 Vector3 pos1 = new Vector3(block.Data, 0); 5016 Vector3 pos1 = new Vector3(block.Data, 0);
4574 5017
4575 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 5018 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
4576 if (handlerUpdatePrimSinglePosition != null) 5019 if (handlerUpdatePrimSinglePosition != null)
4577 { 5020 {
4578 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 5021 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
@@ -4582,7 +5025,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4582 case 2: 5025 case 2:
4583 Quaternion rot1 = new Quaternion(block.Data, 0, true); 5026 Quaternion rot1 = new Quaternion(block.Data, 0, true);
4584 5027
4585 handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 5028 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
4586 if (handlerUpdatePrimSingleRotation != null) 5029 if (handlerUpdatePrimSingleRotation != null)
4587 { 5030 {
4588 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); 5031 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
@@ -4593,7 +5036,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4593 Vector3 rotPos = new Vector3(block.Data, 0); 5036 Vector3 rotPos = new Vector3(block.Data, 0);
4594 Quaternion rot2 = new Quaternion(block.Data, 12, true); 5037 Quaternion rot2 = new Quaternion(block.Data, 12, true);
4595 5038
4596 handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 5039 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition;
4597 if (handlerUpdatePrimSingleRotationPosition != null) 5040 if (handlerUpdatePrimSingleRotationPosition != null)
4598 { 5041 {
4599 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); 5042 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
@@ -4605,7 +5048,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4605 case 20: 5048 case 20:
4606 Vector3 scale4 = new Vector3(block.Data, 0); 5049 Vector3 scale4 = new Vector3(block.Data, 0);
4607 5050
4608 handlerUpdatePrimScale = OnUpdatePrimScale; 5051 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale;
4609 if (handlerUpdatePrimScale != null) 5052 if (handlerUpdatePrimScale != null)
4610 { 5053 {
4611// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); 5054// m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
@@ -4633,7 +5076,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4633 case 9: 5076 case 9:
4634 Vector3 pos2 = new Vector3(block.Data, 0); 5077 Vector3 pos2 = new Vector3(block.Data, 0);
4635 5078
4636 handlerUpdateVector = OnUpdatePrimGroupPosition; 5079 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
4637 5080
4638 if (handlerUpdateVector != null) 5081 if (handlerUpdateVector != null)
4639 { 5082 {
@@ -4644,7 +5087,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4644 case 10: 5087 case 10:
4645 Quaternion rot3 = new Quaternion(block.Data, 0, true); 5088 Quaternion rot3 = new Quaternion(block.Data, 0, true);
4646 5089
4647 handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 5090 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
4648 if (handlerUpdatePrimRotation != null) 5091 if (handlerUpdatePrimRotation != null)
4649 { 5092 {
4650 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); 5093 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
@@ -4667,7 +5110,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4667 case 28: 5110 case 28:
4668 Vector3 scale7 = new Vector3(block.Data, 0); 5111 Vector3 scale7 = new Vector3(block.Data, 0);
4669 5112
4670 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 5113 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
4671 if (handlerUpdatePrimGroupScale != null) 5114 if (handlerUpdatePrimGroupScale != null)
4672 { 5115 {
4673// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); 5116// m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
@@ -4787,45 +5230,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4787 } 5230 }
4788 5231
4789 /// <summary> 5232 /// <summary>
4790 /// returns a byte array of the client set throttles Gets multiplied by the multiplier 5233 /// Sets the throttles from values supplied by the client
4791 ///
4792 /// </summary> 5234 /// </summary>
4793 /// <param name="multiplier">non 1 multiplier for subdividing the throttles between individual regions</param> 5235 /// <param name="throttles"></param>
4794 /// <returns></returns> 5236 public void SetChildAgentThrottle(byte[] throttles)
4795 public byte[] GetThrottlesPacked(float multiplier)
4796 { 5237 {
4797 return m_PacketHandler.PacketQueue.GetThrottlesPacked(multiplier); 5238 m_udpClient.SetThrottles(throttles);
4798 } 5239 }
5240
4799 /// <summary> 5241 /// <summary>
4800 /// sets the throttles from values supplied by the client 5242 /// Get the current throttles for this client as a packed byte array
4801 /// </summary> 5243 /// </summary>
4802 /// <param name="throttles"></param> 5244 /// <param name="multiplier">Unused</param>
4803 public void SetChildAgentThrottle(byte[] throttles) 5245 /// <returns></returns>
5246 public byte[] GetThrottlesPacked(float multiplier)
4804 { 5247 {
4805 m_PacketHandler.PacketQueue.SetThrottleFromClient(throttles); 5248 return m_udpClient.GetThrottlesPacked();
4806 } 5249 }
4807 5250
4808 /// <summary> 5251 /// <summary>
4809 /// Method gets called when a new packet has arrived from the UDP 5252 /// Cruft?
4810 /// server. This happens after it's been decoded into a libsl object.
4811 /// </summary> 5253 /// </summary>
4812 /// <param name="NewPack">object containing the packet.</param>
4813 public virtual void InPacket(object NewPack) 5254 public virtual void InPacket(object NewPack)
4814 { 5255 {
4815 // Cast NewPack to Packet. 5256 throw new NotImplementedException();
4816 m_PacketHandler.InPacket((Packet) NewPack);
4817 } 5257 }
4818 5258
4819 /// <summary> 5259 /// <summary>
4820 /// This is the starting point for sending a simulator packet out to the client. 5260 /// This is the starting point for sending a simulator packet out to the client
4821 ///
4822 /// Please do not call this from outside the LindenUDP client stack.
4823 /// </summary> 5261 /// </summary>
4824 /// <param name="NewPack"></param> 5262 /// <param name="packet">Packet to send</param>
4825 /// <param name="throttlePacketType">Corresponds to the type of data that is going out. Enum</param> 5263 /// <param name="throttlePacketType">Throttling category for the packet</param>
4826 public void OutPacket(Packet NewPack, ThrottleOutPacketType throttlePacketType) 5264 private void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType)
4827 { 5265 {
4828 m_PacketHandler.OutPacket(NewPack, throttlePacketType); 5266 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true);
4829 } 5267 }
4830 5268
4831 public bool AddMoney(int debit) 5269 public bool AddMoney(int debit)
@@ -4869,7 +5307,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4869 return; 5307 return;
4870 } 5308 }
4871 5309
4872 handlerAutoPilotGo = OnAutoPilotGo; 5310 UpdateVector handlerAutoPilotGo = OnAutoPilotGo;
4873 if (handlerAutoPilotGo != null) 5311 if (handlerAutoPilotGo != null)
4874 { 5312 {
4875 handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this); 5313 handlerAutoPilotGo(0, new Vector3(locx, locy, locz), this);
@@ -4921,7 +5359,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4921 } 5359 }
4922 #endregion 5360 #endregion
4923 5361
4924 handlerRequestAvatarProperties = OnRequestAvatarProperties; 5362 RequestAvatarProperties handlerRequestAvatarProperties = OnRequestAvatarProperties;
4925 if (handlerRequestAvatarProperties != null) 5363 if (handlerRequestAvatarProperties != null)
4926 { 5364 {
4927 handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID); 5365 handlerRequestAvatarProperties(this, avatarProperties.AgentData.AvatarID);
@@ -4962,7 +5400,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4962 args.Sender = this; 5400 args.Sender = this;
4963 args.SenderUUID = this.AgentId; 5401 args.SenderUUID = this.AgentId;
4964 5402
4965 handlerChatFromClient = OnChatFromClient; 5403 ChatMessage handlerChatFromClient = OnChatFromClient;
4966 if (handlerChatFromClient != null) 5404 if (handlerChatFromClient != null)
4967 handlerChatFromClient(this, args); 5405 handlerChatFromClient(this, args);
4968 } 5406 }
@@ -4980,7 +5418,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4980 } 5418 }
4981 #endregion 5419 #endregion
4982 5420
4983 handlerUpdateAvatarProperties = OnUpdateAvatarProperties; 5421 UpdateAvatarProperties handlerUpdateAvatarProperties = OnUpdateAvatarProperties;
4984 if (handlerUpdateAvatarProperties != null) 5422 if (handlerUpdateAvatarProperties != null)
4985 { 5423 {
4986 AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData; 5424 AvatarPropertiesUpdatePacket.PropertiesDataBlock Properties = avatarProps.PropertiesData;
@@ -5020,7 +5458,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5020 args.Position = new Vector3(); 5458 args.Position = new Vector3();
5021 args.Scene = Scene; 5459 args.Scene = Scene;
5022 args.Sender = this; 5460 args.Sender = this;
5023 handlerChatFromClient2 = OnChatFromClient; 5461 ChatMessage handlerChatFromClient2 = OnChatFromClient;
5024 if (handlerChatFromClient2 != null) 5462 if (handlerChatFromClient2 != null)
5025 handlerChatFromClient2(this, args); 5463 handlerChatFromClient2(this, args);
5026 } 5464 }
@@ -5041,7 +5479,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5041 5479
5042 string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName); 5480 string IMfromName = Util.FieldToString(msgpack.MessageBlock.FromAgentName);
5043 string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message); 5481 string IMmessage = Utils.BytesToString(msgpack.MessageBlock.Message);
5044 handlerInstantMessage = OnInstantMessage; 5482 ImprovedInstantMessage handlerInstantMessage = OnInstantMessage;
5045 5483
5046 if (handlerInstantMessage != null) 5484 if (handlerInstantMessage != null)
5047 { 5485 {
@@ -5084,7 +5522,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5084 callingCardFolders.Add(afriendpack.FolderData[fi].FolderID); 5522 callingCardFolders.Add(afriendpack.FolderData[fi].FolderID);
5085 } 5523 }
5086 5524
5087 handlerApproveFriendRequest = OnApproveFriendRequest; 5525 FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest;
5088 if (handlerApproveFriendRequest != null) 5526 if (handlerApproveFriendRequest != null)
5089 { 5527 {
5090 handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); 5528 handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders);
@@ -5127,7 +5565,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5127 UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; 5565 UUID listOwnerAgentID = tfriendpack.AgentData.AgentID;
5128 UUID exFriendID = tfriendpack.ExBlock.OtherID; 5566 UUID exFriendID = tfriendpack.ExBlock.OtherID;
5129 5567
5130 handlerTerminateFriendship = OnTerminateFriendship; 5568 FriendshipTermination handlerTerminateFriendship = OnTerminateFriendship;
5131 if (handlerTerminateFriendship != null) 5569 if (handlerTerminateFriendship != null)
5132 { 5570 {
5133 handlerTerminateFriendship(this, listOwnerAgentID, exFriendID); 5571 handlerTerminateFriendship(this, listOwnerAgentID, exFriendID);
@@ -5146,7 +5584,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5146 } 5584 }
5147 #endregion 5585 #endregion
5148 5586
5149 handlerRezObject = OnRezObject; 5587 RezObject handlerRezObject = OnRezObject;
5150 if (handlerRezObject != null) 5588 if (handlerRezObject != null)
5151 { 5589 {
5152 handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd, 5590 handlerRezObject(this, rezPacket.InventoryData.ItemID, rezPacket.RezData.RayEnd,
@@ -5169,7 +5607,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5169 } 5607 }
5170 #endregion 5608 #endregion
5171 5609
5172 handlerDeRezObject = OnDeRezObject; 5610 DeRezObject handlerDeRezObject = OnDeRezObject;
5173 if (handlerDeRezObject != null) 5611 if (handlerDeRezObject != null)
5174 { 5612 {
5175 List<uint> deRezIDs = new List<uint>(); 5613 List<uint> deRezIDs = new List<uint>();
@@ -5208,7 +5646,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5208 { 5646 {
5209 for (int i = 0; i < modify.ParcelData.Length; i++) 5647 for (int i = 0; i < modify.ParcelData.Length; i++)
5210 { 5648 {
5211 handlerModifyTerrain = OnModifyTerrain; 5649 ModifyTerrain handlerModifyTerrain = OnModifyTerrain;
5212 if (handlerModifyTerrain != null) 5650 if (handlerModifyTerrain != null)
5213 { 5651 {
5214 handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds, 5652 handlerModifyTerrain(AgentId, modify.ModifyBlock.Height, modify.ModifyBlock.Seconds,
@@ -5225,7 +5663,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5225 5663
5226 case PacketType.RegionHandshakeReply: 5664 case PacketType.RegionHandshakeReply:
5227 5665
5228 handlerRegionHandShakeReply = OnRegionHandShakeReply; 5666 Action<IClientAPI> handlerRegionHandShakeReply = OnRegionHandShakeReply;
5229 if (handlerRegionHandShakeReply != null) 5667 if (handlerRegionHandShakeReply != null)
5230 { 5668 {
5231 handlerRegionHandShakeReply(this); 5669 handlerRegionHandShakeReply(this);
@@ -5234,14 +5672,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5234 break; 5672 break;
5235 5673
5236 case PacketType.AgentWearablesRequest: 5674 case PacketType.AgentWearablesRequest:
5237 handlerRequestWearables = OnRequestWearables; 5675 GenericCall2 handlerRequestWearables = OnRequestWearables;
5238 5676
5239 if (handlerRequestWearables != null) 5677 if (handlerRequestWearables != null)
5240 { 5678 {
5241 handlerRequestWearables(); 5679 handlerRequestWearables();
5242 } 5680 }
5243 5681
5244 handlerRequestAvatarsData = OnRequestAvatarsData; 5682 Action<IClientAPI> handlerRequestAvatarsData = OnRequestAvatarsData;
5245 5683
5246 if (handlerRequestAvatarsData != null) 5684 if (handlerRequestAvatarsData != null)
5247 { 5685 {
@@ -5262,7 +5700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5262 } 5700 }
5263 #endregion 5701 #endregion
5264 5702
5265 handlerSetAppearance = OnSetAppearance; 5703 SetAppearance handlerSetAppearance = OnSetAppearance;
5266 if (handlerSetAppearance != null) 5704 if (handlerSetAppearance != null)
5267 { 5705 {
5268 // Temporarily protect ourselves from the mantis #951 failure. 5706 // Temporarily protect ourselves from the mantis #951 failure.
@@ -5313,7 +5751,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5313 wearingArgs.NowWearing.Add(wearable); 5751 wearingArgs.NowWearing.Add(wearable);
5314 } 5752 }
5315 5753
5316 handlerAvatarNowWearing = OnAvatarNowWearing; 5754 AvatarNowWearing handlerAvatarNowWearing = OnAvatarNowWearing;
5317 if (handlerAvatarNowWearing != null) 5755 if (handlerAvatarNowWearing != null)
5318 { 5756 {
5319 handlerAvatarNowWearing(this, wearingArgs); 5757 handlerAvatarNowWearing(this, wearingArgs);
@@ -5322,7 +5760,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5322 break; 5760 break;
5323 5761
5324 case PacketType.RezSingleAttachmentFromInv: 5762 case PacketType.RezSingleAttachmentFromInv:
5325 handlerRezSingleAttachment = OnRezSingleAttachmentFromInv; 5763 RezSingleAttachmentFromInv handlerRezSingleAttachment = OnRezSingleAttachmentFromInv;
5326 if (handlerRezSingleAttachment != null) 5764 if (handlerRezSingleAttachment != null)
5327 { 5765 {
5328 RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack; 5766 RezSingleAttachmentFromInvPacket rez = (RezSingleAttachmentFromInvPacket)Pack;
@@ -5343,7 +5781,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5343 break; 5781 break;
5344 5782
5345 case PacketType.RezMultipleAttachmentsFromInv: 5783 case PacketType.RezMultipleAttachmentsFromInv:
5346 handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv; 5784 RezMultipleAttachmentsFromInv handlerRezMultipleAttachments = OnRezMultipleAttachmentsFromInv;
5347 if (handlerRezMultipleAttachments != null) 5785 if (handlerRezMultipleAttachments != null)
5348 { 5786 {
5349 RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack; 5787 RezMultipleAttachmentsFromInvPacket rez = (RezMultipleAttachmentsFromInvPacket)Pack;
@@ -5354,7 +5792,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5354 break; 5792 break;
5355 5793
5356 case PacketType.DetachAttachmentIntoInv: 5794 case PacketType.DetachAttachmentIntoInv:
5357 handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv; 5795 UUIDNameRequest handlerDetachAttachmentIntoInv = OnDetachAttachmentIntoInv;
5358 if (handlerDetachAttachmentIntoInv != null) 5796 if (handlerDetachAttachmentIntoInv != null)
5359 { 5797 {
5360 DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack; 5798 DetachAttachmentIntoInvPacket detachtoInv = (DetachAttachmentIntoInvPacket)Pack;
@@ -5384,7 +5822,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5384 } 5822 }
5385 #endregion 5823 #endregion
5386 5824
5387 handlerObjectAttach = OnObjectAttach; 5825 ObjectAttach handlerObjectAttach = OnObjectAttach;
5388 5826
5389 if (handlerObjectAttach != null) 5827 if (handlerObjectAttach != null)
5390 { 5828 {
@@ -5411,7 +5849,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5411 for (int j = 0; j < dett.ObjectData.Length; j++) 5849 for (int j = 0; j < dett.ObjectData.Length; j++)
5412 { 5850 {
5413 uint obj = dett.ObjectData[j].ObjectLocalID; 5851 uint obj = dett.ObjectData[j].ObjectLocalID;
5414 handlerObjectDetach = OnObjectDetach; 5852 ObjectDeselect handlerObjectDetach = OnObjectDetach;
5415 if (handlerObjectDetach != null) 5853 if (handlerObjectDetach != null)
5416 { 5854 {
5417 handlerObjectDetach(obj, this); 5855 handlerObjectDetach(obj, this);
@@ -5435,7 +5873,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5435 for (int j = 0; j < dropp.ObjectData.Length; j++) 5873 for (int j = 0; j < dropp.ObjectData.Length; j++)
5436 { 5874 {
5437 uint obj = dropp.ObjectData[j].ObjectLocalID; 5875 uint obj = dropp.ObjectData[j].ObjectLocalID;
5438 handlerObjectDrop = OnObjectDrop; 5876 ObjectDrop handlerObjectDrop = OnObjectDrop;
5439 if (handlerObjectDrop != null) 5877 if (handlerObjectDrop != null)
5440 { 5878 {
5441 handlerObjectDrop(obj, this); 5879 handlerObjectDrop(obj, this);
@@ -5455,14 +5893,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5455 } 5893 }
5456 #endregion 5894 #endregion
5457 5895
5458 handlerSetAlwaysRun = OnSetAlwaysRun; 5896 SetAlwaysRun handlerSetAlwaysRun = OnSetAlwaysRun;
5459 if (handlerSetAlwaysRun != null) 5897 if (handlerSetAlwaysRun != null)
5460 handlerSetAlwaysRun(this, run.AgentData.AlwaysRun); 5898 handlerSetAlwaysRun(this, run.AgentData.AlwaysRun);
5461 5899
5462 break; 5900 break;
5463 5901
5464 case PacketType.CompleteAgentMovement: 5902 case PacketType.CompleteAgentMovement:
5465 handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 5903 GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
5466 if (handlerCompleteMovementToRegion != null) 5904 if (handlerCompleteMovementToRegion != null)
5467 { 5905 {
5468 handlerCompleteMovementToRegion(); 5906 handlerCompleteMovementToRegion();
@@ -5531,7 +5969,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5531 arg.HeadRotation = x.HeadRotation; 5969 arg.HeadRotation = x.HeadRotation;
5532 arg.SessionID = x.SessionID; 5970 arg.SessionID = x.SessionID;
5533 arg.State = x.State; 5971 arg.State = x.State;
5534 handlerAgentUpdate = OnAgentUpdate; 5972 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5535 lastarg = arg; // save this set of arguments for nexttime 5973 lastarg = arg; // save this set of arguments for nexttime
5536 if (handlerAgentUpdate != null) 5974 if (handlerAgentUpdate != null)
5537 OnAgentUpdate(this, arg); 5975 OnAgentUpdate(this, arg);
@@ -5554,8 +5992,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5554 } 5992 }
5555 #endregion 5993 #endregion
5556 5994
5557 handlerStartAnim = null; 5995 StartAnim handlerStartAnim = null;
5558 handlerStopAnim = null; 5996 StopAnim handlerStopAnim = null;
5559 5997
5560 for (int i = 0; i < AgentAni.AnimationList.Length; i++) 5998 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
5561 { 5999 {
@@ -5592,7 +6030,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5592 } 6030 }
5593 #endregion 6031 #endregion
5594 6032
5595 handlerAgentRequestSit = OnAgentRequestSit; 6033 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
5596 if (handlerAgentRequestSit != null) 6034 if (handlerAgentRequestSit != null)
5597 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID, 6035 handlerAgentRequestSit(this, agentRequestSit.AgentData.AgentID,
5598 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset); 6036 agentRequestSit.TargetObject.TargetID, agentRequestSit.TargetObject.Offset);
@@ -5613,7 +6051,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5613 } 6051 }
5614 #endregion 6052 #endregion
5615 6053
5616 handlerAgentSit = OnAgentSit; 6054 AgentSit handlerAgentSit = OnAgentSit;
5617 if (handlerAgentSit != null) 6055 if (handlerAgentSit != null)
5618 { 6056 {
5619 OnAgentSit(this, agentSit.AgentData.AgentID); 6057 OnAgentSit(this, agentSit.AgentData.AgentID);
@@ -5631,7 +6069,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5631 } 6069 }
5632 #endregion 6070 #endregion
5633 6071
5634 handlerSoundTrigger = OnSoundTrigger; 6072 SoundTrigger handlerSoundTrigger = OnSoundTrigger;
5635 if (handlerSoundTrigger != null) 6073 if (handlerSoundTrigger != null)
5636 { 6074 {
5637 handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID, 6075 handlerSoundTrigger(soundTriggerPacket.SoundData.SoundID, soundTriggerPacket.SoundData.OwnerID,
@@ -5658,7 +6096,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5658 AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data; 6096 AvatarPickerRequestPacket.DataBlock querydata = avRequestQuery.Data;
5659 //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name)); 6097 //m_log.Debug("Agent Sends:" + Utils.BytesToString(querydata.Name));
5660 6098
5661 handlerAvatarPickerRequest = OnAvatarPickerRequest; 6099 AvatarPickerRequest handlerAvatarPickerRequest = OnAvatarPickerRequest;
5662 if (handlerAvatarPickerRequest != null) 6100 if (handlerAvatarPickerRequest != null)
5663 { 6101 {
5664 handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID, 6102 handlerAvatarPickerRequest(this, Requestdata.AgentID, Requestdata.QueryID,
@@ -5678,7 +6116,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5678 } 6116 }
5679 #endregion 6117 #endregion
5680 6118
5681 handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest; 6119 FetchInventory handlerAgentDataUpdateRequest = OnAgentDataUpdateRequest;
5682 6120
5683 if (handlerAgentDataUpdateRequest != null) 6121 if (handlerAgentDataUpdateRequest != null)
5684 { 6122 {
@@ -5688,7 +6126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5688 break; 6126 break;
5689 6127
5690 case PacketType.UserInfoRequest: 6128 case PacketType.UserInfoRequest:
5691 handlerUserInfoRequest = OnUserInfoRequest; 6129 UserInfoRequest handlerUserInfoRequest = OnUserInfoRequest;
5692 if (handlerUserInfoRequest != null) 6130 if (handlerUserInfoRequest != null)
5693 { 6131 {
5694 handlerUserInfoRequest(this); 6132 handlerUserInfoRequest(this);
@@ -5711,7 +6149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5711 } 6149 }
5712 #endregion 6150 #endregion
5713 6151
5714 handlerUpdateUserInfo = OnUpdateUserInfo; 6152 UpdateUserInfo handlerUpdateUserInfo = OnUpdateUserInfo;
5715 if (handlerUpdateUserInfo != null) 6153 if (handlerUpdateUserInfo != null)
5716 { 6154 {
5717 bool visible = true; 6155 bool visible = true;
@@ -5740,7 +6178,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5740 6178
5741 if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId) 6179 if (avSetStartLocationRequestPacket.AgentData.AgentID == AgentId && avSetStartLocationRequestPacket.AgentData.SessionID == SessionId)
5742 { 6180 {
5743 handlerSetStartLocationRequest = OnSetStartLocationRequest; 6181 TeleportLocationRequest handlerSetStartLocationRequest = OnSetStartLocationRequest;
5744 if (handlerSetStartLocationRequest != null) 6182 if (handlerSetStartLocationRequest != null)
5745 { 6183 {
5746 handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos, 6184 handlerSetStartLocationRequest(this, 0, avSetStartLocationRequestPacket.StartLocationData.LocationPos,
@@ -5762,23 +6200,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5762 } 6200 }
5763 #endregion 6201 #endregion
5764 6202
5765 m_PacketHandler.PacketQueue.SetThrottleFromClient(atpack.Throttle.Throttles); 6203 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
5766 break; 6204 break;
5767 6205
5768 case PacketType.AgentPause: 6206 case PacketType.AgentPause:
5769 m_probesWithNoIngressPackets = 0; 6207 m_udpClient.IsPaused = true;
5770 m_clientBlocked = true;
5771 break; 6208 break;
5772 6209
5773 case PacketType.AgentResume: 6210 case PacketType.AgentResume:
5774 m_probesWithNoIngressPackets = 0; 6211 m_udpClient.IsPaused = false;
5775 m_clientBlocked = false; 6212 SendStartPingCheck(m_udpClient.CurrentPingSequence++);
5776 SendStartPingCheck(0);
5777 6213
5778 break; 6214 break;
5779 6215
5780 case PacketType.ForceScriptControlRelease: 6216 case PacketType.ForceScriptControlRelease:
5781 handlerForceReleaseControls = OnForceReleaseControls; 6217 ForceReleaseControls handlerForceReleaseControls = OnForceReleaseControls;
5782 if (handlerForceReleaseControls != null) 6218 if (handlerForceReleaseControls != null)
5783 { 6219 {
5784 handlerForceReleaseControls(this, AgentId); 6220 handlerForceReleaseControls(this, AgentId);
@@ -5812,7 +6248,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5812 childrenprims.Add(link.ObjectData[i].ObjectLocalID); 6248 childrenprims.Add(link.ObjectData[i].ObjectLocalID);
5813 } 6249 }
5814 } 6250 }
5815 handlerLinkObjects = OnLinkObjects; 6251 LinkObjects handlerLinkObjects = OnLinkObjects;
5816 if (handlerLinkObjects != null) 6252 if (handlerLinkObjects != null)
5817 { 6253 {
5818 handlerLinkObjects(this, parentprimid, childrenprims); 6254 handlerLinkObjects(this, parentprimid, childrenprims);
@@ -5840,7 +6276,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5840 { 6276 {
5841 prims.Add(delink.ObjectData[i].ObjectLocalID); 6277 prims.Add(delink.ObjectData[i].ObjectLocalID);
5842 } 6278 }
5843 handlerDelinkObjects = OnDelinkObjects; 6279 DelinkObjects handlerDelinkObjects = OnDelinkObjects;
5844 if (handlerDelinkObjects != null) 6280 if (handlerDelinkObjects != null)
5845 { 6281 {
5846 handlerDelinkObjects(prims); 6282 handlerDelinkObjects(prims);
@@ -5872,7 +6308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5872 //Check to see if adding the prim is allowed; useful for any module wanting to restrict the 6308 //Check to see if adding the prim is allowed; useful for any module wanting to restrict the
5873 //object from rezing initially 6309 //object from rezing initially
5874 6310
5875 handlerAddPrim = OnAddPrim; 6311 AddNewPrim handlerAddPrim = OnAddPrim;
5876 if (handlerAddPrim != null) 6312 if (handlerAddPrim != null)
5877 handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection); 6313 handlerAddPrim(AgentId, ActiveGroupId, addPacket.ObjectData.RayEnd, addPacket.ObjectData.Rotation, shape, addPacket.ObjectData.BypassRaycast, addPacket.ObjectData.RayStart, addPacket.ObjectData.RayTargetID, addPacket.ObjectData.RayEndIsIntersection);
5878 } 6314 }
@@ -5890,7 +6326,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5890 } 6326 }
5891 #endregion 6327 #endregion
5892 6328
5893 handlerUpdatePrimShape = null; 6329 UpdateShape handlerUpdatePrimShape = null;
5894 for (int i = 0; i < shapePacket.ObjectData.Length; i++) 6330 for (int i = 0; i < shapePacket.ObjectData.Length; i++)
5895 { 6331 {
5896 handlerUpdatePrimShape = OnUpdatePrimShape; 6332 handlerUpdatePrimShape = OnUpdatePrimShape;
@@ -5935,7 +6371,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5935 } 6371 }
5936 #endregion 6372 #endregion
5937 6373
5938 handlerUpdateExtraParams = OnUpdateExtraParams; 6374 ObjectExtraParams handlerUpdateExtraParams = OnUpdateExtraParams;
5939 if (handlerUpdateExtraParams != null) 6375 if (handlerUpdateExtraParams != null)
5940 { 6376 {
5941 for (int i = 0 ; i < extraPar.ObjectData.Length ; i++) 6377 for (int i = 0 ; i < extraPar.ObjectData.Length ; i++)
@@ -5960,7 +6396,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5960 6396
5961 ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData; 6397 ObjectDuplicatePacket.AgentDataBlock AgentandGroupData = dupe.AgentData;
5962 6398
5963 handlerObjectDuplicate = null; 6399 ObjectDuplicate handlerObjectDuplicate = null;
5964 6400
5965 for (int i = 0; i < dupe.ObjectData.Length; i++) 6401 for (int i = 0; i < dupe.ObjectData.Length; i++)
5966 { 6402 {
@@ -5987,7 +6423,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5987 } 6423 }
5988 #endregion 6424 #endregion
5989 6425
5990 handlerObjectRequest = null; 6426 ObjectRequest handlerObjectRequest = null;
5991 6427
5992 for (int i = 0; i < incomingRequest.ObjectData.Length; i++) 6428 for (int i = 0; i < incomingRequest.ObjectData.Length; i++)
5993 { 6429 {
@@ -6010,7 +6446,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6010 } 6446 }
6011 #endregion 6447 #endregion
6012 6448
6013 handlerObjectSelect = null; 6449 ObjectSelect handlerObjectSelect = null;
6014 6450
6015 for (int i = 0; i < incomingselect.ObjectData.Length; i++) 6451 for (int i = 0; i < incomingselect.ObjectData.Length; i++)
6016 { 6452 {
@@ -6033,7 +6469,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6033 } 6469 }
6034 #endregion 6470 #endregion
6035 6471
6036 handlerObjectDeselect = null; 6472 ObjectDeselect handlerObjectDeselect = null;
6037 6473
6038 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++) 6474 for (int i = 0; i < incomingdeselect.ObjectData.Length; i++)
6039 { 6475 {
@@ -6060,7 +6496,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6060 6496
6061 for (int i = 0; i < position.ObjectData.Length; i++) 6497 for (int i = 0; i < position.ObjectData.Length; i++)
6062 { 6498 {
6063 handlerUpdateVector = OnUpdatePrimGroupPosition; 6499 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
6064 if (handlerUpdateVector != null) 6500 if (handlerUpdateVector != null)
6065 handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this); 6501 handlerUpdateVector(position.ObjectData[i].ObjectLocalID, position.ObjectData[i].Position, this);
6066 } 6502 }
@@ -6081,7 +6517,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6081 6517
6082 for (int i = 0; i < scale.ObjectData.Length; i++) 6518 for (int i = 0; i < scale.ObjectData.Length; i++)
6083 { 6519 {
6084 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 6520 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
6085 if (handlerUpdatePrimGroupScale != null) 6521 if (handlerUpdatePrimGroupScale != null)
6086 handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this); 6522 handlerUpdatePrimGroupScale(scale.ObjectData[i].ObjectLocalID, scale.ObjectData[i].Scale, this);
6087 } 6523 }
@@ -6102,7 +6538,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6102 6538
6103 for (int i = 0; i < rotation.ObjectData.Length; i++) 6539 for (int i = 0; i < rotation.ObjectData.Length; i++)
6104 { 6540 {
6105 handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 6541 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
6106 if (handlerUpdatePrimRotation != null) 6542 if (handlerUpdatePrimRotation != null)
6107 handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this); 6543 handlerUpdatePrimRotation(rotation.ObjectData[i].ObjectLocalID, rotation.ObjectData[i].Rotation, this);
6108 } 6544 }
@@ -6120,7 +6556,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6120 } 6556 }
6121 #endregion 6557 #endregion
6122 6558
6123 handlerUpdatePrimFlags = OnUpdatePrimFlags; 6559 UpdatePrimFlags handlerUpdatePrimFlags = OnUpdatePrimFlags;
6124 6560
6125 if (handlerUpdatePrimFlags != null) 6561 if (handlerUpdatePrimFlags != null)
6126 { 6562 {
@@ -6137,7 +6573,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6137 case PacketType.ObjectImage: 6573 case PacketType.ObjectImage:
6138 ObjectImagePacket imagePack = (ObjectImagePacket)Pack; 6574 ObjectImagePacket imagePack = (ObjectImagePacket)Pack;
6139 6575
6140 handlerUpdatePrimTexture = null; 6576 UpdatePrimTexture handlerUpdatePrimTexture = null;
6141 for (int i = 0; i < imagePack.ObjectData.Length; i++) 6577 for (int i = 0; i < imagePack.ObjectData.Length; i++)
6142 { 6578 {
6143 handlerUpdatePrimTexture = OnUpdatePrimTexture; 6579 handlerUpdatePrimTexture = OnUpdatePrimTexture;
@@ -6160,7 +6596,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6160 } 6596 }
6161 #endregion 6597 #endregion
6162 6598
6163 handlerGrabObject = OnGrabObject; 6599 GrabObject handlerGrabObject = OnGrabObject;
6164 6600
6165 if (handlerGrabObject != null) 6601 if (handlerGrabObject != null)
6166 { 6602 {
@@ -6194,7 +6630,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6194 } 6630 }
6195 #endregion 6631 #endregion
6196 6632
6197 handlerGrabUpdate = OnGrabUpdate; 6633 MoveObject handlerGrabUpdate = OnGrabUpdate;
6198 6634
6199 if (handlerGrabUpdate != null) 6635 if (handlerGrabUpdate != null)
6200 { 6636 {
@@ -6229,7 +6665,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6229 } 6665 }
6230 #endregion 6666 #endregion
6231 6667
6232 handlerDeGrabObject = OnDeGrabObject; 6668 DeGrabObject handlerDeGrabObject = OnDeGrabObject;
6233 if (handlerDeGrabObject != null) 6669 if (handlerDeGrabObject != null)
6234 { 6670 {
6235 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>(); 6671 List<SurfaceTouchEventArgs> touchArgs = new List<SurfaceTouchEventArgs>();
@@ -6263,7 +6699,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6263 } 6699 }
6264 #endregion 6700 #endregion
6265 6701
6266 handlerSpinStart = OnSpinStart; 6702 SpinStart handlerSpinStart = OnSpinStart;
6267 if (handlerSpinStart != null) 6703 if (handlerSpinStart != null)
6268 { 6704 {
6269 handlerSpinStart(spinStart.ObjectData.ObjectID, this); 6705 handlerSpinStart(spinStart.ObjectData.ObjectID, this);
@@ -6287,7 +6723,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6287 spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle); 6723 spinUpdate.ObjectData.Rotation.GetAxisAngle(out axis, out angle);
6288 //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle); 6724 //m_log.Warn("[CLIENT]: ObjectSpinUpdate packet rot axis:" + axis + " angle:" + angle);
6289 6725
6290 handlerSpinUpdate = OnSpinUpdate; 6726 SpinObject handlerSpinUpdate = OnSpinUpdate;
6291 if (handlerSpinUpdate != null) 6727 if (handlerSpinUpdate != null)
6292 { 6728 {
6293 handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this); 6729 handlerSpinUpdate(spinUpdate.ObjectData.ObjectID, spinUpdate.ObjectData.Rotation, this);
@@ -6306,7 +6742,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6306 } 6742 }
6307 #endregion 6743 #endregion
6308 6744
6309 handlerSpinStop = OnSpinStop; 6745 SpinStop handlerSpinStop = OnSpinStop;
6310 if (handlerSpinStop != null) 6746 if (handlerSpinStop != null)
6311 { 6747 {
6312 handlerSpinStop(spinStop.ObjectData.ObjectID, this); 6748 handlerSpinStop(spinStop.ObjectData.ObjectID, this);
@@ -6325,7 +6761,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6325 } 6761 }
6326 #endregion 6762 #endregion
6327 6763
6328 handlerObjectDescription = null; 6764 GenericCall7 handlerObjectDescription = null;
6329 6765
6330 for (int i = 0; i < objDes.ObjectData.Length; i++) 6766 for (int i = 0; i < objDes.ObjectData.Length; i++)
6331 { 6767 {
@@ -6349,7 +6785,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6349 } 6785 }
6350 #endregion 6786 #endregion
6351 6787
6352 handlerObjectName = null; 6788 GenericCall7 handlerObjectName = null;
6353 for (int i = 0; i < objName.ObjectData.Length; i++) 6789 for (int i = 0; i < objName.ObjectData.Length; i++)
6354 { 6790 {
6355 handlerObjectName = OnObjectName; 6791 handlerObjectName = OnObjectName;
@@ -6377,7 +6813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6377 UUID AgentID = newobjPerms.AgentData.AgentID; 6813 UUID AgentID = newobjPerms.AgentData.AgentID;
6378 UUID SessionID = newobjPerms.AgentData.SessionID; 6814 UUID SessionID = newobjPerms.AgentData.SessionID;
6379 6815
6380 handlerObjectPermissions = null; 6816 ObjectPermissions handlerObjectPermissions = null;
6381 6817
6382 for (int i = 0; i < newobjPerms.ObjectData.Length; i++) 6818 for (int i = 0; i < newobjPerms.ObjectData.Length; i++)
6383 { 6819 {
@@ -6426,7 +6862,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6426 for (int i = 0; i < undoitem.ObjectData.Length; i++) 6862 for (int i = 0; i < undoitem.ObjectData.Length; i++)
6427 { 6863 {
6428 UUID objiD = undoitem.ObjectData[i].ObjectID; 6864 UUID objiD = undoitem.ObjectData[i].ObjectID;
6429 handlerOnUndo = OnUndo; 6865 AgentSit handlerOnUndo = OnUndo;
6430 if (handlerOnUndo != null) 6866 if (handlerOnUndo != null)
6431 { 6867 {
6432 handlerOnUndo(this, objiD); 6868 handlerOnUndo(this, objiD);
@@ -6447,8 +6883,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6447 } 6883 }
6448 #endregion 6884 #endregion
6449 6885
6450 handlerObjectDuplicateOnRay = null; 6886 ObjectDuplicateOnRay handlerObjectDuplicateOnRay = null;
6451
6452 6887
6453 for (int i = 0; i < dupeOnRay.ObjectData.Length; i++) 6888 for (int i = 0; i < dupeOnRay.ObjectData.Length; i++)
6454 { 6889 {
@@ -6478,7 +6913,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6478 6913
6479 RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData; 6914 RequestObjectPropertiesFamilyPacket.ObjectDataBlock packObjBlock = packToolTip.ObjectData;
6480 6915
6481 handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily; 6916 RequestObjectPropertiesFamily handlerRequestObjectPropertiesFamily = OnRequestObjectPropertiesFamily;
6482 6917
6483 if (handlerRequestObjectPropertiesFamily != null) 6918 if (handlerRequestObjectPropertiesFamily != null)
6484 { 6919 {
@@ -6490,7 +6925,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6490 case PacketType.ObjectIncludeInSearch: 6925 case PacketType.ObjectIncludeInSearch:
6491 //This lets us set objects to appear in search (stuff like DataSnapshot, etc) 6926 //This lets us set objects to appear in search (stuff like DataSnapshot, etc)
6492 ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack; 6927 ObjectIncludeInSearchPacket packInSearch = (ObjectIncludeInSearchPacket)Pack;
6493 handlerObjectIncludeInSearch = null; 6928 ObjectIncludeInSearch handlerObjectIncludeInSearch = null;
6494 6929
6495 #region Packet Session and User Check 6930 #region Packet Session and User Check
6496 if (m_checkPackets) 6931 if (m_checkPackets)
@@ -6527,7 +6962,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6527 } 6962 }
6528 #endregion 6963 #endregion
6529 6964
6530 handlerScriptAnswer = OnScriptAnswer; 6965 ScriptAnswer handlerScriptAnswer = OnScriptAnswer;
6531 if (handlerScriptAnswer != null) 6966 if (handlerScriptAnswer != null)
6532 { 6967 {
6533 handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions); 6968 handlerScriptAnswer(this, scriptAnswer.Data.TaskID, scriptAnswer.Data.ItemID, scriptAnswer.Data.Questions);
@@ -6546,7 +6981,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6546 } 6981 }
6547 #endregion 6982 #endregion
6548 6983
6549 handlerObjectClickAction = OnObjectClickAction; 6984 GenericCall7 handlerObjectClickAction = OnObjectClickAction;
6550 if (handlerObjectClickAction != null) 6985 if (handlerObjectClickAction != null)
6551 { 6986 {
6552 foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData) 6987 foreach (ObjectClickActionPacket.ObjectDataBlock odata in ocpacket.ObjectData)
@@ -6570,7 +7005,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6570 } 7005 }
6571 #endregion 7006 #endregion
6572 7007
6573 handlerObjectMaterial = OnObjectMaterial; 7008 GenericCall7 handlerObjectMaterial = OnObjectMaterial;
6574 if (handlerObjectMaterial != null) 7009 if (handlerObjectMaterial != null)
6575 { 7010 {
6576 foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData) 7011 foreach (ObjectMaterialPacket.ObjectDataBlock odata in ompacket.ObjectData)
@@ -6724,7 +7159,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6724 // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString()); 7159 // m_log.Debug("upload request was for assetid: " + request.AssetBlock.TransactionID.Combine(this.SecureSessionId).ToString());
6725 UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId); 7160 UUID temp = UUID.Combine(request.AssetBlock.TransactionID, SecureSessionId);
6726 7161
6727 handlerAssetUploadRequest = OnAssetUploadRequest; 7162 UDPAssetUploadRequest handlerAssetUploadRequest = OnAssetUploadRequest;
6728 7163
6729 if (handlerAssetUploadRequest != null) 7164 if (handlerAssetUploadRequest != null)
6730 { 7165 {
@@ -6737,7 +7172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6737 case PacketType.RequestXfer: 7172 case PacketType.RequestXfer:
6738 RequestXferPacket xferReq = (RequestXferPacket)Pack; 7173 RequestXferPacket xferReq = (RequestXferPacket)Pack;
6739 7174
6740 handlerRequestXfer = OnRequestXfer; 7175 RequestXfer handlerRequestXfer = OnRequestXfer;
6741 7176
6742 if (handlerRequestXfer != null) 7177 if (handlerRequestXfer != null)
6743 { 7178 {
@@ -6747,7 +7182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6747 case PacketType.SendXferPacket: 7182 case PacketType.SendXferPacket:
6748 SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack; 7183 SendXferPacketPacket xferRec = (SendXferPacketPacket)Pack;
6749 7184
6750 handlerXferReceive = OnXferReceive; 7185 XferReceive handlerXferReceive = OnXferReceive;
6751 if (handlerXferReceive != null) 7186 if (handlerXferReceive != null)
6752 { 7187 {
6753 handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data); 7188 handlerXferReceive(this, xferRec.XferID.ID, xferRec.XferID.Packet, xferRec.DataPacket.Data);
@@ -6756,7 +7191,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6756 case PacketType.ConfirmXferPacket: 7191 case PacketType.ConfirmXferPacket:
6757 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack; 7192 ConfirmXferPacketPacket confirmXfer = (ConfirmXferPacketPacket)Pack;
6758 7193
6759 handlerConfirmXfer = OnConfirmXfer; 7194 ConfirmXfer handlerConfirmXfer = OnConfirmXfer;
6760 if (handlerConfirmXfer != null) 7195 if (handlerConfirmXfer != null)
6761 { 7196 {
6762 handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet); 7197 handlerConfirmXfer(this, confirmXfer.XferID.ID, confirmXfer.XferID.Packet);
@@ -6764,7 +7199,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6764 break; 7199 break;
6765 case PacketType.AbortXfer: 7200 case PacketType.AbortXfer:
6766 AbortXferPacket abortXfer = (AbortXferPacket)Pack; 7201 AbortXferPacket abortXfer = (AbortXferPacket)Pack;
6767 handlerAbortXfer = OnAbortXfer; 7202 AbortXfer handlerAbortXfer = OnAbortXfer;
6768 if (handlerAbortXfer != null) 7203 if (handlerAbortXfer != null)
6769 { 7204 {
6770 handlerAbortXfer(this, abortXfer.XferID.ID); 7205 handlerAbortXfer(this, abortXfer.XferID.ID);
@@ -6783,7 +7218,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6783 } 7218 }
6784 #endregion 7219 #endregion
6785 7220
6786 handlerCreateInventoryFolder = OnCreateNewInventoryFolder; 7221 CreateInventoryFolder handlerCreateInventoryFolder = OnCreateNewInventoryFolder;
6787 if (handlerCreateInventoryFolder != null) 7222 if (handlerCreateInventoryFolder != null)
6788 { 7223 {
6789 handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID, 7224 handlerCreateInventoryFolder(this, invFolder.FolderData.FolderID,
@@ -6806,7 +7241,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6806 } 7241 }
6807 #endregion 7242 #endregion
6808 7243
6809 handlerUpdateInventoryFolder = null; 7244 UpdateInventoryFolder handlerUpdateInventoryFolder = null;
6810 7245
6811 for (int i = 0; i < invFolderx.FolderData.Length; i++) 7246 for (int i = 0; i < invFolderx.FolderData.Length; i++)
6812 { 7247 {
@@ -6835,7 +7270,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6835 } 7270 }
6836 #endregion 7271 #endregion
6837 7272
6838 handlerMoveInventoryFolder = null; 7273 MoveInventoryFolder handlerMoveInventoryFolder = null;
6839 7274
6840 for (int i = 0; i < invFoldery.InventoryData.Length; i++) 7275 for (int i = 0; i < invFoldery.InventoryData.Length; i++)
6841 { 7276 {
@@ -6860,7 +7295,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6860 } 7295 }
6861 #endregion 7296 #endregion
6862 7297
6863 handlerCreateNewInventoryItem = OnCreateNewInventoryItem; 7298 CreateNewInventoryItem handlerCreateNewInventoryItem = OnCreateNewInventoryItem;
6864 if (handlerCreateNewInventoryItem != null) 7299 if (handlerCreateNewInventoryItem != null)
6865 { 7300 {
6866 handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID, 7301 handlerCreateNewInventoryItem(this, createItem.InventoryBlock.TransactionID,
@@ -6889,7 +7324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6889 } 7324 }
6890 #endregion 7325 #endregion
6891 7326
6892 handlerFetchInventory = null; 7327 FetchInventory handlerFetchInventory = null;
6893 7328
6894 for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++) 7329 for (int i = 0; i < FetchInventoryx.InventoryData.Length; i++)
6895 { 7330 {
@@ -6915,7 +7350,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6915 } 7350 }
6916 #endregion 7351 #endregion
6917 7352
6918 handlerFetchInventoryDescendents = OnFetchInventoryDescendents; 7353 FetchInventoryDescendents handlerFetchInventoryDescendents = OnFetchInventoryDescendents;
6919 if (handlerFetchInventoryDescendents != null) 7354 if (handlerFetchInventoryDescendents != null)
6920 { 7355 {
6921 handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID, 7356 handlerFetchInventoryDescendents(this, Fetch.InventoryData.FolderID, Fetch.InventoryData.OwnerID,
@@ -6935,7 +7370,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6935 } 7370 }
6936 #endregion 7371 #endregion
6937 7372
6938 handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents; 7373 PurgeInventoryDescendents handlerPurgeInventoryDescendents = OnPurgeInventoryDescendents;
6939 if (handlerPurgeInventoryDescendents != null) 7374 if (handlerPurgeInventoryDescendents != null)
6940 { 7375 {
6941 handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID); 7376 handlerPurgeInventoryDescendents(this, Purge.InventoryData.FolderID);
@@ -6955,7 +7390,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6955 7390
6956 if (OnUpdateInventoryItem != null) 7391 if (OnUpdateInventoryItem != null)
6957 { 7392 {
6958 handlerUpdateInventoryItem = null; 7393 UpdateInventoryItem handlerUpdateInventoryItem = null;
6959 for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++) 7394 for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++)
6960 { 7395 {
6961 handlerUpdateInventoryItem = OnUpdateInventoryItem; 7396 handlerUpdateInventoryItem = OnUpdateInventoryItem;
@@ -6977,49 +7412,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6977 itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice; 7412 itemUpd.SalePrice = inventoryItemUpdate.InventoryData[i].SalePrice;
6978 itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType; 7413 itemUpd.SaleType = inventoryItemUpdate.InventoryData[i].SaleType;
6979 itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags; 7414 itemUpd.Flags = inventoryItemUpdate.InventoryData[i].Flags;
6980 /* 7415
6981 OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID,
6982 inventoryItemUpdate.InventoryData[i].ItemID,
6983 Util.FieldToString(inventoryItemUpdate.InventoryData[i].Name),
6984 Util.FieldToString(inventoryItemUpdate.InventoryData[i].Description),
6985 inventoryItemUpdate.InventoryData[i].NextOwnerMask);
6986 */
6987 OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID, 7416 OnUpdateInventoryItem(this, inventoryItemUpdate.InventoryData[i].TransactionID,
6988 inventoryItemUpdate.InventoryData[i].ItemID, 7417 inventoryItemUpdate.InventoryData[i].ItemID,
6989 itemUpd); 7418 itemUpd);
6990 } 7419 }
6991 } 7420 }
6992 } 7421 }
6993 //m_log.Debug(Pack.ToString());
6994 /*for (int i = 0; i < inventoryItemUpdate.InventoryData.Length; i++)
6995 {
6996 if (inventoryItemUpdate.InventoryData[i].TransactionID != UUID.Zero)
6997 {
6998 AssetBase asset = m_assetCache.GetAsset(inventoryItemUpdate.InventoryData[i].TransactionID.Combine(this.SecureSessionId));
6999 if (asset != null)
7000 {
7001 // m_log.Debug("updating inventory item, found asset" + asset.FullID.ToString() + " already in cache");
7002 m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset);
7003 }
7004 else
7005 {
7006 asset = this.UploadAssets.AddUploadToAssetCache(inventoryItemUpdate.InventoryData[i].TransactionID);
7007 if (asset != null)
7008 {
7009 //m_log.Debug("updating inventory item, adding asset" + asset.FullID.ToString() + " to cache");
7010 m_inventoryCache.UpdateInventoryItemAsset(this, inventoryItemUpdate.InventoryData[i].ItemID, asset);
7011 }
7012 else
7013 {
7014 //m_log.Debug("trying to update inventory item, but asset is null");
7015 }
7016 }
7017 }
7018 else
7019 {
7020 m_inventoryCache.UpdateInventoryItemDetails(this, inventoryItemUpdate.InventoryData[i].ItemID, inventoryItemUpdate.InventoryData[i]); ;
7021 }
7022 }*/
7023 break; 7422 break;
7024 case PacketType.CopyInventoryItem: 7423 case PacketType.CopyInventoryItem:
7025 CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack; 7424 CopyInventoryItemPacket copyitem = (CopyInventoryItemPacket)Pack;
@@ -7033,7 +7432,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7033 } 7432 }
7034 #endregion 7433 #endregion
7035 7434
7036 handlerCopyInventoryItem = null; 7435 CopyInventoryItem handlerCopyInventoryItem = null;
7037 if (OnCopyInventoryItem != null) 7436 if (OnCopyInventoryItem != null)
7038 { 7437 {
7039 foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData) 7438 foreach (CopyInventoryItemPacket.InventoryDataBlock datablock in copyitem.InventoryData)
@@ -7062,7 +7461,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7062 7461
7063 if (OnMoveInventoryItem != null) 7462 if (OnMoveInventoryItem != null)
7064 { 7463 {
7065 handlerMoveInventoryItem = null; 7464 MoveInventoryItem handlerMoveInventoryItem = null;
7066 InventoryItemBase itm = null; 7465 InventoryItemBase itm = null;
7067 List<InventoryItemBase> items = new List<InventoryItemBase>(); 7466 List<InventoryItemBase> items = new List<InventoryItemBase>();
7068 foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData) 7467 foreach (MoveInventoryItemPacket.InventoryDataBlock datablock in moveitem.InventoryData)
@@ -7095,7 +7494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7095 7494
7096 if (OnRemoveInventoryItem != null) 7495 if (OnRemoveInventoryItem != null)
7097 { 7496 {
7098 handlerRemoveInventoryItem = null; 7497 RemoveInventoryItem handlerRemoveInventoryItem = null;
7099 List<UUID> uuids = new List<UUID>(); 7498 List<UUID> uuids = new List<UUID>();
7100 foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData) 7499 foreach (RemoveInventoryItemPacket.InventoryDataBlock datablock in removeItem.InventoryData)
7101 { 7500 {
@@ -7123,7 +7522,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7123 7522
7124 if (OnRemoveInventoryFolder != null) 7523 if (OnRemoveInventoryFolder != null)
7125 { 7524 {
7126 handlerRemoveInventoryFolder = null; 7525 RemoveInventoryFolder handlerRemoveInventoryFolder = null;
7127 List<UUID> uuids = new List<UUID>(); 7526 List<UUID> uuids = new List<UUID>();
7128 foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData) 7527 foreach (RemoveInventoryFolderPacket.FolderDataBlock datablock in removeFolder.FolderData)
7129 { 7528 {
@@ -7148,7 +7547,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7148 #endregion 7547 #endregion
7149 if (OnRemoveInventoryFolder != null) 7548 if (OnRemoveInventoryFolder != null)
7150 { 7549 {
7151 handlerRemoveInventoryFolder = null; 7550 RemoveInventoryFolder handlerRemoveInventoryFolder = null;
7152 List<UUID> uuids = new List<UUID>(); 7551 List<UUID> uuids = new List<UUID>();
7153 foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData) 7552 foreach (RemoveInventoryObjectsPacket.FolderDataBlock datablock in removeObject.FolderData)
7154 { 7553 {
@@ -7163,7 +7562,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7163 7562
7164 if (OnRemoveInventoryItem != null) 7563 if (OnRemoveInventoryItem != null)
7165 { 7564 {
7166 handlerRemoveInventoryItem = null; 7565 RemoveInventoryItem handlerRemoveInventoryItem = null;
7167 List<UUID> uuids = new List<UUID>(); 7566 List<UUID> uuids = new List<UUID>();
7168 foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData) 7567 foreach (RemoveInventoryObjectsPacket.ItemDataBlock datablock in removeObject.ItemData)
7169 { 7568 {
@@ -7188,7 +7587,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7188 } 7587 }
7189 #endregion 7588 #endregion
7190 7589
7191 handlerRequestTaskInventory = OnRequestTaskInventory; 7590 RequestTaskInventory handlerRequestTaskInventory = OnRequestTaskInventory;
7192 if (handlerRequestTaskInventory != null) 7591 if (handlerRequestTaskInventory != null)
7193 { 7592 {
7194 handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID); 7593 handlerRequestTaskInventory(this, requesttask.InventoryData.LocalID);
@@ -7210,7 +7609,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7210 { 7609 {
7211 if (updatetask.UpdateData.Key == 0) 7610 if (updatetask.UpdateData.Key == 0)
7212 { 7611 {
7213 handlerUpdateTaskInventory = OnUpdateTaskInventory; 7612 UpdateTaskInventory handlerUpdateTaskInventory = OnUpdateTaskInventory;
7214 if (handlerUpdateTaskInventory != null) 7613 if (handlerUpdateTaskInventory != null)
7215 { 7614 {
7216 TaskInventoryItem newTaskItem = new TaskInventoryItem(); 7615 TaskInventoryItem newTaskItem = new TaskInventoryItem();
@@ -7254,7 +7653,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7254 } 7653 }
7255 #endregion 7654 #endregion
7256 7655
7257 handlerRemoveTaskItem = OnRemoveTaskItem; 7656 RemoveTaskInventory handlerRemoveTaskItem = OnRemoveTaskItem;
7258 7657
7259 if (handlerRemoveTaskItem != null) 7658 if (handlerRemoveTaskItem != null)
7260 { 7659 {
@@ -7276,7 +7675,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7276 } 7675 }
7277 #endregion 7676 #endregion
7278 7677
7279 handlerMoveTaskItem = OnMoveTaskItem; 7678 MoveTaskInventory handlerMoveTaskItem = OnMoveTaskItem;
7280 7679
7281 if (handlerMoveTaskItem != null) 7680 if (handlerMoveTaskItem != null)
7282 { 7681 {
@@ -7301,7 +7700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7301 } 7700 }
7302 #endregion 7701 #endregion
7303 7702
7304 handlerRezScript = OnRezScript; 7703 RezScript handlerRezScript = OnRezScript;
7305 InventoryItemBase item = new InventoryItemBase(); 7704 InventoryItemBase item = new InventoryItemBase();
7306 item.ID = rezScriptx.InventoryBlock.ItemID; 7705 item.ID = rezScriptx.InventoryBlock.ItemID;
7307 item.Folder = rezScriptx.InventoryBlock.FolderID; 7706 item.Folder = rezScriptx.InventoryBlock.FolderID;
@@ -7344,7 +7743,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7344 } 7743 }
7345 #endregion 7744 #endregion
7346 7745
7347 handlerRequestMapBlocks = OnRequestMapBlocks; 7746 RequestMapBlocks handlerRequestMapBlocks = OnRequestMapBlocks;
7348 if (handlerRequestMapBlocks != null) 7747 if (handlerRequestMapBlocks != null)
7349 { 7748 {
7350 handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY, 7749 handlerRequestMapBlocks(this, MapRequest.PositionData.MinX, MapRequest.PositionData.MinY,
@@ -7365,7 +7764,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7365 7764
7366 string mapName = Util.UTF8.GetString(map.NameData.Name, 0, 7765 string mapName = Util.UTF8.GetString(map.NameData.Name, 0,
7367 map.NameData.Name.Length - 1); 7766 map.NameData.Name.Length - 1);
7368 handlerMapNameRequest = OnMapNameRequest; 7767 RequestMapName handlerMapNameRequest = OnMapNameRequest;
7369 if (handlerMapNameRequest != null) 7768 if (handlerMapNameRequest != null)
7370 { 7769 {
7371 handlerMapNameRequest(this, mapName); 7770 handlerMapNameRequest(this, mapName);
@@ -7416,7 +7815,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7416 else 7815 else
7417 { 7816 {
7418 // Teleport home request 7817 // Teleport home request
7419 handlerTeleportHomeRequest = OnTeleportHomeRequest; 7818 UUIDNameRequest handlerTeleportHomeRequest = OnTeleportHomeRequest;
7420 if (handlerTeleportHomeRequest != null) 7819 if (handlerTeleportHomeRequest != null)
7421 { 7820 {
7422 handlerTeleportHomeRequest(AgentId, this); 7821 handlerTeleportHomeRequest(AgentId, this);
@@ -7424,7 +7823,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7424 break; 7823 break;
7425 } 7824 }
7426 7825
7427 handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest; 7826 TeleportLandmarkRequest handlerTeleportLandmarkRequest = OnTeleportLandmarkRequest;
7428 if (handlerTeleportLandmarkRequest != null) 7827 if (handlerTeleportLandmarkRequest != null)
7429 { 7828 {
7430 handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position); 7829 handlerTeleportLandmarkRequest(this, lm.RegionID, lm.Position);
@@ -7455,7 +7854,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7455 } 7854 }
7456 #endregion 7855 #endregion
7457 7856
7458 handlerTeleportLocationRequest = OnTeleportLocationRequest; 7857 TeleportLocationRequest handlerTeleportLocationRequest = OnTeleportLocationRequest;
7459 if (handlerTeleportLocationRequest != null) 7858 if (handlerTeleportLocationRequest != null)
7460 { 7859 {
7461 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position, 7860 handlerTeleportLocationRequest(this, tpLocReq.Info.RegionHandle, tpLocReq.Info.Position,
@@ -7478,7 +7877,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7478 7877
7479 foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) 7878 foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock)
7480 { 7879 {
7481 handlerNameRequest = OnNameFromUUIDRequest; 7880 UUIDNameRequest handlerNameRequest = OnNameFromUUIDRequest;
7482 if (handlerNameRequest != null) 7881 if (handlerNameRequest != null)
7483 { 7882 {
7484 handlerNameRequest(UUIDBlock.ID, this); 7883 handlerNameRequest(UUIDBlock.ID, this);
@@ -7491,7 +7890,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7491 case PacketType.RegionHandleRequest: 7890 case PacketType.RegionHandleRequest:
7492 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 7891 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
7493 7892
7494 handlerRegionHandleRequest = OnRegionHandleRequest; 7893 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
7495 if (handlerRegionHandleRequest != null) 7894 if (handlerRegionHandleRequest != null)
7496 { 7895 {
7497 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 7896 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID);
@@ -7510,7 +7909,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7510 } 7909 }
7511 #endregion 7910 #endregion
7512 7911
7513 handlerParcelInfoRequest = OnParcelInfoRequest; 7912 ParcelInfoRequest handlerParcelInfoRequest = OnParcelInfoRequest;
7514 if (handlerParcelInfoRequest != null) 7913 if (handlerParcelInfoRequest != null)
7515 { 7914 {
7516 handlerParcelInfoRequest(this, pirPack.Data.ParcelID); 7915 handlerParcelInfoRequest(this, pirPack.Data.ParcelID);
@@ -7529,7 +7928,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7529 } 7928 }
7530 #endregion 7929 #endregion
7531 7930
7532 handlerParcelAccessListRequest = OnParcelAccessListRequest; 7931 ParcelAccessListRequest handlerParcelAccessListRequest = OnParcelAccessListRequest;
7533 7932
7534 if (handlerParcelAccessListRequest != null) 7933 if (handlerParcelAccessListRequest != null)
7535 { 7934 {
@@ -7561,7 +7960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7561 entries.Add(entry); 7960 entries.Add(entry);
7562 } 7961 }
7563 7962
7564 handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest; 7963 ParcelAccessListUpdateRequest handlerParcelAccessListUpdateRequest = OnParcelAccessListUpdateRequest;
7565 if (handlerParcelAccessListUpdateRequest != null) 7964 if (handlerParcelAccessListUpdateRequest != null)
7566 { 7965 {
7567 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, 7966 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID,
@@ -7582,7 +7981,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7582 } 7981 }
7583 #endregion 7982 #endregion
7584 7983
7585 handlerParcelPropertiesRequest = OnParcelPropertiesRequest; 7984 ParcelPropertiesRequest handlerParcelPropertiesRequest = OnParcelPropertiesRequest;
7586 if (handlerParcelPropertiesRequest != null) 7985 if (handlerParcelPropertiesRequest != null)
7587 { 7986 {
7588 handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West), 7987 handlerParcelPropertiesRequest((int)Math.Round(propertiesRequest.ParcelData.West),
@@ -7605,7 +8004,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7605 } 8004 }
7606 #endregion 8005 #endregion
7607 8006
7608 handlerParcelDivideRequest = OnParcelDivideRequest; 8007 ParcelDivideRequest handlerParcelDivideRequest = OnParcelDivideRequest;
7609 if (handlerParcelDivideRequest != null) 8008 if (handlerParcelDivideRequest != null)
7610 { 8009 {
7611 handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West), 8010 handlerParcelDivideRequest((int)Math.Round(landDivide.ParcelData.West),
@@ -7626,7 +8025,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7626 } 8025 }
7627 #endregion 8026 #endregion
7628 8027
7629 handlerParcelJoinRequest = OnParcelJoinRequest; 8028 ParcelJoinRequest handlerParcelJoinRequest = OnParcelJoinRequest;
7630 8029
7631 if (handlerParcelJoinRequest != null) 8030 if (handlerParcelJoinRequest != null)
7632 { 8031 {
@@ -7648,7 +8047,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7648 } 8047 }
7649 #endregion 8048 #endregion
7650 8049
7651 handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest; 8050 ParcelPropertiesUpdateRequest handlerParcelPropertiesUpdateRequest = OnParcelPropertiesUpdateRequest;
7652 8051
7653 if (handlerParcelPropertiesUpdateRequest != null) 8052 if (handlerParcelPropertiesUpdateRequest != null)
7654 { 8053 {
@@ -7694,7 +8093,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7694 returnIDs.Add(rb.ReturnID); 8093 returnIDs.Add(rb.ReturnID);
7695 } 8094 }
7696 8095
7697 handlerParcelSelectObjects = OnParcelSelectObjects; 8096 ParcelSelectObjects handlerParcelSelectObjects = OnParcelSelectObjects;
7698 8097
7699 if (handlerParcelSelectObjects != null) 8098 if (handlerParcelSelectObjects != null)
7700 { 8099 {
@@ -7715,7 +8114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7715 } 8114 }
7716 #endregion 8115 #endregion
7717 8116
7718 handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest; 8117 ParcelObjectOwnerRequest handlerParcelObjectOwnerRequest = OnParcelObjectOwnerRequest;
7719 8118
7720 if (handlerParcelObjectOwnerRequest != null) 8119 if (handlerParcelObjectOwnerRequest != null)
7721 { 8120 {
@@ -7734,7 +8133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7734 } 8133 }
7735 #endregion 8134 #endregion
7736 8135
7737 handlerParcelGodForceOwner = OnParcelGodForceOwner; 8136 ParcelGodForceOwner handlerParcelGodForceOwner = OnParcelGodForceOwner;
7738 if (handlerParcelGodForceOwner != null) 8137 if (handlerParcelGodForceOwner != null)
7739 { 8138 {
7740 handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this); 8139 handlerParcelGodForceOwner(godForceOwnerPacket.Data.LocalID, godForceOwnerPacket.Data.OwnerID, this);
@@ -7752,7 +8151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7752 } 8151 }
7753 #endregion 8152 #endregion
7754 8153
7755 handlerParcelAbandonRequest = OnParcelAbandonRequest; 8154 ParcelAbandonRequest handlerParcelAbandonRequest = OnParcelAbandonRequest;
7756 if (handlerParcelAbandonRequest != null) 8155 if (handlerParcelAbandonRequest != null)
7757 { 8156 {
7758 handlerParcelAbandonRequest(releasePacket.Data.LocalID, this); 8157 handlerParcelAbandonRequest(releasePacket.Data.LocalID, this);
@@ -7770,7 +8169,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7770 } 8169 }
7771 #endregion 8170 #endregion
7772 8171
7773 handlerParcelReclaim = OnParcelReclaim; 8172 ParcelReclaim handlerParcelReclaim = OnParcelReclaim;
7774 if (handlerParcelReclaim != null) 8173 if (handlerParcelReclaim != null)
7775 { 8174 {
7776 handlerParcelReclaim(reclaimPacket.Data.LocalID, this); 8175 handlerParcelReclaim(reclaimPacket.Data.LocalID, this);
@@ -7799,7 +8198,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7799 for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++) 8198 for (int parceliterator = 0; parceliterator < parcelReturnObjects.TaskIDs.Length; parceliterator++)
7800 puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID; 8199 puserselectedTaskIDs[parceliterator] = parcelReturnObjects.TaskIDs[parceliterator].TaskID;
7801 8200
7802 handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest; 8201 ParcelReturnObjectsRequest handlerParcelReturnObjectsRequest = OnParcelReturnObjectsRequest;
7803 if (handlerParcelReturnObjectsRequest != null) 8202 if (handlerParcelReturnObjectsRequest != null)
7804 { 8203 {
7805 handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this); 8204 handlerParcelReturnObjectsRequest(parcelReturnObjects.ParcelData.LocalID, parcelReturnObjects.ParcelData.ReturnType, puserselectedOwnerIDs, puserselectedTaskIDs, this);
@@ -7819,7 +8218,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7819 } 8218 }
7820 #endregion 8219 #endregion
7821 8220
7822 handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime; 8221 ParcelSetOtherCleanTime handlerParcelSetOtherCleanTime = OnParcelSetOtherCleanTime;
7823 if (handlerParcelSetOtherCleanTime != null) 8222 if (handlerParcelSetOtherCleanTime != null)
7824 { 8223 {
7825 handlerParcelSetOtherCleanTime(this, 8224 handlerParcelSetOtherCleanTime(this,
@@ -7840,7 +8239,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7840 } 8239 }
7841 #endregion 8240 #endregion
7842 8241
7843 handlerLandStatRequest = OnLandStatRequest; 8242 GodLandStatRequest handlerLandStatRequest = OnLandStatRequest;
7844 if (handlerLandStatRequest != null) 8243 if (handlerLandStatRequest != null)
7845 { 8244 {
7846 handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this); 8245 handlerLandStatRequest(lsrp.RequestData.ParcelLocalID, lsrp.RequestData.ReportType, lsrp.RequestData.RequestFlags, Utils.BytesToString(lsrp.RequestData.Filter), this);
@@ -7860,7 +8259,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7860 } 8259 }
7861 #endregion 8260 #endregion
7862 8261
7863 handlerParcelDwellRequest = OnParcelDwellRequest; 8262 ParcelDwellRequest handlerParcelDwellRequest = OnParcelDwellRequest;
7864 if (handlerParcelDwellRequest != null) 8263 if (handlerParcelDwellRequest != null)
7865 { 8264 {
7866 handlerParcelDwellRequest(dwellrq.Data.LocalID, this); 8265 handlerParcelDwellRequest(dwellrq.Data.LocalID, this);
@@ -8104,7 +8503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8104 { 8503 {
8105 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake") 8504 if (Utils.BytesToString(messagePacket.ParamList[0].Parameter) == "bake")
8106 { 8505 {
8107 handlerBakeTerrain = OnBakeTerrain; 8506 BakeTerrain handlerBakeTerrain = OnBakeTerrain;
8108 if (handlerBakeTerrain != null) 8507 if (handlerBakeTerrain != null)
8109 { 8508 {
8110 handlerBakeTerrain(this); 8509 handlerBakeTerrain(this);
@@ -8114,7 +8513,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8114 { 8513 {
8115 if (messagePacket.ParamList.Length > 1) 8514 if (messagePacket.ParamList.Length > 1)
8116 { 8515 {
8117 handlerRequestTerrain = OnRequestTerrain; 8516 RequestTerrain handlerRequestTerrain = OnRequestTerrain;
8118 if (handlerRequestTerrain != null) 8517 if (handlerRequestTerrain != null)
8119 { 8518 {
8120 handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); 8519 handlerRequestTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
@@ -8125,7 +8524,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8125 { 8524 {
8126 if (messagePacket.ParamList.Length > 1) 8525 if (messagePacket.ParamList.Length > 1)
8127 { 8526 {
8128 handlerUploadTerrain = OnUploadTerrain; 8527 RequestTerrain handlerUploadTerrain = OnUploadTerrain;
8129 if (handlerUploadTerrain != null) 8528 if (handlerUploadTerrain != null)
8130 { 8529 {
8131 handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter)); 8530 handlerUploadTerrain(this, Utils.BytesToString(messagePacket.ParamList[1].Parameter));
@@ -8147,7 +8546,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8147 UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); 8546 UInt32 param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
8148 UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter)); 8547 UInt32 param2 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[2].Parameter));
8149 8548
8150 handlerEstateChangeInfo = OnEstateChangeInfo; 8549 EstateChangeInfo handlerEstateChangeInfo = OnEstateChangeInfo;
8151 if (handlerEstateChangeInfo != null) 8550 if (handlerEstateChangeInfo != null)
8152 { 8551 {
8153 handlerEstateChangeInfo(this, invoice, SenderID, param1, param2); 8552 handlerEstateChangeInfo(this, invoice, SenderID, param1, param2);
@@ -8181,7 +8580,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8181 } 8580 }
8182 #endregion 8581 #endregion
8183 8582
8184 handlerRegionInfoRequest = OnRegionInfoRequest; 8583 RegionInfoRequest handlerRegionInfoRequest = OnRegionInfoRequest;
8185 if (handlerRegionInfoRequest != null) 8584 if (handlerRegionInfoRequest != null)
8186 { 8585 {
8187 handlerRegionInfoRequest(this); 8586 handlerRegionInfoRequest(this);
@@ -8192,7 +8591,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8192 //EstateCovenantRequestPacket.AgentDataBlock epack = 8591 //EstateCovenantRequestPacket.AgentDataBlock epack =
8193 // ((EstateCovenantRequestPacket)Pack).AgentData; 8592 // ((EstateCovenantRequestPacket)Pack).AgentData;
8194 8593
8195 handlerEstateCovenantRequest = OnEstateCovenantRequest; 8594 EstateCovenantRequest handlerEstateCovenantRequest = OnEstateCovenantRequest;
8196 if (handlerEstateCovenantRequest != null) 8595 if (handlerEstateCovenantRequest != null)
8197 { 8596 {
8198 handlerEstateCovenantRequest(this); 8597 handlerEstateCovenantRequest(this);
@@ -8210,7 +8609,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8210 8609
8211 RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData; 8610 RequestGodlikePowersPacket.AgentDataBlock ablock = rglpPack.AgentData;
8212 8611
8213 handlerReqGodlikePowers = OnRequestGodlikePowers; 8612 RequestGodlikePowers handlerReqGodlikePowers = OnRequestGodlikePowers;
8214 8613
8215 if (handlerReqGodlikePowers != null) 8614 if (handlerReqGodlikePowers != null)
8216 { 8615 {
@@ -8223,7 +8622,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8223 8622
8224 if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID) 8623 if (gkupack.UserInfo.GodSessionID == SessionId && AgentId == gkupack.UserInfo.GodID)
8225 { 8624 {
8226 handlerGodKickUser = OnGodKickUser; 8625 GodKickUser handlerGodKickUser = OnGodKickUser;
8227 if (handlerGodKickUser != null) 8626 if (handlerGodKickUser != null)
8228 { 8627 {
8229 handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID, 8628 handlerGodKickUser(gkupack.UserInfo.GodID, gkupack.UserInfo.GodSessionID,
@@ -8263,7 +8662,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8263 } 8662 }
8264 #endregion 8663 #endregion
8265 8664
8266 handlerMoneyBalanceRequest = OnMoneyBalanceRequest; 8665 MoneyBalanceRequest handlerMoneyBalanceRequest = OnMoneyBalanceRequest;
8267 8666
8268 if (handlerMoneyBalanceRequest != null) 8667 if (handlerMoneyBalanceRequest != null)
8269 { 8668 {
@@ -8274,7 +8673,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8274 case PacketType.EconomyDataRequest: 8673 case PacketType.EconomyDataRequest:
8275 8674
8276 8675
8277 handlerEconomoyDataRequest = OnEconomyDataRequest; 8676 EconomyDataRequest handlerEconomoyDataRequest = OnEconomyDataRequest;
8278 if (handlerEconomoyDataRequest != null) 8677 if (handlerEconomoyDataRequest != null)
8279 { 8678 {
8280 handlerEconomoyDataRequest(AgentId); 8679 handlerEconomoyDataRequest(AgentId);
@@ -8283,7 +8682,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8283 case PacketType.RequestPayPrice: 8682 case PacketType.RequestPayPrice:
8284 RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack; 8683 RequestPayPricePacket requestPayPricePacket = (RequestPayPricePacket)Pack;
8285 8684
8286 handlerRequestPayPrice = OnRequestPayPrice; 8685 RequestPayPrice handlerRequestPayPrice = OnRequestPayPrice;
8287 if (handlerRequestPayPrice != null) 8686 if (handlerRequestPayPrice != null)
8288 { 8687 {
8289 handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID); 8688 handlerRequestPayPrice(this, requestPayPricePacket.ObjectData.ObjectID);
@@ -8302,7 +8701,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8302 } 8701 }
8303 #endregion 8702 #endregion
8304 8703
8305 handlerObjectSaleInfo = OnObjectSaleInfo; 8704 ObjectSaleInfo handlerObjectSaleInfo = OnObjectSaleInfo;
8306 if (handlerObjectSaleInfo != null) 8705 if (handlerObjectSaleInfo != null)
8307 { 8706 {
8308 foreach (ObjectSaleInfoPacket.ObjectDataBlock d 8707 foreach (ObjectSaleInfoPacket.ObjectDataBlock d
@@ -8330,7 +8729,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8330 } 8729 }
8331 #endregion 8730 #endregion
8332 8731
8333 handlerObjectBuy = OnObjectBuy; 8732 ObjectBuy handlerObjectBuy = OnObjectBuy;
8334 8733
8335 if (handlerObjectBuy != null) 8734 if (handlerObjectBuy != null)
8336 { 8735 {
@@ -8356,7 +8755,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8356 case PacketType.GetScriptRunning: 8755 case PacketType.GetScriptRunning:
8357 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack; 8756 GetScriptRunningPacket scriptRunning = (GetScriptRunningPacket)Pack;
8358 8757
8359 handlerGetScriptRunning = OnGetScriptRunning; 8758 GetScriptRunning handlerGetScriptRunning = OnGetScriptRunning;
8360 if (handlerGetScriptRunning != null) 8759 if (handlerGetScriptRunning != null)
8361 { 8760 {
8362 handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID); 8761 handlerGetScriptRunning(this, scriptRunning.Script.ObjectID, scriptRunning.Script.ItemID);
@@ -8375,7 +8774,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8375 } 8774 }
8376 #endregion 8775 #endregion
8377 8776
8378 handlerSetScriptRunning = OnSetScriptRunning; 8777 SetScriptRunning handlerSetScriptRunning = OnSetScriptRunning;
8379 if (handlerSetScriptRunning != null) 8778 if (handlerSetScriptRunning != null)
8380 { 8779 {
8381 handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running); 8780 handlerSetScriptRunning(this, setScriptRunning.Script.ObjectID, setScriptRunning.Script.ItemID, setScriptRunning.Script.Running);
@@ -8394,7 +8793,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8394 } 8793 }
8395 #endregion 8794 #endregion
8396 8795
8397 handlerScriptReset = OnScriptReset; 8796 ScriptReset handlerScriptReset = OnScriptReset;
8398 if (handlerScriptReset != null) 8797 if (handlerScriptReset != null)
8399 { 8798 {
8400 handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID); 8799 handlerScriptReset(this, scriptResetPacket.Script.ObjectID, scriptResetPacket.Script.ItemID);
@@ -8417,7 +8816,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8417 } 8816 }
8418 #endregion 8817 #endregion
8419 8818
8420 handlerActivateGesture = OnActivateGesture; 8819 ActivateGesture handlerActivateGesture = OnActivateGesture;
8421 if (handlerActivateGesture != null) 8820 if (handlerActivateGesture != null)
8422 { 8821 {
8423 handlerActivateGesture(this, 8822 handlerActivateGesture(this,
@@ -8440,7 +8839,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8440 } 8839 }
8441 #endregion 8840 #endregion
8442 8841
8443 handlerDeactivateGesture = OnDeactivateGesture; 8842 DeactivateGesture handlerDeactivateGesture = OnDeactivateGesture;
8444 if (handlerDeactivateGesture != null) 8843 if (handlerDeactivateGesture != null)
8445 { 8844 {
8446 handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID); 8845 handlerDeactivateGesture(this, deactivateGesturePacket.Data[0].ItemID);
@@ -8463,7 +8862,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8463 foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData) 8862 foreach (ObjectOwnerPacket.ObjectDataBlock d in objectOwnerPacket.ObjectData)
8464 localIDs.Add(d.ObjectLocalID); 8863 localIDs.Add(d.ObjectLocalID);
8465 8864
8466 handlerObjectOwner = OnObjectOwner; 8865 ObjectOwner handlerObjectOwner = OnObjectOwner;
8467 if (handlerObjectOwner != null) 8866 if (handlerObjectOwner != null)
8468 { 8867 {
8469 handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs); 8868 handlerObjectOwner(this, objectOwnerPacket.HeaderData.OwnerID, objectOwnerPacket.HeaderData.GroupID, localIDs);
@@ -8476,14 +8875,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8476 #region unimplemented handlers 8875 #region unimplemented handlers
8477 8876
8478 case PacketType.StartPingCheck: 8877 case PacketType.StartPingCheck:
8479 // Send the client the ping response back 8878 StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack;
8480 // Pass the same PingID in the matching packet 8879 CompletePingCheckPacket pingComplete = new CompletePingCheckPacket();
8481 // Handled In the packet processing 8880 pingComplete.PingID.PingID = pingStart.PingID.PingID;
8482 //m_log.Debug("[CLIENT]: possibly unhandled StartPingCheck packet"); 8881 m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false);
8483 break; 8882 break;
8883
8484 case PacketType.CompletePingCheck: 8884 case PacketType.CompletePingCheck:
8485 // TODO: Perhaps this should be processed on the Sim to determine whether or not to drop a dead client 8885 // TODO: Do stats tracking or something with these?
8486 //m_log.Warn("[CLIENT]: unhandled CompletePingCheck packet");
8487 break; 8886 break;
8488 8887
8489 case PacketType.ViewerStats: 8888 case PacketType.ViewerStats:
@@ -8504,7 +8903,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8504 #endregion 8903 #endregion
8505 8904
8506 //m_log.Debug(mirpk.ToString()); 8905 //m_log.Debug(mirpk.ToString());
8507 handlerMapItemRequest = OnMapItemRequest; 8906 MapItemRequest handlerMapItemRequest = OnMapItemRequest;
8508 if (handlerMapItemRequest != null) 8907 if (handlerMapItemRequest != null)
8509 { 8908 {
8510 handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID, 8909 handlerMapItemRequest(this,mirpk.AgentData.Flags, mirpk.AgentData.EstateID,
@@ -8531,7 +8930,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8531 } 8930 }
8532 #endregion 8931 #endregion
8533 8932
8534 handlerMuteListRequest = OnMuteListRequest; 8933 MuteListRequest handlerMuteListRequest = OnMuteListRequest;
8535 if (handlerMuteListRequest != null) 8934 if (handlerMuteListRequest != null)
8536 { 8935 {
8537 handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC); 8936 handlerMuteListRequest(this, muteListRequest.MuteData.MuteCRC);
@@ -8568,7 +8967,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8568 } 8967 }
8569 #endregion 8968 #endregion
8570 8969
8571 handlerDirPlacesQuery = OnDirPlacesQuery; 8970 DirPlacesQuery handlerDirPlacesQuery = OnDirPlacesQuery;
8572 if (handlerDirPlacesQuery != null) 8971 if (handlerDirPlacesQuery != null)
8573 { 8972 {
8574 handlerDirPlacesQuery(this, 8973 handlerDirPlacesQuery(this,
@@ -8594,7 +8993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8594 } 8993 }
8595 #endregion 8994 #endregion
8596 8995
8597 handlerDirFindQuery = OnDirFindQuery; 8996 DirFindQuery handlerDirFindQuery = OnDirFindQuery;
8598 if (handlerDirFindQuery != null) 8997 if (handlerDirFindQuery != null)
8599 { 8998 {
8600 handlerDirFindQuery(this, 8999 handlerDirFindQuery(this,
@@ -8617,7 +9016,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8617 } 9016 }
8618 #endregion 9017 #endregion
8619 9018
8620 handlerDirLandQuery = OnDirLandQuery; 9019 DirLandQuery handlerDirLandQuery = OnDirLandQuery;
8621 if (handlerDirLandQuery != null) 9020 if (handlerDirLandQuery != null)
8622 { 9021 {
8623 handlerDirLandQuery(this, 9022 handlerDirLandQuery(this,
@@ -8641,7 +9040,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8641 } 9040 }
8642 #endregion 9041 #endregion
8643 9042
8644 handlerDirPopularQuery = OnDirPopularQuery; 9043 DirPopularQuery handlerDirPopularQuery = OnDirPopularQuery;
8645 if (handlerDirPopularQuery != null) 9044 if (handlerDirPopularQuery != null)
8646 { 9045 {
8647 handlerDirPopularQuery(this, 9046 handlerDirPopularQuery(this,
@@ -8661,7 +9060,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8661 } 9060 }
8662 #endregion 9061 #endregion
8663 9062
8664 handlerDirClassifiedQuery = OnDirClassifiedQuery; 9063 DirClassifiedQuery handlerDirClassifiedQuery = OnDirClassifiedQuery;
8665 if (handlerDirClassifiedQuery != null) 9064 if (handlerDirClassifiedQuery != null)
8666 { 9065 {
8667 handlerDirClassifiedQuery(this, 9066 handlerDirClassifiedQuery(this,
@@ -9177,7 +9576,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9177 ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack; 9576 ParcelDeedToGroupPacket parcelDeedToGroup = (ParcelDeedToGroupPacket)Pack;
9178 if (m_GroupsModule != null) 9577 if (m_GroupsModule != null)
9179 { 9578 {
9180 handlerParcelDeedToGroup = OnParcelDeedToGroup; 9579 ParcelDeedToGroup handlerParcelDeedToGroup = OnParcelDeedToGroup;
9181 if (handlerParcelDeedToGroup != null) 9580 if (handlerParcelDeedToGroup != null)
9182 { 9581 {
9183 handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this); 9582 handlerParcelDeedToGroup(parcelDeedToGroup.Data.LocalID, parcelDeedToGroup.Data.GroupID,this);
@@ -9421,7 +9820,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9421 } 9820 }
9422 #endregion 9821 #endregion
9423 9822
9424 handlerStartLure = OnStartLure; 9823 StartLure handlerStartLure = OnStartLure;
9425 if (handlerStartLure != null) 9824 if (handlerStartLure != null)
9426 handlerStartLure(startLureRequest.Info.LureType, 9825 handlerStartLure(startLureRequest.Info.LureType,
9427 Utils.BytesToString( 9826 Utils.BytesToString(
@@ -9443,7 +9842,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9443 } 9842 }
9444 #endregion 9843 #endregion
9445 9844
9446 handlerTeleportLureRequest = OnTeleportLureRequest; 9845 TeleportLureRequest handlerTeleportLureRequest = OnTeleportLureRequest;
9447 if (handlerTeleportLureRequest != null) 9846 if (handlerTeleportLureRequest != null)
9448 handlerTeleportLureRequest( 9847 handlerTeleportLureRequest(
9449 teleportLureRequest.Info.LureID, 9848 teleportLureRequest.Info.LureID,
@@ -9464,7 +9863,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9464 } 9863 }
9465 #endregion 9864 #endregion
9466 9865
9467 handlerClassifiedInfoRequest = OnClassifiedInfoRequest; 9866 ClassifiedInfoRequest handlerClassifiedInfoRequest = OnClassifiedInfoRequest;
9468 if (handlerClassifiedInfoRequest != null) 9867 if (handlerClassifiedInfoRequest != null)
9469 handlerClassifiedInfoRequest( 9868 handlerClassifiedInfoRequest(
9470 classifiedInfoRequest.Data.ClassifiedID, 9869 classifiedInfoRequest.Data.ClassifiedID,
@@ -9484,7 +9883,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9484 } 9883 }
9485 #endregion 9884 #endregion
9486 9885
9487 handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate; 9886 ClassifiedInfoUpdate handlerClassifiedInfoUpdate = OnClassifiedInfoUpdate;
9488 if (handlerClassifiedInfoUpdate != null) 9887 if (handlerClassifiedInfoUpdate != null)
9489 handlerClassifiedInfoUpdate( 9888 handlerClassifiedInfoUpdate(
9490 classifiedInfoUpdate.Data.ClassifiedID, 9889 classifiedInfoUpdate.Data.ClassifiedID,
@@ -9516,7 +9915,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9516 } 9915 }
9517 #endregion 9916 #endregion
9518 9917
9519 handlerClassifiedDelete = OnClassifiedDelete; 9918 ClassifiedDelete handlerClassifiedDelete = OnClassifiedDelete;
9520 if (handlerClassifiedDelete != null) 9919 if (handlerClassifiedDelete != null)
9521 handlerClassifiedDelete( 9920 handlerClassifiedDelete(
9522 classifiedDelete.Data.ClassifiedID, 9921 classifiedDelete.Data.ClassifiedID,
@@ -9536,7 +9935,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9536 } 9935 }
9537 #endregion 9936 #endregion
9538 9937
9539 handlerClassifiedGodDelete = OnClassifiedGodDelete; 9938 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
9540 if (handlerClassifiedGodDelete != null) 9939 if (handlerClassifiedGodDelete != null)
9541 handlerClassifiedGodDelete( 9940 handlerClassifiedGodDelete(
9542 classifiedGodDelete.Data.ClassifiedID, 9941 classifiedGodDelete.Data.ClassifiedID,
@@ -9556,7 +9955,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9556 } 9955 }
9557 #endregion 9956 #endregion
9558 9957
9559 handlerEventGodDelete = OnEventGodDelete; 9958 EventGodDelete handlerEventGodDelete = OnEventGodDelete;
9560 if (handlerEventGodDelete != null) 9959 if (handlerEventGodDelete != null)
9561 handlerEventGodDelete( 9960 handlerEventGodDelete(
9562 eventGodDelete.EventData.EventID, 9961 eventGodDelete.EventData.EventID,
@@ -9581,7 +9980,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9581 } 9980 }
9582 #endregion 9981 #endregion
9583 9982
9584 handlerEventNotificationAddRequest = OnEventNotificationAddRequest; 9983 EventNotificationAddRequest handlerEventNotificationAddRequest = OnEventNotificationAddRequest;
9585 if (handlerEventNotificationAddRequest != null) 9984 if (handlerEventNotificationAddRequest != null)
9586 handlerEventNotificationAddRequest( 9985 handlerEventNotificationAddRequest(
9587 eventNotificationAdd.EventData.EventID, this); 9986 eventNotificationAdd.EventData.EventID, this);
@@ -9600,7 +9999,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9600 } 9999 }
9601 #endregion 10000 #endregion
9602 10001
9603 handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest; 10002 EventNotificationRemoveRequest handlerEventNotificationRemoveRequest = OnEventNotificationRemoveRequest;
9604 if (handlerEventNotificationRemoveRequest != null) 10003 if (handlerEventNotificationRemoveRequest != null)
9605 handlerEventNotificationRemoveRequest( 10004 handlerEventNotificationRemoveRequest(
9606 eventNotificationRemove.EventData.EventID, this); 10005 eventNotificationRemove.EventData.EventID, this);
@@ -9618,7 +10017,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9618 } 10017 }
9619 #endregion 10018 #endregion
9620 10019
9621 handlerRetrieveInstantMessages = OnRetrieveInstantMessages; 10020 RetrieveInstantMessages handlerRetrieveInstantMessages = OnRetrieveInstantMessages;
9622 if (handlerRetrieveInstantMessages != null) 10021 if (handlerRetrieveInstantMessages != null)
9623 handlerRetrieveInstantMessages(this); 10022 handlerRetrieveInstantMessages(this);
9624 break; 10023 break;
@@ -9636,7 +10035,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9636 } 10035 }
9637 #endregion 10036 #endregion
9638 10037
9639 handlerPickDelete = OnPickDelete; 10038 PickDelete handlerPickDelete = OnPickDelete;
9640 if (handlerPickDelete != null) 10039 if (handlerPickDelete != null)
9641 handlerPickDelete(this, pickDelete.Data.PickID); 10040 handlerPickDelete(this, pickDelete.Data.PickID);
9642 break; 10041 break;
@@ -9653,7 +10052,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9653 } 10052 }
9654 #endregion 10053 #endregion
9655 10054
9656 handlerPickGodDelete = OnPickGodDelete; 10055 PickGodDelete handlerPickGodDelete = OnPickGodDelete;
9657 if (handlerPickGodDelete != null) 10056 if (handlerPickGodDelete != null)
9658 handlerPickGodDelete(this, 10057 handlerPickGodDelete(this,
9659 pickGodDelete.AgentData.AgentID, 10058 pickGodDelete.AgentData.AgentID,
@@ -9673,7 +10072,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9673 } 10072 }
9674 #endregion 10073 #endregion
9675 10074
9676 handlerPickInfoUpdate = OnPickInfoUpdate; 10075 PickInfoUpdate handlerPickInfoUpdate = OnPickInfoUpdate;
9677 if (handlerPickInfoUpdate != null) 10076 if (handlerPickInfoUpdate != null)
9678 handlerPickInfoUpdate(this, 10077 handlerPickInfoUpdate(this,
9679 pickInfoUpdate.Data.PickID, 10078 pickInfoUpdate.Data.PickID,
@@ -9698,7 +10097,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9698 } 10097 }
9699 #endregion 10098 #endregion
9700 10099
9701 handlerAvatarNotesUpdate = OnAvatarNotesUpdate; 10100 AvatarNotesUpdate handlerAvatarNotesUpdate = OnAvatarNotesUpdate;
9702 if (handlerAvatarNotesUpdate != null) 10101 if (handlerAvatarNotesUpdate != null)
9703 handlerAvatarNotesUpdate(this, 10102 handlerAvatarNotesUpdate(this,
9704 avatarNotesUpdate.Data.TargetID, 10103 avatarNotesUpdate.Data.TargetID,
@@ -9715,7 +10114,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9715 PlacesQueryPacket placesQueryPacket = 10114 PlacesQueryPacket placesQueryPacket =
9716 (PlacesQueryPacket)Pack; 10115 (PlacesQueryPacket)Pack;
9717 10116
9718 handlerPlacesQuery = OnPlacesQuery; 10117 PlacesQuery handlerPlacesQuery = OnPlacesQuery;
9719 10118
9720 if (handlerPlacesQuery != null) 10119 if (handlerPlacesQuery != null)
9721 handlerPlacesQuery(placesQueryPacket.AgentData.QueryID, 10120 handlerPlacesQuery(placesQueryPacket.AgentData.QueryID,
@@ -9769,304 +10168,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9769 //shape.Textures = ntex; 10168 //shape.Textures = ntex;
9770 return shape; 10169 return shape;
9771 } 10170 }
9772 10171
9773 /// <summary>
9774 /// Send the client an Estate message blue box pop-down with a single OK button
9775 /// </summary>
9776 /// <param name="FromAvatarID"></param>
9777 /// <param name="fromSessionID"></param>
9778 /// <param name="FromAvatarName"></param>
9779 /// <param name="Message"></param>
9780 public void SendBlueBoxMessage(UUID FromAvatarID, String FromAvatarName, String Message)
9781 {
9782 if (!ChildAgentStatus())
9783 SendInstantMessage(new GridInstantMessage(null, FromAvatarID, FromAvatarName, AgentId, 1, Message, false, new Vector3()));
9784
9785 //SendInstantMessage(FromAvatarID, fromSessionID, Message, AgentId, SessionId, FromAvatarName, (byte)21,(uint) Util.UnixTimeSinceEpoch());
9786 }
9787
9788 public void SendLogoutPacket()
9789 {
9790 // I know this is a bit of a hack, however there are times when you don't
9791 // want to send this, but still need to do the rest of the shutdown process
9792 // this method gets called from the packet server.. which makes it practically
9793 // impossible to do any other way.
9794
9795 if (m_SendLogoutPacketWhenClosing)
9796 {
9797 LogoutReplyPacket logReply = (LogoutReplyPacket)PacketPool.Instance.GetPacket(PacketType.LogoutReply);
9798 // TODO: don't create new blocks if recycling an old packet
9799 logReply.AgentData.AgentID = AgentId;
9800 logReply.AgentData.SessionID = SessionId;
9801 logReply.InventoryData = new LogoutReplyPacket.InventoryDataBlock[1];
9802 logReply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock();
9803 logReply.InventoryData[0].ItemID = UUID.Zero;
9804
9805 OutPacket(logReply, ThrottleOutPacketType.Task);
9806 }
9807 }
9808
9809 public void SendHealth(float health)
9810 {
9811 HealthMessagePacket healthpacket = (HealthMessagePacket)PacketPool.Instance.GetPacket(PacketType.HealthMessage);
9812 healthpacket.HealthData.Health = health;
9813 OutPacket(healthpacket, ThrottleOutPacketType.Task);
9814 }
9815
9816 public void SendAgentOnline(UUID[] agentIDs)
9817 {
9818 OnlineNotificationPacket onp = new OnlineNotificationPacket();
9819 OnlineNotificationPacket.AgentBlockBlock[] onpb = new OnlineNotificationPacket.AgentBlockBlock[agentIDs.Length];
9820 for (int i = 0; i < agentIDs.Length; i++)
9821 {
9822 OnlineNotificationPacket.AgentBlockBlock onpbl = new OnlineNotificationPacket.AgentBlockBlock();
9823 onpbl.AgentID = agentIDs[i];
9824 onpb[i] = onpbl;
9825 }
9826 onp.AgentBlock = onpb;
9827 onp.Header.Reliable = true;
9828 OutPacket(onp, ThrottleOutPacketType.Task);
9829 }
9830
9831 public void SendAgentOffline(UUID[] agentIDs)
9832 {
9833 OfflineNotificationPacket offp = new OfflineNotificationPacket();
9834 OfflineNotificationPacket.AgentBlockBlock[] offpb = new OfflineNotificationPacket.AgentBlockBlock[agentIDs.Length];
9835 for (int i = 0; i < agentIDs.Length; i++)
9836 {
9837 OfflineNotificationPacket.AgentBlockBlock onpbl = new OfflineNotificationPacket.AgentBlockBlock();
9838 onpbl.AgentID = agentIDs[i];
9839 offpb[i] = onpbl;
9840 }
9841 offp.AgentBlock = offpb;
9842 offp.Header.Reliable = true;
9843 OutPacket(offp, ThrottleOutPacketType.Task);
9844 }
9845
9846 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
9847 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
9848 {
9849 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
9850 avatarSitResponse.SitObject.ID = TargetID;
9851 if (CameraAtOffset != Vector3.Zero)
9852 {
9853 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
9854 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
9855 }
9856 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
9857 avatarSitResponse.SitTransform.AutoPilot = autopilot;
9858 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
9859 avatarSitResponse.SitTransform.SitRotation = SitOrientation;
9860
9861 OutPacket(avatarSitResponse, ThrottleOutPacketType.Task);
9862 }
9863
9864 public void SendAdminResponse(UUID Token, uint AdminLevel)
9865 {
9866 GrantGodlikePowersPacket respondPacket = new GrantGodlikePowersPacket();
9867 GrantGodlikePowersPacket.GrantDataBlock gdb = new GrantGodlikePowersPacket.GrantDataBlock();
9868 GrantGodlikePowersPacket.AgentDataBlock adb = new GrantGodlikePowersPacket.AgentDataBlock();
9869
9870 adb.AgentID = AgentId;
9871 adb.SessionID = SessionId; // More security
9872 gdb.GodLevel = (byte)AdminLevel;
9873 gdb.Token = Token;
9874 //respondPacket.AgentData = (GrantGodlikePowersPacket.AgentDataBlock)ablock;
9875 respondPacket.GrantData = gdb;
9876 respondPacket.AgentData = adb;
9877 OutPacket(respondPacket, ThrottleOutPacketType.Task);
9878 }
9879
9880 public void SendGroupMembership(GroupMembershipData[] GroupMembership)
9881 {
9882 m_groupPowers.Clear();
9883
9884 AgentGroupDataUpdatePacket Groupupdate = new AgentGroupDataUpdatePacket();
9885 AgentGroupDataUpdatePacket.GroupDataBlock[] Groups = new AgentGroupDataUpdatePacket.GroupDataBlock[GroupMembership.Length];
9886 for (int i = 0; i < GroupMembership.Length; i++)
9887 {
9888 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
9889
9890 AgentGroupDataUpdatePacket.GroupDataBlock Group = new AgentGroupDataUpdatePacket.GroupDataBlock();
9891 Group.AcceptNotices = GroupMembership[i].AcceptNotices;
9892 Group.Contribution = GroupMembership[i].Contribution;
9893 Group.GroupID = GroupMembership[i].GroupID;
9894 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
9895 Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName);
9896 Group.GroupPowers = GroupMembership[i].GroupPowers;
9897 Groups[i] = Group;
9898
9899
9900 }
9901 Groupupdate.GroupData = Groups;
9902 Groupupdate.AgentData = new AgentGroupDataUpdatePacket.AgentDataBlock();
9903 Groupupdate.AgentData.AgentID = AgentId;
9904 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
9905
9906 try
9907 {
9908 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
9909 if (eq != null)
9910 {
9911 eq.GroupMembership(Groupupdate, this.AgentId);
9912 }
9913 }
9914 catch (Exception ex)
9915 {
9916 m_log.Error("Unable to send group membership data via eventqueue - exception: " + ex.ToString());
9917 m_log.Warn("sending group membership data via UDP");
9918 OutPacket(Groupupdate, ThrottleOutPacketType.Task);
9919 }
9920 }
9921
9922
9923 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
9924 {
9925 UUIDGroupNameReplyPacket pack = new UUIDGroupNameReplyPacket();
9926 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
9927 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
9928 uidnamebloc.ID = groupLLUID;
9929 uidnamebloc.GroupName = Utils.StringToBytes(GroupName);
9930 uidnameblock[0] = uidnamebloc;
9931 pack.UUIDNameBlock = uidnameblock;
9932 OutPacket(pack, ThrottleOutPacketType.Task);
9933 }
9934
9935 public void SendLandStatReply(uint reportType, uint requestFlags, uint resultCount, LandStatReportItem[] lsrpia)
9936 {
9937 LandStatReplyPacket lsrp = new LandStatReplyPacket();
9938 // LandStatReplyPacket.RequestDataBlock lsreqdpb = new LandStatReplyPacket.RequestDataBlock();
9939 LandStatReplyPacket.ReportDataBlock[] lsrepdba = new LandStatReplyPacket.ReportDataBlock[lsrpia.Length];
9940 //LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
9941 // lsrepdb.
9942 lsrp.RequestData.ReportType = reportType;
9943 lsrp.RequestData.RequestFlags = requestFlags;
9944 lsrp.RequestData.TotalObjectCount = resultCount;
9945 for (int i = 0; i < lsrpia.Length; i++)
9946 {
9947 LandStatReplyPacket.ReportDataBlock lsrepdb = new LandStatReplyPacket.ReportDataBlock();
9948 lsrepdb.LocationX = lsrpia[i].LocationX;
9949 lsrepdb.LocationY = lsrpia[i].LocationY;
9950 lsrepdb.LocationZ = lsrpia[i].LocationZ;
9951 lsrepdb.Score = lsrpia[i].Score;
9952 lsrepdb.TaskID = lsrpia[i].TaskID;
9953 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
9954 lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName);
9955 lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName);
9956 lsrepdba[i] = lsrepdb;
9957 }
9958 lsrp.ReportData = lsrepdba;
9959 OutPacket(lsrp, ThrottleOutPacketType.Task);
9960 }
9961
9962 public void SendScriptRunningReply(UUID objectID, UUID itemID, bool running)
9963 {
9964 ScriptRunningReplyPacket scriptRunningReply = new ScriptRunningReplyPacket();
9965 scriptRunningReply.Script.ObjectID = objectID;
9966 scriptRunningReply.Script.ItemID = itemID;
9967 scriptRunningReply.Script.Running = running;
9968
9969 OutPacket(scriptRunningReply, ThrottleOutPacketType.Task);
9970 }
9971
9972 public void SendAsset(AssetRequestToClient req)
9973 {
9974 //m_log.Debug("sending asset " + req.RequestAssetID);
9975 TransferInfoPacket Transfer = new TransferInfoPacket();
9976 Transfer.TransferInfo.ChannelType = 2;
9977 Transfer.TransferInfo.Status = 0;
9978 Transfer.TransferInfo.TargetType = 0;
9979 if (req.AssetRequestSource == 2)
9980 {
9981 Transfer.TransferInfo.Params = new byte[20];
9982 Array.Copy(req.RequestAssetID.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
9983 int assType = req.AssetInf.Type;
9984 Array.Copy(Utils.IntToBytes(assType), 0, Transfer.TransferInfo.Params, 16, 4);
9985 }
9986 else if (req.AssetRequestSource == 3)
9987 {
9988 Transfer.TransferInfo.Params = req.Params;
9989 // Transfer.TransferInfo.Params = new byte[100];
9990 //Array.Copy(req.RequestUser.AgentId.GetBytes(), 0, Transfer.TransferInfo.Params, 0, 16);
9991 //Array.Copy(req.RequestUser.SessionId.GetBytes(), 0, Transfer.TransferInfo.Params, 16, 16);
9992 }
9993 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
9994 Transfer.TransferInfo.TransferID = req.TransferRequestID;
9995 Transfer.Header.Zerocoded = true;
9996 OutPacket(Transfer, ThrottleOutPacketType.Asset);
9997
9998 if (req.NumPackets == 1)
9999 {
10000 TransferPacketPacket TransferPacket = new TransferPacketPacket();
10001 TransferPacket.TransferData.Packet = 0;
10002 TransferPacket.TransferData.ChannelType = 2;
10003 TransferPacket.TransferData.TransferID = req.TransferRequestID;
10004 TransferPacket.TransferData.Data = req.AssetInf.Data;
10005 TransferPacket.TransferData.Status = 1;
10006 TransferPacket.Header.Zerocoded = true;
10007 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
10008 }
10009 else
10010 {
10011 int processedLength = 0;
10012 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
10013 int packetNumber = 0;
10014
10015 while (processedLength < req.AssetInf.Data.Length)
10016 {
10017 TransferPacketPacket TransferPacket = new TransferPacketPacket();
10018 TransferPacket.TransferData.Packet = packetNumber;
10019 TransferPacket.TransferData.ChannelType = 2;
10020 TransferPacket.TransferData.TransferID = req.TransferRequestID;
10021
10022 int chunkSize = Math.Min(req.AssetInf.Data.Length - processedLength, maxChunkSize);
10023 byte[] chunk = new byte[chunkSize];
10024 Array.Copy(req.AssetInf.Data, processedLength, chunk, 0, chunk.Length);
10025
10026 TransferPacket.TransferData.Data = chunk;
10027
10028 // 0 indicates more packets to come, 1 indicates last packet
10029 if (req.AssetInf.Data.Length - processedLength > maxChunkSize)
10030 {
10031 TransferPacket.TransferData.Status = 0;
10032 }
10033 else
10034 {
10035 TransferPacket.TransferData.Status = 1;
10036 }
10037 TransferPacket.Header.Zerocoded = true;
10038 OutPacket(TransferPacket, ThrottleOutPacketType.Asset);
10039
10040 processedLength += chunkSize;
10041 packetNumber++;
10042 }
10043 }
10044 }
10045
10046 public void SendTexture(AssetBase TextureAsset)
10047 {
10048
10049 }
10050
10051 public ClientInfo GetClientInfo() 10172 public ClientInfo GetClientInfo()
10052 { 10173 {
10053 ClientInfo info = m_PacketHandler.GetClientInfo(); 10174 ClientInfo info = m_udpClient.GetClientInfo();
10054 10175
10055 info.userEP = m_userEndPoint; 10176 info.userEP = m_userEndPoint;
10056 info.proxyEP = m_proxyEndPoint; 10177 info.proxyEP = null;
10057 info.agentcircuit = new sAgentCircuitData(RequestClientInfo()); 10178 info.agentcircuit = new sAgentCircuitData(RequestClientInfo());
10058 10179
10059 return info; 10180 return info;
10060 } 10181 }
10061 10182
10062 public EndPoint GetClientEP() 10183 public void SetClientInfo(ClientInfo info)
10063 { 10184 {
10064 return m_userEndPoint; 10185 m_udpClient.SetClientInfo(info);
10065 } 10186 }
10066 10187
10067 public void SetClientInfo(ClientInfo info) 10188 public EndPoint GetClientEP()
10068 { 10189 {
10069 m_PacketHandler.SetClientInfo(info); 10190 return m_userEndPoint;
10070 } 10191 }
10071 10192
10072 #region Media Parcel Members 10193 #region Media Parcel Members
@@ -10101,7 +10222,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10101 10222
10102 #endregion 10223 #endregion
10103 10224
10104
10105 #region Camera 10225 #region Camera
10106 10226
10107 public void SendSetFollowCamProperties (UUID objectID, SortedDictionary<int, float> parameters) 10227 public void SendSetFollowCamProperties (UUID objectID, SortedDictionary<int, float> parameters)
@@ -10131,70 +10251,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10131 10251
10132 #endregion 10252 #endregion
10133 10253
10134 public void SendRegionHandle(UUID regionID, ulong handle) {
10135 RegionIDAndHandleReplyPacket reply = (RegionIDAndHandleReplyPacket)PacketPool.Instance.GetPacket(PacketType.RegionIDAndHandleReply);
10136 reply.ReplyBlock.RegionID = regionID;
10137 reply.ReplyBlock.RegionHandle = handle;
10138 OutPacket(reply, ThrottleOutPacketType.Land);
10139 }
10140
10141 public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y)
10142 {
10143 ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply);
10144 reply.AgentData.AgentID = m_agentId;
10145 reply.Data.ParcelID = parcelID;
10146 reply.Data.OwnerID = land.OwnerID;
10147 reply.Data.Name = Utils.StringToBytes(land.Name);
10148 reply.Data.Desc = Utils.StringToBytes(land.Description);
10149 reply.Data.ActualArea = land.Area;
10150 reply.Data.BillableArea = land.Area; // TODO: what is this?
10151
10152 // Bit 0: Mature, bit 7: on sale, other bits: no idea
10153 reply.Data.Flags = (byte)(
10154 ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) +
10155 ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0));
10156
10157 Vector3 pos = land.UserLocation;
10158 if (pos.Equals(Vector3.Zero))
10159 {
10160 pos = (land.AABBMax + land.AABBMin) * 0.5f;
10161 }
10162 reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x;
10163 reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y;
10164 reply.Data.GlobalZ = pos.Z;
10165 reply.Data.SimName = Utils.StringToBytes(info.RegionName);
10166 reply.Data.SnapshotID = land.SnapshotID;
10167 reply.Data.Dwell = land.Dwell;
10168 reply.Data.SalePrice = land.SalePrice;
10169 reply.Data.AuctionID = (int)land.AuctionID;
10170
10171 OutPacket(reply, ThrottleOutPacketType.Land);
10172 }
10173
10174 public void SendScriptTeleportRequest(string objName, string simName, Vector3 pos, Vector3 lookAt)
10175 {
10176 ScriptTeleportRequestPacket packet = (ScriptTeleportRequestPacket)PacketPool.Instance.GetPacket(PacketType.ScriptTeleportRequest);
10177
10178 packet.Data.ObjectName = Utils.StringToBytes(objName);
10179 packet.Data.SimName = Utils.StringToBytes(simName);
10180 packet.Data.SimPosition = pos;
10181 packet.Data.LookAt = lookAt;
10182
10183 OutPacket(packet, ThrottleOutPacketType.Task);
10184 }
10185
10186 public void SetClientOption(string option, string value) 10254 public void SetClientOption(string option, string value)
10187 { 10255 {
10188 switch (option) 10256 switch (option)
10189 { 10257 {
10190 case "ReliableIsImportant": 10258 default:
10191 bool val; 10259 break;
10192
10193 if (bool.TryParse(value, out val))
10194 m_PacketHandler.ReliableIsImportant = val;
10195 break;
10196 default:
10197 break;
10198 } 10260 }
10199 } 10261 }
10200 10262
@@ -10202,571 +10264,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10202 { 10264 {
10203 switch (option) 10265 switch (option)
10204 { 10266 {
10205 case "ReliableIsImportant":
10206 return m_PacketHandler.ReliableIsImportant.ToString();
10207
10208 default: 10267 default:
10209 break; 10268 break;
10210 } 10269 }
10211 return string.Empty; 10270 return string.Empty;
10212 } 10271 }
10213 10272
10214 public void SendDirPlacesReply(UUID queryID, DirPlacesReplyData[] data)
10215 {
10216 DirPlacesReplyPacket packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply);
10217
10218 packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock();
10219
10220 packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1];
10221 packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock();
10222
10223 packet.QueryReplies =
10224 new DirPlacesReplyPacket.QueryRepliesBlock[data.Length];
10225
10226 packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[
10227 data.Length];
10228
10229 packet.AgentData.AgentID = AgentId;
10230
10231 packet.QueryData[0].QueryID = queryID;
10232
10233 int i = 0;
10234 foreach (DirPlacesReplyData d in data)
10235 {
10236 packet.QueryReplies[i] =
10237 new DirPlacesReplyPacket.QueryRepliesBlock();
10238 packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock();
10239 packet.QueryReplies[i].ParcelID = d.parcelID;
10240 packet.QueryReplies[i].Name = Utils.StringToBytes(d.name);
10241 packet.QueryReplies[i].ForSale = d.forSale;
10242 packet.QueryReplies[i].Auction = d.auction;
10243 packet.QueryReplies[i].Dwell = d.dwell;
10244 packet.StatusData[i].Status = d.Status;
10245 i++;
10246 }
10247
10248 OutPacket(packet, ThrottleOutPacketType.Task);
10249 }
10250
10251 public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data)
10252 {
10253 DirPeopleReplyPacket packet = (DirPeopleReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPeopleReply);
10254
10255 packet.AgentData = new DirPeopleReplyPacket.AgentDataBlock();
10256 packet.AgentData.AgentID = AgentId;
10257
10258 packet.QueryData = new DirPeopleReplyPacket.QueryDataBlock();
10259 packet.QueryData.QueryID = queryID;
10260
10261 packet.QueryReplies = new DirPeopleReplyPacket.QueryRepliesBlock[
10262 data.Length];
10263
10264 int i = 0;
10265 foreach (DirPeopleReplyData d in data)
10266 {
10267 packet.QueryReplies[i] = new DirPeopleReplyPacket.QueryRepliesBlock();
10268 packet.QueryReplies[i].AgentID = d.agentID;
10269 packet.QueryReplies[i].FirstName =
10270 Utils.StringToBytes(d.firstName);
10271 packet.QueryReplies[i].LastName =
10272 Utils.StringToBytes(d.lastName);
10273 packet.QueryReplies[i].Group =
10274 Utils.StringToBytes(d.group);
10275 packet.QueryReplies[i].Online = d.online;
10276 packet.QueryReplies[i].Reputation = d.reputation;
10277 i++;
10278 }
10279
10280 OutPacket(packet, ThrottleOutPacketType.Task);
10281 }
10282
10283 public void SendDirEventsReply(UUID queryID, DirEventsReplyData[] data)
10284 {
10285 DirEventsReplyPacket packet = (DirEventsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirEventsReply);
10286
10287 packet.AgentData = new DirEventsReplyPacket.AgentDataBlock();
10288 packet.AgentData.AgentID = AgentId;
10289
10290 packet.QueryData = new DirEventsReplyPacket.QueryDataBlock();
10291 packet.QueryData.QueryID = queryID;
10292
10293 packet.QueryReplies = new DirEventsReplyPacket.QueryRepliesBlock[
10294 data.Length];
10295
10296 packet.StatusData = new DirEventsReplyPacket.StatusDataBlock[
10297 data.Length];
10298
10299 int i = 0;
10300 foreach (DirEventsReplyData d in data)
10301 {
10302 packet.QueryReplies[i] = new DirEventsReplyPacket.QueryRepliesBlock();
10303 packet.StatusData[i] = new DirEventsReplyPacket.StatusDataBlock();
10304 packet.QueryReplies[i].OwnerID = d.ownerID;
10305 packet.QueryReplies[i].Name =
10306 Utils.StringToBytes(d.name);
10307 packet.QueryReplies[i].EventID = d.eventID;
10308 packet.QueryReplies[i].Date =
10309 Utils.StringToBytes(d.date);
10310 packet.QueryReplies[i].UnixTime = d.unixTime;
10311 packet.QueryReplies[i].EventFlags = d.eventFlags;
10312 packet.StatusData[i].Status = d.Status;
10313 i++;
10314 }
10315
10316 OutPacket(packet, ThrottleOutPacketType.Task);
10317 }
10318
10319 public void SendDirGroupsReply(UUID queryID, DirGroupsReplyData[] data)
10320 {
10321 DirGroupsReplyPacket packet = (DirGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirGroupsReply);
10322
10323 packet.AgentData = new DirGroupsReplyPacket.AgentDataBlock();
10324 packet.AgentData.AgentID = AgentId;
10325
10326 packet.QueryData = new DirGroupsReplyPacket.QueryDataBlock();
10327 packet.QueryData.QueryID = queryID;
10328
10329 packet.QueryReplies = new DirGroupsReplyPacket.QueryRepliesBlock[
10330 data.Length];
10331
10332 int i = 0;
10333 foreach (DirGroupsReplyData d in data)
10334 {
10335 packet.QueryReplies[i] = new DirGroupsReplyPacket.QueryRepliesBlock();
10336 packet.QueryReplies[i].GroupID = d.groupID;
10337 packet.QueryReplies[i].GroupName =
10338 Utils.StringToBytes(d.groupName);
10339 packet.QueryReplies[i].Members = d.members;
10340 packet.QueryReplies[i].SearchOrder = d.searchOrder;
10341 i++;
10342 }
10343
10344 OutPacket(packet, ThrottleOutPacketType.Task);
10345 }
10346
10347 public void SendDirClassifiedReply(UUID queryID, DirClassifiedReplyData[] data)
10348 {
10349 DirClassifiedReplyPacket packet = (DirClassifiedReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirClassifiedReply);
10350
10351 packet.AgentData = new DirClassifiedReplyPacket.AgentDataBlock();
10352 packet.AgentData.AgentID = AgentId;
10353
10354 packet.QueryData = new DirClassifiedReplyPacket.QueryDataBlock();
10355 packet.QueryData.QueryID = queryID;
10356
10357 packet.QueryReplies = new DirClassifiedReplyPacket.QueryRepliesBlock[
10358 data.Length];
10359 packet.StatusData = new DirClassifiedReplyPacket.StatusDataBlock[
10360 data.Length];
10361
10362 int i = 0;
10363 foreach (DirClassifiedReplyData d in data)
10364 {
10365 packet.QueryReplies[i] = new DirClassifiedReplyPacket.QueryRepliesBlock();
10366 packet.StatusData[i] = new DirClassifiedReplyPacket.StatusDataBlock();
10367 packet.QueryReplies[i].ClassifiedID = d.classifiedID;
10368 packet.QueryReplies[i].Name =
10369 Utils.StringToBytes(d.name);
10370 packet.QueryReplies[i].ClassifiedFlags = d.classifiedFlags;
10371 packet.QueryReplies[i].CreationDate = d.creationDate;
10372 packet.QueryReplies[i].ExpirationDate = d.expirationDate;
10373 packet.QueryReplies[i].PriceForListing = d.price;
10374 packet.StatusData[i].Status = d.Status;
10375 i++;
10376 }
10377
10378 OutPacket(packet, ThrottleOutPacketType.Task);
10379 }
10380
10381 public void SendDirLandReply(UUID queryID, DirLandReplyData[] data)
10382 {
10383 DirLandReplyPacket packet = (DirLandReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirLandReply);
10384
10385 packet.AgentData = new DirLandReplyPacket.AgentDataBlock();
10386 packet.AgentData.AgentID = AgentId;
10387
10388 packet.QueryData = new DirLandReplyPacket.QueryDataBlock();
10389 packet.QueryData.QueryID = queryID;
10390
10391 packet.QueryReplies = new DirLandReplyPacket.QueryRepliesBlock[
10392 data.Length];
10393
10394 int i = 0;
10395 foreach (DirLandReplyData d in data)
10396 {
10397 packet.QueryReplies[i] = new DirLandReplyPacket.QueryRepliesBlock();
10398 packet.QueryReplies[i].ParcelID = d.parcelID;
10399 packet.QueryReplies[i].Name =
10400 Utils.StringToBytes(d.name);
10401 packet.QueryReplies[i].Auction = d.auction;
10402 packet.QueryReplies[i].ForSale = d.forSale;
10403 packet.QueryReplies[i].SalePrice = d.salePrice;
10404 packet.QueryReplies[i].ActualArea = d.actualArea;
10405 i++;
10406 }
10407
10408 OutPacket(packet, ThrottleOutPacketType.Task);
10409 }
10410
10411 public void SendDirPopularReply(UUID queryID, DirPopularReplyData[] data)
10412 {
10413 DirPopularReplyPacket packet = (DirPopularReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPopularReply);
10414
10415 packet.AgentData = new DirPopularReplyPacket.AgentDataBlock();
10416 packet.AgentData.AgentID = AgentId;
10417
10418 packet.QueryData = new DirPopularReplyPacket.QueryDataBlock();
10419 packet.QueryData.QueryID = queryID;
10420
10421 packet.QueryReplies = new DirPopularReplyPacket.QueryRepliesBlock[
10422 data.Length];
10423
10424 int i = 0;
10425 foreach (DirPopularReplyData d in data)
10426 {
10427 packet.QueryReplies[i] = new DirPopularReplyPacket.QueryRepliesBlock();
10428 packet.QueryReplies[i].ParcelID = d.parcelID;
10429 packet.QueryReplies[i].Name =
10430 Utils.StringToBytes(d.name);
10431 packet.QueryReplies[i].Dwell = d.dwell;
10432 i++;
10433 }
10434
10435 OutPacket(packet, ThrottleOutPacketType.Task);
10436 }
10437
10438 public void SendEventInfoReply(EventData data)
10439 {
10440 EventInfoReplyPacket packet = (EventInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.EventInfoReply);
10441
10442 packet.AgentData = new EventInfoReplyPacket.AgentDataBlock();
10443 packet.AgentData.AgentID = AgentId;
10444
10445 packet.EventData = new EventInfoReplyPacket.EventDataBlock();
10446 packet.EventData.EventID = data.eventID;
10447 packet.EventData.Creator = Utils.StringToBytes(data.creator);
10448 packet.EventData.Name = Utils.StringToBytes(data.name);
10449 packet.EventData.Category = Utils.StringToBytes(data.category);
10450 packet.EventData.Desc = Utils.StringToBytes(data.description);
10451 packet.EventData.Date = Utils.StringToBytes(data.date);
10452 packet.EventData.DateUTC = data.dateUTC;
10453 packet.EventData.Duration = data.duration;
10454 packet.EventData.Cover = data.cover;
10455 packet.EventData.Amount = data.amount;
10456 packet.EventData.SimName = Utils.StringToBytes(data.simName);
10457 packet.EventData.GlobalPos = new Vector3d(data.globalPos);
10458 packet.EventData.EventFlags = data.eventFlags;
10459
10460 OutPacket(packet, ThrottleOutPacketType.Task);
10461 }
10462
10463 public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags)
10464 {
10465 MapItemReplyPacket mirplk = new MapItemReplyPacket();
10466 mirplk.AgentData.AgentID = AgentId;
10467 mirplk.RequestData.ItemType = mapitemtype;
10468 mirplk.Data = new MapItemReplyPacket.DataBlock[replies.Length];
10469 for (int i = 0; i < replies.Length; i++)
10470 {
10471 MapItemReplyPacket.DataBlock mrdata = new MapItemReplyPacket.DataBlock();
10472 mrdata.X = replies[i].x;
10473 mrdata.Y = replies[i].y;
10474 mrdata.ID = replies[i].id;
10475 mrdata.Extra = replies[i].Extra;
10476 mrdata.Extra2 = replies[i].Extra2;
10477 mrdata.Name = Utils.StringToBytes(replies[i].name);
10478 mirplk.Data[i] = mrdata;
10479 }
10480 //m_log.Debug(mirplk.ToString());
10481 OutPacket(mirplk, ThrottleOutPacketType.Task);
10482
10483 }
10484
10485 public void SendOfferCallingCard(UUID srcID, UUID transactionID)
10486 {
10487 // a bit special, as this uses AgentID to store the source instead
10488 // of the destination. The destination (the receiver) goes into destID
10489 OfferCallingCardPacket p = (OfferCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.OfferCallingCard);
10490 p.AgentData.AgentID = srcID;
10491 p.AgentData.SessionID = UUID.Zero;
10492 p.AgentBlock.DestID = AgentId;
10493 p.AgentBlock.TransactionID = transactionID;
10494 OutPacket(p, ThrottleOutPacketType.Task);
10495 }
10496
10497 public void SendAcceptCallingCard(UUID transactionID)
10498 {
10499 AcceptCallingCardPacket p = (AcceptCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.AcceptCallingCard);
10500 p.AgentData.AgentID = AgentId;
10501 p.AgentData.SessionID = UUID.Zero;
10502 p.FolderData = new AcceptCallingCardPacket.FolderDataBlock[1];
10503 p.FolderData[0] = new AcceptCallingCardPacket.FolderDataBlock();
10504 p.FolderData[0].FolderID = UUID.Zero;
10505 OutPacket(p, ThrottleOutPacketType.Task);
10506 }
10507
10508 public void SendDeclineCallingCard(UUID transactionID)
10509 {
10510 DeclineCallingCardPacket p = (DeclineCallingCardPacket)PacketPool.Instance.GetPacket(PacketType.DeclineCallingCard);
10511 p.AgentData.AgentID = AgentId;
10512 p.AgentData.SessionID = UUID.Zero;
10513 p.TransactionBlock.TransactionID = transactionID;
10514 OutPacket(p, ThrottleOutPacketType.Task);
10515 }
10516
10517 public void SendTerminateFriend(UUID exFriendID)
10518 {
10519 TerminateFriendshipPacket p = (TerminateFriendshipPacket)PacketPool.Instance.GetPacket(PacketType.TerminateFriendship);
10520 p.AgentData.AgentID = AgentId;
10521 p.AgentData.SessionID = SessionId;
10522 p.ExBlock.OtherID = exFriendID;
10523 OutPacket(p, ThrottleOutPacketType.Task);
10524 }
10525
10526 public void SendAvatarGroupsReply(UUID avatarID, GroupMembershipData[] data)
10527 {
10528 AvatarGroupsReplyPacket p = (AvatarGroupsReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarGroupsReply);
10529
10530 p.AgentData = new AvatarGroupsReplyPacket.AgentDataBlock();
10531 p.AgentData.AgentID = AgentId;
10532 p.AgentData.AvatarID = avatarID;
10533
10534 p.GroupData = new AvatarGroupsReplyPacket.GroupDataBlock[data.Length];
10535 int i = 0;
10536 foreach (GroupMembershipData m in data)
10537 {
10538 p.GroupData[i] = new AvatarGroupsReplyPacket.GroupDataBlock();
10539 p.GroupData[i].GroupPowers = m.GroupPowers;
10540 p.GroupData[i].AcceptNotices = m.AcceptNotices;
10541 p.GroupData[i].GroupTitle = Utils.StringToBytes(m.GroupTitle);
10542 p.GroupData[i].GroupID = m.GroupID;
10543 p.GroupData[i].GroupName = Utils.StringToBytes(m.GroupName);
10544 p.GroupData[i].GroupInsigniaID = m.GroupPicture;
10545 i++;
10546 }
10547
10548 p.NewGroupData = new AvatarGroupsReplyPacket.NewGroupDataBlock();
10549 p.NewGroupData.ListInProfile = true;
10550
10551 OutPacket(p, ThrottleOutPacketType.Task);
10552 }
10553
10554 public void SendJoinGroupReply(UUID groupID, bool success)
10555 {
10556 JoinGroupReplyPacket p = (JoinGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.JoinGroupReply);
10557
10558 p.AgentData = new JoinGroupReplyPacket.AgentDataBlock();
10559 p.AgentData.AgentID = AgentId;
10560
10561 p.GroupData = new JoinGroupReplyPacket.GroupDataBlock();
10562 p.GroupData.GroupID = groupID;
10563 p.GroupData.Success = success;
10564
10565 OutPacket(p, ThrottleOutPacketType.Task);
10566 }
10567
10568 public void SendEjectGroupMemberReply(UUID agentID, UUID groupID, bool success)
10569 {
10570 EjectGroupMemberReplyPacket p = (EjectGroupMemberReplyPacket)PacketPool.Instance.GetPacket(PacketType.EjectGroupMemberReply);
10571
10572 p.AgentData = new EjectGroupMemberReplyPacket.AgentDataBlock();
10573 p.AgentData.AgentID = agentID;
10574
10575 p.GroupData = new EjectGroupMemberReplyPacket.GroupDataBlock();
10576 p.GroupData.GroupID = groupID;
10577
10578 p.EjectData = new EjectGroupMemberReplyPacket.EjectDataBlock();
10579 p.EjectData.Success = success;
10580
10581 OutPacket(p, ThrottleOutPacketType.Task);
10582 }
10583
10584 public void SendLeaveGroupReply(UUID groupID, bool success)
10585 {
10586 LeaveGroupReplyPacket p = (LeaveGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.LeaveGroupReply);
10587
10588 p.AgentData = new LeaveGroupReplyPacket.AgentDataBlock();
10589 p.AgentData.AgentID = AgentId;
10590
10591 p.GroupData = new LeaveGroupReplyPacket.GroupDataBlock();
10592 p.GroupData.GroupID = groupID;
10593 p.GroupData.Success = success;
10594
10595 OutPacket(p, ThrottleOutPacketType.Task);
10596 }
10597
10598 public void SendAvatarClassifiedReply(UUID targetID, UUID[] classifiedID, string[] name)
10599 {
10600 if (classifiedID.Length != name.Length)
10601 return;
10602
10603 AvatarClassifiedReplyPacket ac =
10604 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
10605 PacketType.AvatarClassifiedReply);
10606
10607 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
10608 ac.AgentData.AgentID = AgentId;
10609 ac.AgentData.TargetID = targetID;
10610
10611 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifiedID.Length];
10612 int i;
10613 for (i = 0 ; i < classifiedID.Length ; i++)
10614 {
10615 ac.Data[i].ClassifiedID = classifiedID[i];
10616 ac.Data[i].Name = Utils.StringToBytes(name[i]);
10617 }
10618
10619 OutPacket(ac, ThrottleOutPacketType.Task);
10620 }
10621
10622 public void SendClassifiedInfoReply(UUID classifiedID, UUID creatorID, uint creationDate, uint expirationDate, uint category, string name, string description, UUID parcelID, uint parentEstate, UUID snapshotID, string simName, Vector3 globalPos, string parcelName, byte classifiedFlags, int price)
10623 {
10624 ClassifiedInfoReplyPacket cr =
10625 (ClassifiedInfoReplyPacket)PacketPool.Instance.GetPacket(
10626 PacketType.ClassifiedInfoReply);
10627
10628 cr.AgentData = new ClassifiedInfoReplyPacket.AgentDataBlock();
10629 cr.AgentData.AgentID = AgentId;
10630
10631 cr.Data = new ClassifiedInfoReplyPacket.DataBlock();
10632 cr.Data.ClassifiedID = classifiedID;
10633 cr.Data.CreatorID = creatorID;
10634 cr.Data.CreationDate = creationDate;
10635 cr.Data.ExpirationDate = expirationDate;
10636 cr.Data.Category = category;
10637 cr.Data.Name = Utils.StringToBytes(name);
10638 cr.Data.Desc = Utils.StringToBytes(description);
10639 cr.Data.ParcelID = parcelID;
10640 cr.Data.ParentEstate = parentEstate;
10641 cr.Data.SnapshotID = snapshotID;
10642 cr.Data.SimName = Utils.StringToBytes(simName);
10643 cr.Data.PosGlobal = new Vector3d(globalPos);
10644 cr.Data.ParcelName = Utils.StringToBytes(parcelName);
10645 cr.Data.ClassifiedFlags = classifiedFlags;
10646 cr.Data.PriceForListing = price;
10647
10648 OutPacket(cr, ThrottleOutPacketType.Task);
10649 }
10650
10651 public void SendAgentDropGroup(UUID groupID)
10652 {
10653 AgentDropGroupPacket dg =
10654 (AgentDropGroupPacket)PacketPool.Instance.GetPacket(
10655 PacketType.AgentDropGroup);
10656
10657 dg.AgentData = new AgentDropGroupPacket.AgentDataBlock();
10658 dg.AgentData.AgentID = AgentId;
10659 dg.AgentData.GroupID = groupID;
10660
10661 OutPacket(dg, ThrottleOutPacketType.Task);
10662 }
10663
10664 public void SendAvatarNotesReply(UUID targetID, string text)
10665 {
10666 AvatarNotesReplyPacket an =
10667 (AvatarNotesReplyPacket)PacketPool.Instance.GetPacket(
10668 PacketType.AvatarNotesReply);
10669
10670 an.AgentData = new AvatarNotesReplyPacket.AgentDataBlock();
10671 an.AgentData.AgentID = AgentId;
10672
10673 an.Data = new AvatarNotesReplyPacket.DataBlock();
10674 an.Data.TargetID = targetID;
10675 an.Data.Notes = Utils.StringToBytes(text);
10676
10677 OutPacket(an, ThrottleOutPacketType.Task);
10678 }
10679
10680 public void SendAvatarPicksReply(UUID targetID, Dictionary<UUID, string> picks)
10681 {
10682 AvatarPicksReplyPacket ap =
10683 (AvatarPicksReplyPacket)PacketPool.Instance.GetPacket(
10684 PacketType.AvatarPicksReply);
10685
10686 ap.AgentData = new AvatarPicksReplyPacket.AgentDataBlock();
10687 ap.AgentData.AgentID = AgentId;
10688 ap.AgentData.TargetID = targetID;
10689
10690 ap.Data = new AvatarPicksReplyPacket.DataBlock[picks.Count];
10691
10692 int i = 0;
10693 foreach (KeyValuePair<UUID, string> pick in picks)
10694 {
10695 ap.Data[i] = new AvatarPicksReplyPacket.DataBlock();
10696 ap.Data[i].PickID = pick.Key;
10697 ap.Data[i].PickName = Utils.StringToBytes(pick.Value);
10698 i++;
10699 }
10700
10701 OutPacket(ap, ThrottleOutPacketType.Task);
10702 }
10703
10704 public void SendAvatarClassifiedReply(UUID targetID, Dictionary<UUID, string> classifieds)
10705 {
10706 AvatarClassifiedReplyPacket ac =
10707 (AvatarClassifiedReplyPacket)PacketPool.Instance.GetPacket(
10708 PacketType.AvatarClassifiedReply);
10709
10710 ac.AgentData = new AvatarClassifiedReplyPacket.AgentDataBlock();
10711 ac.AgentData.AgentID = AgentId;
10712 ac.AgentData.TargetID = targetID;
10713
10714 ac.Data = new AvatarClassifiedReplyPacket.DataBlock[classifieds.Count];
10715
10716 int i = 0;
10717 foreach (KeyValuePair<UUID, string> classified in classifieds)
10718 {
10719 ac.Data[i] = new AvatarClassifiedReplyPacket.DataBlock();
10720 ac.Data[i].ClassifiedID = classified.Key;
10721 ac.Data[i].Name = Utils.StringToBytes(classified.Value);
10722 i++;
10723 }
10724
10725 OutPacket(ac, ThrottleOutPacketType.Task);
10726 }
10727
10728 public void SendParcelDwellReply(int localID, UUID parcelID, float dwell)
10729 {
10730 ParcelDwellReplyPacket pd =
10731 (ParcelDwellReplyPacket)PacketPool.Instance.GetPacket(
10732 PacketType.ParcelDwellReply);
10733
10734 pd.AgentData = new ParcelDwellReplyPacket.AgentDataBlock();
10735 pd.AgentData.AgentID = AgentId;
10736
10737 pd.Data = new ParcelDwellReplyPacket.DataBlock();
10738 pd.Data.LocalID = localID;
10739 pd.Data.ParcelID = parcelID;
10740 pd.Data.Dwell = dwell;
10741
10742 OutPacket(pd, ThrottleOutPacketType.Land);
10743 }
10744
10745 public void SendUserInfoReply(bool imViaEmail, bool visible, string email)
10746 {
10747 UserInfoReplyPacket ur =
10748 (UserInfoReplyPacket)PacketPool.Instance.GetPacket(
10749 PacketType.UserInfoReply);
10750
10751 string Visible = "hidden";
10752 if (visible)
10753 Visible = "default";
10754
10755 ur.AgentData = new UserInfoReplyPacket.AgentDataBlock();
10756 ur.AgentData.AgentID = AgentId;
10757
10758 ur.UserData = new UserInfoReplyPacket.UserDataBlock();
10759 ur.UserData.IMViaEMail = imViaEmail;
10760 ur.UserData.DirectoryVisibility = Utils.StringToBytes(Visible);
10761 ur.UserData.EMail = Utils.StringToBytes(email);
10762
10763 OutPacket(ur, ThrottleOutPacketType.Task);
10764 }
10765
10766 public void KillEndDone() 10273 public void KillEndDone()
10767 { 10274 {
10768 KillPacket kp = new KillPacket(); 10275 m_udpClient.Shutdown();
10769 OutPacket(kp, ThrottleOutPacketType.Task | ThrottleOutPacketType.LowPriority);
10770 } 10276 }
10771 10277
10772 #region IClientCore 10278 #region IClientCore
@@ -10789,13 +10295,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10789 } 10295 }
10790 } 10296 }
10791 10297
10792 protected virtual void RegisterInterfaces()
10793 {
10794 RegisterInterface<IClientIM>(this);
10795 RegisterInterface<IClientChat>(this);
10796 RegisterInterface<IClientIPEndpoint>(this);
10797 }
10798
10799 public bool TryGet<T>(out T iface) 10298 public bool TryGet<T>(out T iface)
10800 { 10299 {
10801 if (m_clientInterfaces.ContainsKey(typeof(T))) 10300 if (m_clientInterfaces.ContainsKey(typeof(T)))
@@ -10843,78 +10342,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10843 } 10342 }
10844 } 10343 }
10845 10344
10846 public void SendCreateGroupReply(UUID groupID, bool success, string message)
10847 {
10848 CreateGroupReplyPacket createGroupReply = (CreateGroupReplyPacket)PacketPool.Instance.GetPacket(PacketType.CreateGroupReply);
10849
10850 createGroupReply.AgentData =
10851 new CreateGroupReplyPacket.AgentDataBlock();
10852 createGroupReply.ReplyData =
10853 new CreateGroupReplyPacket.ReplyDataBlock();
10854
10855 createGroupReply.AgentData.AgentID = AgentId;
10856 createGroupReply.ReplyData.GroupID = groupID;
10857
10858 createGroupReply.ReplyData.Success = success;
10859 createGroupReply.ReplyData.Message = Utils.StringToBytes(message);
10860 OutPacket(createGroupReply, ThrottleOutPacketType.Task);
10861 }
10862
10863 public void SendUseCachedMuteList()
10864 {
10865 UseCachedMuteListPacket useCachedMuteList = (UseCachedMuteListPacket)PacketPool.Instance.GetPacket(PacketType.UseCachedMuteList);
10866
10867 useCachedMuteList.AgentData = new UseCachedMuteListPacket.AgentDataBlock();
10868 useCachedMuteList.AgentData.AgentID = AgentId;
10869
10870 OutPacket(useCachedMuteList, ThrottleOutPacketType.Task);
10871 }
10872
10873 public void SendMuteListUpdate(string filename)
10874 {
10875 MuteListUpdatePacket muteListUpdate = (MuteListUpdatePacket)PacketPool.Instance.GetPacket(PacketType.MuteListUpdate);
10876
10877 muteListUpdate.MuteData = new MuteListUpdatePacket.MuteDataBlock();
10878 muteListUpdate.MuteData.AgentID = AgentId;
10879 muteListUpdate.MuteData.Filename = Utils.StringToBytes(filename);
10880
10881 OutPacket(muteListUpdate, ThrottleOutPacketType.Task);
10882 }
10883
10884 public void SendPickInfoReply(UUID pickID,UUID creatorID, bool topPick, UUID parcelID, string name, string desc, UUID snapshotID, string user, string originalName, string simName, Vector3 posGlobal, int sortOrder, bool enabled)
10885 {
10886 PickInfoReplyPacket pickInfoReply = (PickInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.PickInfoReply);
10887
10888 pickInfoReply.AgentData = new PickInfoReplyPacket.AgentDataBlock();
10889 pickInfoReply.AgentData.AgentID = AgentId;
10890
10891 pickInfoReply.Data = new PickInfoReplyPacket.DataBlock();
10892 pickInfoReply.Data.PickID = pickID;
10893 pickInfoReply.Data.CreatorID = creatorID;
10894 pickInfoReply.Data.TopPick = topPick;
10895 pickInfoReply.Data.ParcelID = parcelID;
10896 pickInfoReply.Data.Name = Utils.StringToBytes(name);
10897 pickInfoReply.Data.Desc = Utils.StringToBytes(desc);
10898 pickInfoReply.Data.SnapshotID = snapshotID;
10899 pickInfoReply.Data.User = Utils.StringToBytes(user);
10900 pickInfoReply.Data.OriginalName = Utils.StringToBytes(originalName);
10901 pickInfoReply.Data.SimName = Utils.StringToBytes(simName);
10902 pickInfoReply.Data.PosGlobal = new Vector3d(posGlobal);
10903 pickInfoReply.Data.SortOrder = sortOrder;
10904 pickInfoReply.Data.Enabled = enabled;
10905
10906 OutPacket(pickInfoReply, ThrottleOutPacketType.Task);
10907 }
10908
10909 public string Report() 10345 public string Report()
10910 { 10346 {
10911 LLPacketHandler handler = (LLPacketHandler) m_PacketHandler; 10347 return m_udpClient.GetStats();
10912 return handler.PacketQueue.GetStats();
10913 } 10348 }
10914 10349
10915 public string XReport(string uptime, string version) 10350 public string XReport(string uptime, string version)
10916 { 10351 {
10917 return ""; 10352 return String.Empty;
10918 } 10353 }
10919 10354
10920 public void MakeAssetRequest(TransferRequestPacket transferRequest) 10355 public void MakeAssetRequest(TransferRequestPacket transferRequest)
@@ -11003,7 +10438,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11003 return numPackets; 10438 return numPackets;
11004 } 10439 }
11005 10440
11006
11007 #region IClientIPEndpoint Members 10441 #region IClientIPEndpoint Members
11008 10442
11009 public IPAddress EndPoint 10443 public IPAddress EndPoint
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index cc290ed..343f537 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -172,7 +172,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
172 m_lastloopprocessed = DateTime.Now.Ticks; 172 m_lastloopprocessed = DateTime.Now.Ticks;
173 173
174 // This can happen during Close() 174 // This can happen during Close()
175 if (m_client == null || m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null) 175 if (m_client == null)
176 return false; 176 return false;
177 177
178 while ((imagereq = GetHighestPriorityImage()) != null) 178 while ((imagereq = GetHighestPriorityImage()) != null)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
deleted file mode 100644
index e98a360..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketHandler.cs
+++ /dev/null
@@ -1,870 +0,0 @@
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 OpenSimulator 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.Reflection;
30using System.Collections.Generic;
31using System.Net.Sockets;
32using System.Threading;
33using System.Timers;
34using OpenMetaverse;
35using OpenMetaverse.Packets;
36using log4net;
37using OpenSim.Framework;
38using Timer=System.Timers.Timer;
39
40namespace OpenSim.Region.ClientStack.LindenUDP
41{
42 public class LLPacketHandler : ILLPacketHandler
43 {
44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 //private int m_resentCount;
48
49 // Packet queues
50 //
51 LLPacketQueue m_PacketQueue;
52
53 public LLPacketQueue PacketQueue
54 {
55 get { return m_PacketQueue; }
56 }
57
58 // Timer to run stats and acks on
59 //
60 private Timer m_AckTimer = new Timer(250);
61
62 // A list of the packets we haven't acked yet
63 //
64 private List<uint> m_PendingAcks = new List<uint>();
65 private Dictionary<uint, uint> m_PendingAcksMap = new Dictionary<uint, uint>();
66
67 private Dictionary<uint, LLQueItem> m_NeedAck =
68 new Dictionary<uint, LLQueItem>();
69
70 /// <summary>
71 /// The number of milliseconds that can pass before a packet that needs an ack is resent.
72 /// </param>
73 private uint m_ResendTimeout = 4000;
74
75 public uint ResendTimeout
76 {
77 get { return m_ResendTimeout; }
78 set { m_ResendTimeout = value; }
79 }
80
81 private int m_MaxReliableResends = 3;
82
83 public int MaxReliableResends
84 {
85 get { return m_MaxReliableResends; }
86 set { m_MaxReliableResends = value; }
87 }
88
89 // Track duplicated packets. This uses a Dictionary. Both insertion
90 // and lookup are common operations and need to take advantage of
91 // the hashing. Expiration is less common and can be allowed the
92 // time for a linear scan.
93 //
94 private List<uint> m_alreadySeenList = new List<uint>();
95 private Dictionary<uint, int>m_alreadySeenTracker = new Dictionary<uint, int>();
96 private int m_alreadySeenWindow = 30000;
97 private int m_lastAlreadySeenCheck = Environment.TickCount & Int32.MaxValue;
98
99 // private Dictionary<uint, int> m_DupeTracker =
100 // new Dictionary<uint, int>();
101 // private uint m_DupeTrackerWindow = 30;
102 // private int m_DupeTrackerLastCheck = Environment.TickCount;
103
104 // Values for the SimStatsReporter
105 //
106 private int m_PacketsReceived = 0;
107 private int m_PacketsReceivedReported = 0;
108 private int m_PacketsSent = 0;
109 private int m_PacketsSentReported = 0;
110 private int m_UnackedBytes = 0;
111
112 private int m_LastResend = 0;
113
114 public int PacketsReceived
115 {
116 get { return m_PacketsReceived; }
117 }
118
119 public int PacketsReceivedReported
120 {
121 get { return m_PacketsReceivedReported; }
122 }
123
124 // The client we are working for
125 //
126 private IClientAPI m_Client;
127
128 // Some events
129 //
130 public event PacketStats OnPacketStats;
131 public event PacketDrop OnPacketDrop;
132 public event QueueEmpty OnQueueEmpty;
133
134
135 //private SynchronizeClientHandler m_SynchronizeClient = null;
136
137 public SynchronizeClientHandler SynchronizeClient
138 {
139 set { /* m_SynchronizeClient = value; */ }
140 }
141
142 // Packet sequencing
143 //
144 private uint m_Sequence = 0;
145 private object m_SequenceLock = new object();
146 private const int MAX_SEQUENCE = 0xFFFFFF;
147
148 // Packet dropping
149 //
150 List<PacketType> m_ImportantPackets = new List<PacketType>();
151 private bool m_ReliableIsImportant = false;
152
153 public bool ReliableIsImportant
154 {
155 get { return m_ReliableIsImportant; }
156 set { m_ReliableIsImportant = value; }
157 }
158
159 private int m_DropSafeTimeout;
160
161 LLPacketServer m_PacketServer;
162 private byte[] m_ZeroOutBuffer = new byte[4096];
163
164 ////////////////////////////////////////////////////////////////////
165
166 // Constructors
167 //
168 public LLPacketHandler(IClientAPI client, LLPacketServer server, ClientStackUserSettings userSettings)
169 {
170 m_Client = client;
171 m_PacketServer = server;
172 m_DropSafeTimeout = Environment.TickCount + 15000;
173
174 m_PacketQueue = new LLPacketQueue(client.AgentId, userSettings);
175
176 m_PacketQueue.OnQueueEmpty += TriggerOnQueueEmpty;
177
178 m_AckTimer.Elapsed += AckTimerElapsed;
179 m_AckTimer.Start();
180 }
181
182 public void Dispose()
183 {
184 m_AckTimer.Stop();
185 m_AckTimer.Close();
186
187 m_PacketQueue.Enqueue(null);
188 m_PacketQueue.Close();
189 m_Client = null;
190 }
191
192 // Send one packet. This actually doesn't send anything, it queues
193 // it. Designed to be fire-and-forget, but there is an optional
194 // notifier.
195 //
196 public void OutPacket(
197 Packet packet, ThrottleOutPacketType throttlePacketType)
198 {
199 OutPacket(packet, throttlePacketType, null);
200 }
201
202 public void OutPacket(
203 Packet packet, ThrottleOutPacketType throttlePacketType,
204 Object id)
205 {
206 // Call the load balancer's hook. If this is not active here
207 // we defer to the sim server this client is actually connected
208 // to. Packet drop notifies will not be triggered in this
209 // configuration!
210 //
211
212 packet.Header.Sequence = 0;
213
214 lock (m_NeedAck)
215 {
216 DropResend(id);
217
218 AddAcks(ref packet);
219 QueuePacket(packet, throttlePacketType, id);
220 }
221 }
222
223 private void AddAcks(ref Packet packet)
224 {
225 // These packet types have shown to have issues with
226 // acks being appended to the payload, just don't send
227 // any with them until libsl is fixed.
228 //
229 if (packet is ViewerEffectPacket)
230 return;
231 if (packet is SimStatsPacket)
232 return;
233
234 // Add acks to outgoing packets
235 //
236 if (m_PendingAcks.Count > 0)
237 {
238 int count = m_PendingAcks.Count;
239 if (count > 10)
240 count = 10;
241 packet.Header.AckList = new uint[count];
242 packet.Header.AppendedAcks = true;
243
244 for (int i = 0; i < count; i++)
245 {
246 packet.Header.AckList[i] = m_PendingAcks[i];
247 m_PendingAcksMap.Remove(m_PendingAcks[i]);
248 }
249 m_PendingAcks.RemoveRange(0, count);
250 }
251 }
252
253 private void QueuePacket(
254 Packet packet, ThrottleOutPacketType throttlePacketType,
255 Object id)
256 {
257 LLQueItem item = new LLQueItem();
258 item.Packet = packet;
259 item.Incoming = false;
260 item.throttleType = throttlePacketType;
261 item.TickCount = Environment.TickCount;
262 item.Identifier = id;
263 item.Resends = 0;
264 item.Length = packet.Length;
265 item.Sequence = packet.Header.Sequence;
266
267 m_PacketQueue.Enqueue(item);
268 m_PacketsSent++;
269 }
270
271 private void ResendUnacked()
272 {
273 int now = Environment.TickCount;
274
275 int intervalMs = 250;
276
277 if (m_LastResend != 0)
278 intervalMs = now - m_LastResend;
279
280 lock (m_NeedAck)
281 {
282 if (m_DropSafeTimeout > now ||
283 intervalMs > 500) // We were frozen!
284 {
285 foreach (LLQueItem data in m_NeedAck.Values)
286 {
287 if (m_DropSafeTimeout > now)
288 {
289 m_NeedAck[data.Packet.Header.Sequence].TickCount = now;
290 }
291 else
292 {
293 m_NeedAck[data.Packet.Header.Sequence].TickCount += intervalMs;
294 }
295 }
296 }
297
298 m_LastResend = now;
299
300 // Unless we have received at least one ack, don't bother resending
301 // anything. There may not be a client there, don't clog up the
302 // pipes.
303
304
305 // Nothing to do
306 //
307 if (m_NeedAck.Count == 0)
308 return;
309
310 int resent = 0;
311 long dueDate = now - m_ResendTimeout;
312
313 List<LLQueItem> dropped = new List<LLQueItem>();
314 foreach (LLQueItem data in m_NeedAck.Values)
315 {
316 Packet packet = data.Packet;
317
318 // Packets this old get resent
319 //
320 if (data.TickCount < dueDate && data.Sequence != 0 && !m_PacketQueue.Contains(data.Sequence))
321 {
322 if (resent < 20) // Was 20 (= Max 117kbit/sec resends)
323 {
324 m_NeedAck[packet.Header.Sequence].Resends++;
325
326 // The client needs to be told that a packet is being resent, otherwise it appears to believe
327 // that it should reset its sequence to that packet number.
328 packet.Header.Resent = true;
329
330 if ((m_NeedAck[packet.Header.Sequence].Resends >= m_MaxReliableResends) &&
331 (!m_ReliableIsImportant))
332 {
333 dropped.Add(data);
334 continue;
335 }
336
337 m_NeedAck[packet.Header.Sequence].TickCount = Environment.TickCount;
338 QueuePacket(packet, ThrottleOutPacketType.Resend, data.Identifier);
339 resent++;
340 }
341 else
342 {
343 m_NeedAck[packet.Header.Sequence].TickCount += intervalMs;
344 }
345 }
346 }
347
348 foreach (LLQueItem data in dropped)
349 {
350 m_NeedAck.Remove(data.Packet.Header.Sequence);
351 TriggerOnPacketDrop(data.Packet, data.Identifier);
352 m_PacketQueue.Cancel(data.Packet.Header.Sequence);
353 PacketPool.Instance.ReturnPacket(data.Packet);
354 }
355 }
356 }
357
358 // Send the pending packet acks to the client
359 // Will send blocks of acks for up to 250 packets
360 //
361 private void SendAcks()
362 {
363 lock (m_NeedAck)
364 {
365 if (m_PendingAcks.Count == 0)
366 return;
367
368 PacketAckPacket acks = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
369
370 // The case of equality is more common than one might think,
371 // because this function will be called unconditionally when
372 // the counter reaches 250. So there is a good chance another
373 // packet with 250 blocks exists.
374 //
375 if (acks.Packets == null ||
376 acks.Packets.Length != m_PendingAcks.Count)
377 acks.Packets = new PacketAckPacket.PacketsBlock[m_PendingAcks.Count];
378
379 for (int i = 0; i < m_PendingAcks.Count; i++)
380 {
381 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
382 acks.Packets[i].ID = m_PendingAcks[i];
383
384 }
385 m_PendingAcks.Clear();
386 m_PendingAcksMap.Clear();
387
388 acks.Header.Reliable = false;
389 OutPacket(acks, ThrottleOutPacketType.Unknown);
390 }
391 }
392
393 // Queue a packet ack. It will be sent either after 250 acks are
394 // queued, or when the timer fires.
395 //
396 private void AckPacket(Packet packet)
397 {
398 lock (m_NeedAck)
399 {
400 if (m_PendingAcks.Count < 250)
401 {
402 if (!m_PendingAcksMap.ContainsKey(packet.Header.Sequence))
403 {
404 m_PendingAcks.Add(packet.Header.Sequence);
405 m_PendingAcksMap.Add(packet.Header.Sequence,
406 packet.Header.Sequence);
407 }
408 return;
409 }
410 }
411
412 SendAcks();
413
414 lock (m_NeedAck)
415 {
416 // If this is still full we have a truly exceptional
417 // condition (means, can't happen)
418 //
419 if (m_PendingAcks.Count < 250)
420 {
421 if (!m_PendingAcksMap.ContainsKey(packet.Header.Sequence))
422 {
423 m_PendingAcks.Add(packet.Header.Sequence);
424 m_PendingAcksMap.Add(packet.Header.Sequence,
425 packet.Header.Sequence);
426 }
427 return;
428 }
429 }
430 }
431
432 // When the timer elapses, send the pending acks, trigger resends
433 // and report all the stats.
434 //
435 private void AckTimerElapsed(object sender, ElapsedEventArgs ea)
436 {
437 SendAcks();
438 ResendUnacked();
439 SendPacketStats();
440 }
441
442 // Push out pachet counts for the sim status reporter
443 //
444 private void SendPacketStats()
445 {
446 PacketStats handlerPacketStats = OnPacketStats;
447 if (handlerPacketStats != null)
448 {
449 handlerPacketStats(
450 m_PacketsReceived - m_PacketsReceivedReported,
451 m_PacketsSent - m_PacketsSentReported,
452 m_UnackedBytes);
453
454 m_PacketsReceivedReported = m_PacketsReceived;
455 m_PacketsSentReported = m_PacketsSent;
456 }
457 }
458
459 // We can't keep an unlimited record of dupes. This will prune the
460 // dictionary by age.
461 //
462 // NOTE: this needs to be called from within lock
463 // (m_alreadySeenTracker) context!
464 private void ExpireSeenPackets()
465 {
466 if (m_alreadySeenList.Count < 1024)
467 return;
468
469 int ticks = 0;
470 int tc = Environment.TickCount & Int32.MaxValue;
471 if (tc >= m_lastAlreadySeenCheck)
472 ticks = tc - m_lastAlreadySeenCheck;
473 else
474 ticks = Int32.MaxValue - m_lastAlreadySeenCheck + tc;
475
476 if (ticks < 2000) return;
477 m_lastAlreadySeenCheck = tc;
478
479 // we calculate the drop dead tick count here instead of
480 // in the loop: any packet with a timestamp before
481 // dropDeadTC can be expired
482 int dropDeadTC = tc - m_alreadySeenWindow;
483 int i = 0;
484 while (i < m_alreadySeenList.Count && m_alreadySeenTracker[m_alreadySeenList[i]] < dropDeadTC)
485 {
486 m_alreadySeenTracker.Remove(m_alreadySeenList[i]);
487 i++;
488 }
489 // if we dropped packet from m_alreadySeenTracker we need
490 // to drop them from m_alreadySeenList as well, let's do
491 // that in one go: the list is ordered after all.
492 if (i > 0)
493 {
494 m_alreadySeenList.RemoveRange(0, i);
495 // m_log.DebugFormat("[CLIENT]: expired {0} packets, {1}:{2} left", i, m_alreadySeenList.Count, m_alreadySeenTracker.Count);
496 }
497 }
498
499 public void InPacket(Packet packet)
500 {
501 if (packet == null)
502 return;
503
504 // When too many acks are needed to be sent, the client sends
505 // a packet consisting of acks only
506 //
507 if (packet.Type == PacketType.PacketAck)
508 {
509 PacketAckPacket ackPacket = (PacketAckPacket)packet;
510
511 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
512 {
513 ProcessAck(block.ID);
514 }
515
516 PacketPool.Instance.ReturnPacket(packet);
517 return;
518 }
519
520 // Any packet can have some packet acks in the header.
521 // Process them here
522 //
523 if (packet.Header.AppendedAcks)
524 {
525 foreach (uint id in packet.Header.AckList)
526 {
527 ProcessAck(id);
528 }
529 }
530
531 // If this client is on another partial instance, no need
532 // to handle packets
533 //
534 if (!m_Client.IsActive && packet.Type != PacketType.LogoutRequest)
535 {
536 PacketPool.Instance.ReturnPacket(packet);
537 return;
538 }
539
540 if (packet.Type == PacketType.StartPingCheck)
541 {
542 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
543 CompletePingCheckPacket endPing
544 = (CompletePingCheckPacket)PacketPool.Instance.GetPacket(PacketType.CompletePingCheck);
545
546 endPing.PingID.PingID = startPing.PingID.PingID;
547 OutPacket(endPing, ThrottleOutPacketType.Task);
548 }
549 else
550 {
551 LLQueItem item = new LLQueItem();
552 item.Packet = packet;
553 item.Incoming = true;
554 m_PacketQueue.Enqueue(item);
555 }
556 }
557
558 public void ProcessInPacket(LLQueItem item)
559 {
560 Packet packet = item.Packet;
561
562 // Always ack the packet!
563 //
564 if (packet.Header.Reliable)
565 AckPacket(packet);
566
567 if (packet.Type != PacketType.AgentUpdate)
568 m_PacketsReceived++;
569
570 // Check for duplicate packets.. packets that the client is
571 // resending because it didn't receive our ack
572 //
573 lock (m_alreadySeenTracker)
574 {
575 ExpireSeenPackets();
576
577 if (m_alreadySeenTracker.ContainsKey(packet.Header.Sequence))
578 return;
579
580 m_alreadySeenTracker.Add(packet.Header.Sequence, Environment.TickCount & Int32.MaxValue);
581 m_alreadySeenList.Add(packet.Header.Sequence);
582 }
583
584 m_Client.ProcessInPacket(packet);
585 }
586
587 public void Flush()
588 {
589 m_PacketQueue.Flush();
590 m_UnackedBytes = (-1 * m_UnackedBytes);
591 SendPacketStats();
592 }
593
594 public void Clear()
595 {
596 m_UnackedBytes = (-1 * m_UnackedBytes);
597 SendPacketStats();
598 lock (m_NeedAck)
599 {
600 m_NeedAck.Clear();
601 m_PendingAcks.Clear();
602 m_PendingAcksMap.Clear();
603 }
604 m_Sequence += 1000000;
605 }
606
607 private void ProcessAck(uint id)
608 {
609 LLQueItem data;
610
611 lock (m_NeedAck)
612 {
613 //m_log.DebugFormat("[CLIENT]: In {0} received ack for packet {1}", m_Client.Scene.RegionInfo.ExternalEndPoint.Port, id);
614
615 if (!m_NeedAck.TryGetValue(id, out data))
616 return;
617
618 m_NeedAck.Remove(id);
619 m_PacketQueue.Cancel(data.Sequence);
620 PacketPool.Instance.ReturnPacket(data.Packet);
621 m_UnackedBytes -= data.Length;
622 }
623 }
624
625 // Allocate packet sequence numbers in a threadsave manner
626 //
627 protected uint NextPacketSequenceNumber()
628 {
629 // Set the sequence number
630 uint seq = 1;
631 lock (m_SequenceLock)
632 {
633 if (m_Sequence >= MAX_SEQUENCE)
634 {
635 m_Sequence = 1;
636 }
637 else
638 {
639 m_Sequence++;
640 }
641 seq = m_Sequence;
642 }
643 return seq;
644 }
645
646 public ClientInfo GetClientInfo()
647 {
648 ClientInfo info = new ClientInfo();
649
650 info.pendingAcks = m_PendingAcksMap;
651 info.needAck = new Dictionary<uint, byte[]>();
652
653 lock (m_NeedAck)
654 {
655 foreach (uint key in m_NeedAck.Keys)
656 info.needAck.Add(key, m_NeedAck[key].Packet.ToBytes());
657 }
658
659 LLQueItem[] queitems = m_PacketQueue.GetQueueArray();
660
661 for (int i = 0; i < queitems.Length; i++)
662 {
663 if (queitems[i].Incoming == false)
664 info.out_packets.Add(queitems[i].Packet.ToBytes());
665 }
666
667 info.sequence = m_Sequence;
668
669 float multiplier = m_PacketQueue.ThrottleMultiplier;
670 info.resendThrottle = (int) (m_PacketQueue.ResendThrottle.Throttle / multiplier);
671 info.landThrottle = (int) (m_PacketQueue.LandThrottle.Throttle / multiplier);
672 info.windThrottle = (int) (m_PacketQueue.WindThrottle.Throttle / multiplier);
673 info.cloudThrottle = (int) (m_PacketQueue.CloudThrottle.Throttle / multiplier);
674 info.taskThrottle = (int) (m_PacketQueue.TaskThrottle.Throttle / multiplier);
675 info.assetThrottle = (int) (m_PacketQueue.AssetThrottle.Throttle / multiplier);
676 info.textureThrottle = (int) (m_PacketQueue.TextureThrottle.Throttle / multiplier);
677 info.totalThrottle = (int) (m_PacketQueue.TotalThrottle.Throttle / multiplier);
678
679 return info;
680 }
681
682 public void SetClientInfo(ClientInfo info)
683 {
684 m_PendingAcksMap = info.pendingAcks;
685 m_PendingAcks = new List<uint>(m_PendingAcksMap.Keys);
686 m_NeedAck = new Dictionary<uint, LLQueItem>();
687
688 Packet packet = null;
689 int packetEnd = 0;
690 byte[] zero = new byte[3000];
691
692 foreach (uint key in info.needAck.Keys)
693 {
694 byte[] buff = info.needAck[key];
695 packetEnd = buff.Length - 1;
696
697 try
698 {
699 packet = PacketPool.Instance.GetPacket(buff, ref packetEnd, zero);
700 }
701 catch (Exception)
702 {
703 }
704
705 LLQueItem item = new LLQueItem();
706 item.Packet = packet;
707 item.Incoming = false;
708 item.throttleType = 0;
709 item.TickCount = Environment.TickCount;
710 item.Identifier = 0;
711 item.Resends = 0;
712 item.Length = packet.Length;
713 item.Sequence = packet.Header.Sequence;
714 m_NeedAck.Add(key, item);
715 }
716
717 m_Sequence = info.sequence;
718
719 m_PacketQueue.ResendThrottle.Throttle = info.resendThrottle;
720 m_PacketQueue.LandThrottle.Throttle = info.landThrottle;
721 m_PacketQueue.WindThrottle.Throttle = info.windThrottle;
722 m_PacketQueue.CloudThrottle.Throttle = info.cloudThrottle;
723 m_PacketQueue.TaskThrottle.Throttle = info.taskThrottle;
724 m_PacketQueue.AssetThrottle.Throttle = info.assetThrottle;
725 m_PacketQueue.TextureThrottle.Throttle = info.textureThrottle;
726 m_PacketQueue.TotalThrottle.Throttle = info.totalThrottle;
727 }
728
729 public void AddImportantPacket(PacketType type)
730 {
731 if (m_ImportantPackets.Contains(type))
732 return;
733
734 m_ImportantPackets.Add(type);
735 }
736
737 public void RemoveImportantPacket(PacketType type)
738 {
739 if (!m_ImportantPackets.Contains(type))
740 return;
741
742 m_ImportantPackets.Remove(type);
743 }
744
745 private void DropResend(Object id)
746 {
747 LLQueItem d = null;
748
749 foreach (LLQueItem data in m_NeedAck.Values)
750 {
751 if (data.Identifier != null && data.Identifier == id)
752 {
753 d = data;
754 break;
755 }
756 }
757
758 if (null == d) return;
759
760 m_NeedAck.Remove(d.Packet.Header.Sequence);
761 m_PacketQueue.Cancel(d.Sequence);
762 PacketPool.Instance.ReturnPacket(d.Packet);
763 }
764
765 private void TriggerOnPacketDrop(Packet packet, Object id)
766 {
767 PacketDrop handlerPacketDrop = OnPacketDrop;
768
769 if (handlerPacketDrop == null)
770 return;
771
772 handlerPacketDrop(packet, id);
773 }
774
775 private void TriggerOnQueueEmpty(ThrottleOutPacketType queue)
776 {
777 QueueEmpty handlerQueueEmpty = OnQueueEmpty;
778
779 if (handlerQueueEmpty != null)
780 handlerQueueEmpty(queue);
781 }
782
783 // Convert the packet to bytes and stuff it onto the send queue
784 //
785 public void ProcessOutPacket(LLQueItem item)
786 {
787 Packet packet = item.Packet;
788
789 // Assign sequence number here to prevent out of order packets
790 if (packet.Header.Sequence == 0)
791 {
792 lock (m_NeedAck)
793 {
794 packet.Header.Sequence = NextPacketSequenceNumber();
795 item.Sequence = packet.Header.Sequence;
796 item.TickCount = Environment.TickCount;
797
798 // We want to see that packet arrive if it's reliable
799 if (packet.Header.Reliable)
800 {
801 m_UnackedBytes += item.Length;
802
803 // Keep track of when this packet was sent out
804 item.TickCount = Environment.TickCount;
805
806 m_NeedAck[packet.Header.Sequence] = item;
807 }
808 }
809 }
810
811 // If we sent a killpacket
812 if (packet is KillPacket)
813 Abort();
814
815 try
816 {
817 // If this packet has been reused/returned, the ToBytes
818 // will blow up in our face.
819 // Fail gracefully.
820 //
821
822 // Actually make the byte array and send it
823 byte[] sendbuffer = item.Packet.ToBytes();
824
825 if (packet.Header.Zerocoded)
826 {
827 int packetsize = Helpers.ZeroEncode(sendbuffer,
828 sendbuffer.Length, m_ZeroOutBuffer);
829 m_PacketServer.SendPacketTo(m_ZeroOutBuffer, packetsize,
830 SocketFlags.None, m_Client.CircuitCode);
831 }
832 else
833 {
834 // Need some extra space in case we need to add proxy
835 // information to the message later
836 Buffer.BlockCopy(sendbuffer, 0, m_ZeroOutBuffer, 0,
837 sendbuffer.Length);
838 m_PacketServer.SendPacketTo(m_ZeroOutBuffer,
839 sendbuffer.Length, SocketFlags.None, m_Client.CircuitCode);
840 }
841 }
842 catch (NullReferenceException)
843 {
844 m_log.Error("[PACKET]: Detected reuse of a returned packet");
845 m_PacketQueue.Cancel(item.Sequence);
846 return;
847 }
848
849 // If this is a reliable packet, we are still holding a ref
850 // Dont't return in that case
851 //
852 if (!packet.Header.Reliable)
853 {
854 m_PacketQueue.Cancel(item.Sequence);
855 PacketPool.Instance.ReturnPacket(packet);
856 }
857 }
858
859 private void Abort()
860 {
861 m_PacketQueue.Close();
862 Thread.CurrentThread.Abort();
863 }
864
865 public int GetQueueCount(ThrottleOutPacketType queue)
866 {
867 return m_PacketQueue.GetQueueCount(queue);
868 }
869 }
870}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
deleted file mode 100644
index 3eed2e0..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketQueue.cs
+++ /dev/null
@@ -1,742 +0,0 @@
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 OpenSimulator 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.Reflection;
31using System.Threading;
32using System.Timers;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Statistics;
37using OpenSim.Framework.Statistics.Interfaces;
38using Timer=System.Timers.Timer;
39
40namespace OpenSim.Region.ClientStack.LindenUDP
41{
42 public class LLPacketQueue : IPullStatsProvider, IDisposable
43 {
44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 /// Is queueing enabled at all?
49 /// </summary>
50 private bool m_enabled = true;
51
52 private OpenSim.Framework.BlockingQueue<LLQueItem> SendQueue;
53
54 private Queue<LLQueItem> IncomingPacketQueue;
55 private Queue<LLQueItem> OutgoingPacketQueue;
56 private Queue<LLQueItem> ResendOutgoingPacketQueue;
57 private Queue<LLQueItem> LandOutgoingPacketQueue;
58 private Queue<LLQueItem> WindOutgoingPacketQueue;
59 private Queue<LLQueItem> CloudOutgoingPacketQueue;
60 private Queue<LLQueItem> TaskOutgoingPacketQueue;
61 private Queue<LLQueItem> TaskLowpriorityPacketQueue;
62 private Queue<LLQueItem> TextureOutgoingPacketQueue;
63 private Queue<LLQueItem> AssetOutgoingPacketQueue;
64
65 private List<ThrottleOutPacketType> Empty = new List<ThrottleOutPacketType>();
66 // m_log.Info("[THROTTLE]: Entering Throttle");
67 // private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
68 // private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
69
70 // All throttle times and number of bytes are calculated by dividing by this value
71 // This value also determines how many times per throttletimems the timer will run
72 // If throttleimems is 1000 ms, then the timer will fire every 1000/7 milliseconds
73
74 private float throttleMultiplier = 2.0f; // Default value really doesn't matter.
75 private int throttleTimeDivisor = 7;
76
77 private int throttletimems = 1000;
78
79 internal LLPacketThrottle ResendThrottle;
80 internal LLPacketThrottle LandThrottle;
81 internal LLPacketThrottle WindThrottle;
82 internal LLPacketThrottle CloudThrottle;
83 internal LLPacketThrottle TaskThrottle;
84 internal LLPacketThrottle AssetThrottle;
85 internal LLPacketThrottle TextureThrottle;
86 internal LLPacketThrottle TotalThrottle;
87
88 private Dictionary<uint,int> contents = new Dictionary<uint, int>();
89
90 // private long LastThrottle;
91 // private long ThrottleInterval;
92 private Timer throttleTimer;
93
94 private UUID m_agentId;
95
96 public event QueueEmpty OnQueueEmpty;
97
98 public LLPacketQueue(UUID agentId, ClientStackUserSettings userSettings)
99 {
100 // While working on this, the BlockingQueue had me fooled for a bit.
101 // The Blocking queue causes the thread to stop until there's something
102 // in it to process. it's an on-purpose threadlock though because
103 // without it, the clientloop will suck up all sim resources.
104
105 SendQueue = new OpenSim.Framework.BlockingQueue<LLQueItem>();
106
107 IncomingPacketQueue = new Queue<LLQueItem>();
108 OutgoingPacketQueue = new Queue<LLQueItem>();
109 ResendOutgoingPacketQueue = new Queue<LLQueItem>();
110 LandOutgoingPacketQueue = new Queue<LLQueItem>();
111 WindOutgoingPacketQueue = new Queue<LLQueItem>();
112 CloudOutgoingPacketQueue = new Queue<LLQueItem>();
113 TaskOutgoingPacketQueue = new Queue<LLQueItem>();
114 TaskLowpriorityPacketQueue = new Queue<LLQueItem>();
115 TextureOutgoingPacketQueue = new Queue<LLQueItem>();
116 AssetOutgoingPacketQueue = new Queue<LLQueItem>();
117
118 // Store the throttle multiplier for posterity.
119 throttleMultiplier = userSettings.ClientThrottleMultipler;
120
121
122 int throttleMaxBPS = 1500000;
123 if (userSettings.TotalThrottleSettings != null)
124 throttleMaxBPS = userSettings.TotalThrottleSettings.Max;
125
126 // Set up the throttle classes (min, max, current) in bits per second
127 ResendThrottle = new LLPacketThrottle(5000, throttleMaxBPS / 15, 16000, userSettings.ClientThrottleMultipler);
128 LandThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 15, 2000, userSettings.ClientThrottleMultipler);
129 WindThrottle = new LLPacketThrottle(0, throttleMaxBPS / 15, 0, userSettings.ClientThrottleMultipler);
130 CloudThrottle = new LLPacketThrottle(0, throttleMaxBPS / 15, 0, userSettings.ClientThrottleMultipler);
131 TaskThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 2, 3000, userSettings.ClientThrottleMultipler);
132 AssetThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 2, 1000, userSettings.ClientThrottleMultipler);
133 TextureThrottle = new LLPacketThrottle(1000, throttleMaxBPS / 2, 4000, userSettings.ClientThrottleMultipler);
134
135
136 // Total Throttle trumps all - it is the number of bits in total that are allowed to go out per second.
137
138
139 ThrottleSettings totalThrottleSettings = userSettings.TotalThrottleSettings;
140 if (null == totalThrottleSettings)
141 {
142 totalThrottleSettings = new ThrottleSettings(0, throttleMaxBPS, 28000);
143 }
144
145 TotalThrottle
146 = new LLPacketThrottle(
147 totalThrottleSettings.Min, totalThrottleSettings.Max, totalThrottleSettings.Current,
148 userSettings.ClientThrottleMultipler);
149
150 throttleTimer = new Timer((int)(throttletimems / throttleTimeDivisor));
151 throttleTimer.Elapsed += ThrottleTimerElapsed;
152 throttleTimer.Start();
153
154 // TIMERS needed for this
155 // LastThrottle = DateTime.Now.Ticks;
156 // ThrottleInterval = (long)(throttletimems/throttleTimeDivisor);
157
158 m_agentId = agentId;
159
160 if (StatsManager.SimExtraStats != null)
161 {
162 StatsManager.SimExtraStats.RegisterPacketQueueStatsProvider(m_agentId, this);
163 }
164 }
165
166 /* STANDARD QUEUE MANIPULATION INTERFACES */
167
168 public void Enqueue(LLQueItem item)
169 {
170 if (!m_enabled)
171 {
172 return;
173 }
174 // We could micro lock, but that will tend to actually
175 // probably be worse than just synchronizing on SendQueue
176
177 if (item == null)
178 {
179 SendQueue.Enqueue(item);
180 return;
181 }
182
183 if (item.Incoming)
184 {
185 SendQueue.PriorityEnqueue(item);
186 return;
187 }
188
189 if (item.Sequence != 0)
190 lock (contents)
191 {
192 if (contents.ContainsKey(item.Sequence))
193 contents[item.Sequence] += 1;
194 else
195 contents.Add(item.Sequence, 1);
196 }
197
198 lock (this)
199 {
200 switch (item.throttleType & ThrottleOutPacketType.TypeMask)
201 {
202 case ThrottleOutPacketType.Resend:
203 ThrottleCheck(ref ResendThrottle, ref ResendOutgoingPacketQueue, item, ThrottleOutPacketType.Resend);
204 break;
205 case ThrottleOutPacketType.Texture:
206 ThrottleCheck(ref TextureThrottle, ref TextureOutgoingPacketQueue, item, ThrottleOutPacketType.Texture);
207 break;
208 case ThrottleOutPacketType.Task:
209 if ((item.throttleType & ThrottleOutPacketType.LowPriority) != 0)
210 ThrottleCheck(ref TaskThrottle, ref TaskLowpriorityPacketQueue, item, ThrottleOutPacketType.Task);
211 else
212 ThrottleCheck(ref TaskThrottle, ref TaskOutgoingPacketQueue, item, ThrottleOutPacketType.Task);
213 break;
214 case ThrottleOutPacketType.Land:
215 ThrottleCheck(ref LandThrottle, ref LandOutgoingPacketQueue, item, ThrottleOutPacketType.Land);
216 break;
217 case ThrottleOutPacketType.Asset:
218 ThrottleCheck(ref AssetThrottle, ref AssetOutgoingPacketQueue, item, ThrottleOutPacketType.Asset);
219 break;
220 case ThrottleOutPacketType.Cloud:
221 ThrottleCheck(ref CloudThrottle, ref CloudOutgoingPacketQueue, item, ThrottleOutPacketType.Cloud);
222 break;
223 case ThrottleOutPacketType.Wind:
224 ThrottleCheck(ref WindThrottle, ref WindOutgoingPacketQueue, item, ThrottleOutPacketType.Wind);
225 break;
226
227 default:
228 // Acknowledgements and other such stuff should go directly to the blocking Queue
229 // Throttling them may and likely 'will' be problematic
230 SendQueue.PriorityEnqueue(item);
231 break;
232 }
233 }
234 }
235
236 public LLQueItem Dequeue()
237 {
238 while (true)
239 {
240 LLQueItem item = SendQueue.Dequeue();
241 if (item == null)
242 return null;
243 if (item.Incoming)
244 return item;
245 item.TickCount = System.Environment.TickCount;
246 if (item.Sequence == 0)
247 return item;
248 lock (contents)
249 {
250 if (contents.ContainsKey(item.Sequence))
251 {
252 if (contents[item.Sequence] == 1)
253 contents.Remove(item.Sequence);
254 else
255 contents[item.Sequence] -= 1;
256 return item;
257 }
258 }
259 }
260 }
261
262 public void Cancel(uint sequence)
263 {
264 lock (contents) contents.Remove(sequence);
265 }
266
267 public bool Contains(uint sequence)
268 {
269 lock (contents) return contents.ContainsKey(sequence);
270 }
271
272 public void Flush()
273 {
274 lock (this)
275 {
276 // These categories do not contain transactional packets so we can safely drop any pending data in them
277 LandOutgoingPacketQueue.Clear();
278 WindOutgoingPacketQueue.Clear();
279 CloudOutgoingPacketQueue.Clear();
280 TextureOutgoingPacketQueue.Clear();
281 AssetOutgoingPacketQueue.Clear();
282
283 // Now comes the fun part.. we dump all remaining resend and task packets into the send queue
284 while (ResendOutgoingPacketQueue.Count > 0 || TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0)
285 {
286 if (ResendOutgoingPacketQueue.Count > 0)
287 SendQueue.Enqueue(ResendOutgoingPacketQueue.Dequeue());
288
289 if (TaskOutgoingPacketQueue.Count > 0)
290 SendQueue.PriorityEnqueue(TaskOutgoingPacketQueue.Dequeue());
291
292 if (TaskLowpriorityPacketQueue.Count > 0)
293 SendQueue.Enqueue(TaskLowpriorityPacketQueue.Dequeue());
294 }
295 }
296 }
297
298 public void WipeClean()
299 {
300 lock (this)
301 {
302 ResendOutgoingPacketQueue.Clear();
303 LandOutgoingPacketQueue.Clear();
304 WindOutgoingPacketQueue.Clear();
305 CloudOutgoingPacketQueue.Clear();
306 TaskOutgoingPacketQueue.Clear();
307 TaskLowpriorityPacketQueue.Clear();
308 TextureOutgoingPacketQueue.Clear();
309 AssetOutgoingPacketQueue.Clear();
310 SendQueue.Clear();
311 lock (contents) contents.Clear();
312 }
313 }
314
315 public void Close()
316 {
317 Dispose();
318 }
319
320 public void Dispose()
321 {
322 Flush();
323 WipeClean(); // I'm sure there's a dirty joke in here somewhere. -AFrisby
324
325 m_enabled = false;
326 throttleTimer.Stop();
327 throttleTimer.Close();
328
329 if (StatsManager.SimExtraStats != null)
330 {
331 StatsManager.SimExtraStats.DeregisterPacketQueueStatsProvider(m_agentId);
332 }
333 }
334
335 private void ResetCounters()
336 {
337 ResendThrottle.Reset();
338 LandThrottle.Reset();
339 WindThrottle.Reset();
340 CloudThrottle.Reset();
341 TaskThrottle.Reset();
342 AssetThrottle.Reset();
343 TextureThrottle.Reset();
344 TotalThrottle.Reset();
345 }
346
347 private bool PacketsWaiting()
348 {
349 return (ResendOutgoingPacketQueue.Count > 0 ||
350 LandOutgoingPacketQueue.Count > 0 ||
351 WindOutgoingPacketQueue.Count > 0 ||
352 CloudOutgoingPacketQueue.Count > 0 ||
353 TaskOutgoingPacketQueue.Count > 0 ||
354 TaskLowpriorityPacketQueue.Count > 0 ||
355 AssetOutgoingPacketQueue.Count > 0 ||
356 TextureOutgoingPacketQueue.Count > 0);
357 }
358
359 public void ProcessThrottle()
360 {
361 // I was considering this.. Will an event fire if the thread it's on is blocked?
362
363 // Then I figured out.. it doesn't really matter.. because this thread won't be blocked for long
364 // The General overhead of the UDP protocol gets sent to the queue un-throttled by this
365 // so This'll pick up about around the right time.
366
367 int MaxThrottleLoops = 4550; // 50*7 packets can be dequeued at once.
368 int throttleLoops = 0;
369 List<ThrottleOutPacketType> e;
370
371 // We're going to dequeue all of the saved up packets until
372 // we've hit the throttle limit or there's no more packets to send
373 lock (this)
374 {
375 // this variable will be true if there was work done in the last execution of the
376 // loop, since each pass through the loop checks the queue length, we no longer
377 // need the check on entering the loop
378 bool qchanged = true;
379
380 ResetCounters();
381
382 while (TotalThrottle.UnderLimit() && qchanged && throttleLoops <= MaxThrottleLoops)
383 {
384 qchanged = false; // We will break out of the loop if no work was accomplished
385
386 throttleLoops++;
387 //Now comes the fun part.. we dump all our elements into m_packetQueue that we've saved up.
388 if ((ResendOutgoingPacketQueue.Count > 0) && ResendThrottle.UnderLimit())
389 {
390 LLQueItem qpack = ResendOutgoingPacketQueue.Dequeue();
391
392 SendQueue.Enqueue(qpack);
393 TotalThrottle.AddBytes(qpack.Length);
394 ResendThrottle.AddBytes(qpack.Length);
395
396 qchanged = true;
397 }
398
399 if ((LandOutgoingPacketQueue.Count > 0) && LandThrottle.UnderLimit())
400 {
401 LLQueItem qpack = LandOutgoingPacketQueue.Dequeue();
402
403 SendQueue.Enqueue(qpack);
404 TotalThrottle.AddBytes(qpack.Length);
405 LandThrottle.AddBytes(qpack.Length);
406 qchanged = true;
407
408 if (LandOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Land))
409 Empty.Add(ThrottleOutPacketType.Land);
410 }
411
412 if ((WindOutgoingPacketQueue.Count > 0) && WindThrottle.UnderLimit())
413 {
414 LLQueItem qpack = WindOutgoingPacketQueue.Dequeue();
415
416 SendQueue.Enqueue(qpack);
417 TotalThrottle.AddBytes(qpack.Length);
418 WindThrottle.AddBytes(qpack.Length);
419 qchanged = true;
420
421 if (WindOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Wind))
422 Empty.Add(ThrottleOutPacketType.Wind);
423 }
424
425 if ((CloudOutgoingPacketQueue.Count > 0) && CloudThrottle.UnderLimit())
426 {
427 LLQueItem qpack = CloudOutgoingPacketQueue.Dequeue();
428
429 SendQueue.Enqueue(qpack);
430 TotalThrottle.AddBytes(qpack.Length);
431 CloudThrottle.AddBytes(qpack.Length);
432 qchanged = true;
433
434 if (CloudOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Cloud))
435 Empty.Add(ThrottleOutPacketType.Cloud);
436 }
437
438 if ((TaskOutgoingPacketQueue.Count > 0 || TaskLowpriorityPacketQueue.Count > 0) && TaskThrottle.UnderLimit())
439 {
440 LLQueItem qpack;
441 if (TaskOutgoingPacketQueue.Count > 0)
442 {
443 qpack = TaskOutgoingPacketQueue.Dequeue();
444 SendQueue.PriorityEnqueue(qpack);
445 }
446 else
447 {
448 qpack = TaskLowpriorityPacketQueue.Dequeue();
449 SendQueue.Enqueue(qpack);
450 }
451
452 TotalThrottle.AddBytes(qpack.Length);
453 TaskThrottle.AddBytes(qpack.Length);
454 qchanged = true;
455
456 if (TaskOutgoingPacketQueue.Count == 0 && TaskLowpriorityPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Task))
457 Empty.Add(ThrottleOutPacketType.Task);
458 }
459
460 if ((TextureOutgoingPacketQueue.Count > 0) && TextureThrottle.UnderLimit())
461 {
462 LLQueItem qpack = TextureOutgoingPacketQueue.Dequeue();
463
464 SendQueue.Enqueue(qpack);
465 TotalThrottle.AddBytes(qpack.Length);
466 TextureThrottle.AddBytes(qpack.Length);
467 qchanged = true;
468
469 if (TextureOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Texture))
470 Empty.Add(ThrottleOutPacketType.Texture);
471 }
472
473 if ((AssetOutgoingPacketQueue.Count > 0) && AssetThrottle.UnderLimit())
474 {
475 LLQueItem qpack = AssetOutgoingPacketQueue.Dequeue();
476
477 SendQueue.Enqueue(qpack);
478 TotalThrottle.AddBytes(qpack.Length);
479 AssetThrottle.AddBytes(qpack.Length);
480 qchanged = true;
481
482 if (AssetOutgoingPacketQueue.Count == 0 && !Empty.Contains(ThrottleOutPacketType.Asset))
483 Empty.Add(ThrottleOutPacketType.Asset);
484 }
485 }
486 // m_log.Info("[THROTTLE]: Processed " + throttleLoops + " packets");
487
488 e = new List<ThrottleOutPacketType>(Empty);
489 Empty.Clear();
490 }
491
492 foreach (ThrottleOutPacketType t in e)
493 {
494 if (GetQueueCount(t) == 0)
495 TriggerOnQueueEmpty(t);
496 }
497 }
498
499 private void TriggerOnQueueEmpty(ThrottleOutPacketType queue)
500 {
501 QueueEmpty handlerQueueEmpty = OnQueueEmpty;
502
503 if (handlerQueueEmpty != null)
504 handlerQueueEmpty(queue);
505 }
506
507 private void ThrottleTimerElapsed(object sender, ElapsedEventArgs e)
508 {
509 // just to change the signature, and that ProcessThrottle
510 // will be used elsewhere possibly
511 ProcessThrottle();
512 }
513
514 private void ThrottleCheck(ref LLPacketThrottle throttle, ref Queue<LLQueItem> q, LLQueItem item, ThrottleOutPacketType itemType)
515 {
516 // The idea.. is if the packet throttle queues are empty
517 // and the client is under throttle for the type. Queue
518 // it up directly. This basically short cuts having to
519 // wait for the timer to fire to put things into the
520 // output queue
521
522 if ((q.Count == 0) && (throttle.UnderLimit()))
523 {
524 try
525 {
526 Monitor.Enter(this);
527 throttle.AddBytes(item.Length);
528 TotalThrottle.AddBytes(item.Length);
529 SendQueue.Enqueue(item);
530 lock (this)
531 {
532 if (!Empty.Contains(itemType))
533 Empty.Add(itemType);
534 }
535 }
536 catch (Exception e)
537 {
538 // Probably a serialization exception
539 m_log.WarnFormat("ThrottleCheck: {0}", e.ToString());
540 }
541 finally
542 {
543 Monitor.Pulse(this);
544 Monitor.Exit(this);
545 }
546 }
547 else
548 {
549 q.Enqueue(item);
550 }
551 }
552
553 private static int ScaleThrottle(int value, int curmax, int newmax)
554 {
555 return (int)((value / (float)curmax) * newmax);
556 }
557
558 public byte[] GetThrottlesPacked(float multiplier)
559 {
560 int singlefloat = 4;
561 float tResend = ResendThrottle.Throttle*multiplier;
562 float tLand = LandThrottle.Throttle*multiplier;
563 float tWind = WindThrottle.Throttle*multiplier;
564 float tCloud = CloudThrottle.Throttle*multiplier;
565 float tTask = TaskThrottle.Throttle*multiplier;
566 float tTexture = TextureThrottle.Throttle*multiplier;
567 float tAsset = AssetThrottle.Throttle*multiplier;
568
569 byte[] throttles = new byte[singlefloat*7];
570 int i = 0;
571 Buffer.BlockCopy(BitConverter.GetBytes(tResend), 0, throttles, singlefloat*i, singlefloat);
572 i++;
573 Buffer.BlockCopy(BitConverter.GetBytes(tLand), 0, throttles, singlefloat*i, singlefloat);
574 i++;
575 Buffer.BlockCopy(BitConverter.GetBytes(tWind), 0, throttles, singlefloat*i, singlefloat);
576 i++;
577 Buffer.BlockCopy(BitConverter.GetBytes(tCloud), 0, throttles, singlefloat*i, singlefloat);
578 i++;
579 Buffer.BlockCopy(BitConverter.GetBytes(tTask), 0, throttles, singlefloat*i, singlefloat);
580 i++;
581 Buffer.BlockCopy(BitConverter.GetBytes(tTexture), 0, throttles, singlefloat*i, singlefloat);
582 i++;
583 Buffer.BlockCopy(BitConverter.GetBytes(tAsset), 0, throttles, singlefloat*i, singlefloat);
584
585 return throttles;
586 }
587
588 public void SetThrottleFromClient(byte[] throttle)
589 {
590 // From mantis http://opensimulator.org/mantis/view.php?id=1374
591 // it appears that sometimes we are receiving empty throttle byte arrays.
592 // TODO: Investigate this behaviour
593 if (throttle.Length == 0)
594 {
595 m_log.Warn("[PACKET QUEUE]: SetThrottleFromClient unexpectedly received a throttle byte array containing no elements!");
596 return;
597 }
598
599 int tResend = -1;
600 int tLand = -1;
601 int tWind = -1;
602 int tCloud = -1;
603 int tTask = -1;
604 int tTexture = -1;
605 int tAsset = -1;
606 int tall = -1;
607 int singlefloat = 4;
608
609 //Agent Throttle Block contains 7 single floatingpoint values.
610 int j = 0;
611
612 // Some Systems may be big endian...
613 // it might be smart to do this check more often...
614 if (!BitConverter.IsLittleEndian)
615 for (int i = 0; i < 7; i++)
616 Array.Reverse(throttle, j + i*singlefloat, singlefloat);
617
618 // values gotten from OpenMetaverse.org/wiki/Throttle. Thanks MW_
619 // bytes
620 // Convert to integer, since.. the full fp space isn't used.
621 tResend = (int) BitConverter.ToSingle(throttle, j);
622 j += singlefloat;
623 tLand = (int) BitConverter.ToSingle(throttle, j);
624 j += singlefloat;
625 tWind = (int) BitConverter.ToSingle(throttle, j);
626 j += singlefloat;
627 tCloud = (int) BitConverter.ToSingle(throttle, j);
628 j += singlefloat;
629 tTask = (int) BitConverter.ToSingle(throttle, j);
630 j += singlefloat;
631 tTexture = (int) BitConverter.ToSingle(throttle, j);
632 j += singlefloat;
633 tAsset = (int) BitConverter.ToSingle(throttle, j);
634
635 tall = tResend + tLand + tWind + tCloud + tTask + tTexture + tAsset;
636
637 /*
638 m_log.Info("[CLIENT]: Client AgentThrottle - Got throttle:resendbits=" + tResend +
639 " landbits=" + tLand +
640 " windbits=" + tWind +
641 " cloudbits=" + tCloud +
642 " taskbits=" + tTask +
643 " texturebits=" + tTexture +
644 " Assetbits=" + tAsset +
645 " Allbits=" + tall);
646 */
647
648
649 // Total Sanity
650 // Make sure that the client sent sane total values.
651
652 // If the client didn't send acceptable values....
653 // Scale the clients values down until they are acceptable.
654
655 if (tall <= TotalThrottle.Max)
656 {
657 ResendThrottle.Throttle = tResend;
658 LandThrottle.Throttle = tLand;
659 WindThrottle.Throttle = tWind;
660 CloudThrottle.Throttle = tCloud;
661 TaskThrottle.Throttle = tTask;
662 TextureThrottle.Throttle = tTexture;
663 AssetThrottle.Throttle = tAsset;
664 TotalThrottle.Throttle = tall;
665 }
666// else if (tall < 1)
667// {
668// // client is stupid, penalize him by minning everything
669// ResendThrottle.Throttle = ResendThrottle.Min;
670// LandThrottle.Throttle = LandThrottle.Min;
671// WindThrottle.Throttle = WindThrottle.Min;
672// CloudThrottle.Throttle = CloudThrottle.Min;
673// TaskThrottle.Throttle = TaskThrottle.Min;
674// TextureThrottle.Throttle = TextureThrottle.Min;
675// AssetThrottle.Throttle = AssetThrottle.Min;
676// TotalThrottle.Throttle = TotalThrottle.Min;
677// }
678 else
679 {
680 // we're over so figure out percentages and use those
681 ResendThrottle.Throttle = tResend;
682
683 LandThrottle.Throttle = ScaleThrottle(tLand, tall, TotalThrottle.Max);
684 WindThrottle.Throttle = ScaleThrottle(tWind, tall, TotalThrottle.Max);
685 CloudThrottle.Throttle = ScaleThrottle(tCloud, tall, TotalThrottle.Max);
686 TaskThrottle.Throttle = ScaleThrottle(tTask, tall, TotalThrottle.Max);
687 TextureThrottle.Throttle = ScaleThrottle(tTexture, tall, TotalThrottle.Max);
688 AssetThrottle.Throttle = ScaleThrottle(tAsset, tall, TotalThrottle.Max);
689 TotalThrottle.Throttle = TotalThrottle.Max;
690 }
691 // effectively wiggling the slider causes things reset
692// ResetCounters(); // DO NOT reset, better to send less for one period than more
693 }
694
695 // See IPullStatsProvider
696 public string GetStats()
697 {
698 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
699 SendQueue.Count(),
700 IncomingPacketQueue.Count,
701 OutgoingPacketQueue.Count,
702 ResendOutgoingPacketQueue.Count,
703 LandOutgoingPacketQueue.Count,
704 WindOutgoingPacketQueue.Count,
705 CloudOutgoingPacketQueue.Count,
706 TaskOutgoingPacketQueue.Count,
707 TextureOutgoingPacketQueue.Count,
708 AssetOutgoingPacketQueue.Count);
709 }
710
711 public LLQueItem[] GetQueueArray()
712 {
713 return SendQueue.GetQueueArray();
714 }
715
716 public float ThrottleMultiplier
717 {
718 get { return throttleMultiplier; }
719 }
720
721 public int GetQueueCount(ThrottleOutPacketType queue)
722 {
723 switch (queue)
724 {
725 case ThrottleOutPacketType.Land:
726 return LandOutgoingPacketQueue.Count;
727 case ThrottleOutPacketType.Wind:
728 return WindOutgoingPacketQueue.Count;
729 case ThrottleOutPacketType.Cloud:
730 return CloudOutgoingPacketQueue.Count;
731 case ThrottleOutPacketType.Task:
732 return TaskOutgoingPacketQueue.Count;
733 case ThrottleOutPacketType.Texture:
734 return TextureOutgoingPacketQueue.Count;
735 case ThrottleOutPacketType.Asset:
736 return AssetOutgoingPacketQueue.Count;
737 }
738
739 return 0;
740 }
741 }
742}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs
deleted file mode 100644
index 70d94e7..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketServer.cs
+++ /dev/null
@@ -1,206 +0,0 @@
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 OpenSimulator 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 OpenMetaverse;
31using OpenMetaverse.Packets;
32using OpenSim.Framework;
33
34namespace OpenSim.Region.ClientStack.LindenUDP
35{
36 /// <summary>
37 /// This class sets up new client stacks. It also handles the immediate distribution of incoming packets to
38 /// client stacks
39 /// </summary>
40 public class LLPacketServer
41 {
42// private static readonly log4net.ILog m_log
43// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
44
45 protected readonly ILLClientStackNetworkHandler m_networkHandler;
46 protected IScene m_scene;
47
48 /// <summary>
49 /// Tweakable user settings
50 /// </summary>
51 private ClientStackUserSettings m_userSettings;
52
53 public LLPacketServer(ILLClientStackNetworkHandler networkHandler, ClientStackUserSettings userSettings)
54 {
55 m_userSettings = userSettings;
56 m_networkHandler = networkHandler;
57
58 m_networkHandler.RegisterPacketServer(this);
59 }
60
61 public IScene LocalScene
62 {
63 set { m_scene = value; }
64 }
65
66 /// <summary>
67 /// Process an incoming packet.
68 /// </summary>
69 /// <param name="circuitCode"></param>
70 /// <param name="packet"></param>
71 public virtual void InPacket(uint circuitCode, Packet packet)
72 {
73 m_scene.ClientManager.InPacket(circuitCode, packet);
74 }
75
76 /// <summary>
77 /// Create a new client circuit
78 /// </summary>
79 /// <param name="remoteEP"></param>
80 /// <param name="scene"></param>
81 /// <param name="assetCache"></param>
82 /// <param name="packServer"></param>
83 /// <param name="sessionInfo"></param>
84 /// <param name="agentId"></param>
85 /// <param name="sessionId"></param>
86 /// <param name="circuitCode"></param>
87 /// <param name="proxyEP"></param>
88 /// <returns></returns>
89 protected virtual IClientAPI CreateNewCircuit(
90 EndPoint remoteEP, IScene scene,
91 LLPacketServer packServer, AuthenticateResponse sessionInfo,
92 UUID agentId, UUID sessionId, uint circuitCode, EndPoint proxyEP)
93 {
94 return
95 new LLClientView(
96 remoteEP, scene, packServer, sessionInfo, agentId, sessionId, circuitCode, proxyEP,
97 m_userSettings);
98 }
99
100 /// <summary>
101 /// Check whether a given client is authorized to connect.
102 /// </summary>
103 /// <param name="useCircuit"></param>
104 /// <param name="circuitManager"></param>
105 /// <param name="sessionInfo"></param>
106 /// <returns></returns>
107 public virtual bool IsClientAuthorized(
108 UseCircuitCodePacket useCircuit, AgentCircuitManager circuitManager, out AuthenticateResponse sessionInfo)
109 {
110 UUID agentId = useCircuit.CircuitCode.ID;
111 UUID sessionId = useCircuit.CircuitCode.SessionID;
112 uint circuitCode = useCircuit.CircuitCode.Code;
113
114 sessionInfo = circuitManager.AuthenticateSession(sessionId, agentId, circuitCode);
115
116 if (!sessionInfo.Authorised)
117 return false;
118
119 return true;
120 }
121
122 /// <summary>
123 /// Add a new client circuit. We assume that is has already passed an authorization check
124 /// </summary>
125 /// <param name="epSender"></param>
126 /// <param name="useCircuit"></param>
127 /// <param name="assetCache"></param>
128 /// <param name="sessionInfo"></param>
129 /// <param name="proxyEP"></param>
130 /// <returns>
131 /// true if a new circuit was created, false if a circuit with the given circuit code already existed
132 /// </returns>
133 public virtual bool AddNewClient(
134 EndPoint epSender, UseCircuitCodePacket useCircuit,
135 AuthenticateResponse sessionInfo, EndPoint proxyEP)
136 {
137 IClientAPI newuser;
138 uint circuitCode = useCircuit.CircuitCode.Code;
139
140 if (m_scene.ClientManager.TryGetClient(circuitCode, out newuser))
141 {
142 // The circuit is already known to the scene. This not actually a problem since this will currently
143 // occur if a client is crossing borders (hence upgrading its circuit). However, we shouldn't
144 // really by trying to add a new client if this is the case.
145 return false;
146 }
147
148 UUID agentId = useCircuit.CircuitCode.ID;
149 UUID sessionId = useCircuit.CircuitCode.SessionID;
150
151 newuser
152 = CreateNewCircuit(
153 epSender, m_scene, this, sessionInfo, agentId, sessionId, circuitCode, proxyEP);
154
155 m_scene.ClientManager.Add(circuitCode, newuser);
156
157 newuser.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
158 newuser.OnLogout += LogoutHandler;
159 newuser.OnConnectionClosed += CloseClient;
160
161 newuser.Start();
162
163 return true;
164 }
165
166 public void LogoutHandler(IClientAPI client)
167 {
168 client.SendLogoutPacket();
169 CloseClient(client);
170 }
171
172 /// <summary>
173 /// Send a packet to the given circuit
174 /// </summary>
175 /// <param name="buffer"></param>
176 /// <param name="size"></param>
177 /// <param name="flags"></param>
178 /// <param name="circuitcode"></param>
179 public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode)
180 {
181 m_networkHandler.SendPacketTo(buffer, size, flags, circuitcode);
182 }
183
184 /// <summary>
185 /// Close a client circuit only
186 /// </summary>
187 /// <param name="circuitcode"></param>
188 public virtual void CloseCircuit(uint circuitcode)
189 {
190 m_networkHandler.RemoveClientCircuit(circuitcode);
191 }
192
193 /// <summary>
194 /// Completely close down the given client.
195 /// </summary>
196 /// <param name="client"></param>
197 public virtual void CloseClient(IClientAPI client)
198 {
199 //m_log.Info("PacketServer:CloseClient()");
200
201 CloseCircuit(client.CircuitCode);
202 m_scene.ClientManager.Remove(client.CircuitCode);
203 client.Close(false);
204 }
205 }
206}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs b/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs
deleted file mode 100644
index 52effc5..0000000
--- a/OpenSim/Region/ClientStack/LindenUDP/LLPacketThrottle.cs
+++ /dev/null
@@ -1,128 +0,0 @@
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 OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28namespace OpenSim.Region.ClientStack.LindenUDP
29{
30 public class LLPacketThrottle
31 {
32 private readonly int m_maxAllowableThrottle;
33 private readonly int m_minAllowableThrottle;
34 private int m_currentThrottle;
35 private const int m_throttleTimeDivisor = 7;
36 private int m_currentBitsSent;
37 private int m_throttleBits;
38
39 /// <value>
40 /// Value with which to multiply all the throttle fields
41 /// </value>
42 private float m_throttleMultiplier;
43
44 public int Max
45 {
46 get { return m_maxAllowableThrottle; }
47 }
48
49 public int Min
50 {
51 get { return m_minAllowableThrottle; }
52 }
53
54 public int Current
55 {
56 get { return m_currentThrottle; }
57 }
58
59 /// <summary>
60 /// Constructor.
61 /// </summary>
62 /// <param name="min"></param>
63 /// <param name="max"></param>
64 /// <param name="throttle"></param>
65 /// <param name="throttleMultiplier">
66 /// A parameter that's ends up multiplying all throttle settings. An alternative solution would have been
67 /// to multiply all the parameters by this before giving them to the constructor. But doing it this way
68 /// represents the fact that the multiplier is a hack that pumps data to clients much faster than the actual
69 /// settings that we are given.
70 /// </param>
71 public LLPacketThrottle(int min, int max, int throttle, float throttleMultiplier)
72 {
73 m_throttleMultiplier = throttleMultiplier;
74 m_maxAllowableThrottle = max;
75 m_minAllowableThrottle = min;
76 m_currentThrottle = throttle;
77 m_currentBitsSent = 0;
78
79 CalcBits();
80 }
81
82 /// <summary>
83 /// Calculate the actual throttle required.
84 /// </summary>
85 private void CalcBits()
86 {
87 m_throttleBits = (int)((float)m_currentThrottle * m_throttleMultiplier / (float)m_throttleTimeDivisor);
88 }
89
90 public void Reset()
91 {
92 m_currentBitsSent = 0;
93 }
94
95 public bool UnderLimit()
96 {
97 return m_currentBitsSent < m_throttleBits;
98 }
99
100 public int AddBytes(int bytes)
101 {
102 m_currentBitsSent += bytes * 8;
103 return m_currentBitsSent;
104 }
105
106 public int Throttle
107 {
108 get { return m_currentThrottle; }
109 set
110 {
111 if (value < m_minAllowableThrottle)
112 {
113 m_currentThrottle = m_minAllowableThrottle;
114 }
115 else if (value > m_maxAllowableThrottle)
116 {
117 m_currentThrottle = m_maxAllowableThrottle;
118 }
119 else
120 {
121 m_currentThrottle = value;
122 }
123
124 CalcBits();
125 }
126 }
127 }
128}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
new file mode 100644
index 0000000..871e8e8
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -0,0 +1,442 @@
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 OpenSimulator 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 OpenSim.Framework;
32using OpenMetaverse;
33
34namespace OpenSim.Region.ClientStack.LindenUDP
35{
36 #region Delegates
37
38 /// <summary>
39 /// Fired when updated networking stats are produced for this client
40 /// </summary>
41 /// <param name="inPackets">Number of incoming packets received since this
42 /// event was last fired</param>
43 /// <param name="outPackets">Number of outgoing packets sent since this
44 /// event was last fired</param>
45 /// <param name="unAckedBytes">Current total number of bytes in packets we
46 /// are waiting on ACKs for</param>
47 public delegate void PacketStats(int inPackets, int outPackets, int unAckedBytes);
48 /// <summary>
49 /// Fired when the queue for a packet category is empty. This event can be
50 /// hooked to put more data on the empty queue
51 /// </summary>
52 /// <param name="category">Category of the packet queue that is empty</param>
53 public delegate void QueueEmpty(ThrottleOutPacketType category);
54
55 #endregion Delegates
56
57 /// <summary>
58 /// Tracks state for a client UDP connection and provides client-specific methods
59 /// </summary>
60 public sealed class LLUDPClient
61 {
62 /// <summary>The number of packet categories to throttle on. If a throttle category is added
63 /// or removed, this number must also change</summary>
64 const int THROTTLE_CATEGORY_COUNT = 7;
65
66 /// <summary>Fired when updated networking stats are produced for this client</summary>
67 public event PacketStats OnPacketStats;
68 /// <summary>Fired when the queue for a packet category is empty. This event can be
69 /// hooked to put more data on the empty queue</summary>
70 public event QueueEmpty OnQueueEmpty;
71
72 /// <summary>AgentID for this client</summary>
73 public readonly UUID AgentID;
74 /// <summary>The remote address of the connected client</summary>
75 public readonly IPEndPoint RemoteEndPoint;
76 /// <summary>Circuit code that this client is connected on</summary>
77 public readonly uint CircuitCode;
78 /// <summary>Sequence numbers of packets we've received (for duplicate checking)</summary>
79 public readonly IncomingPacketHistoryCollection PacketArchive = new IncomingPacketHistoryCollection(200);
80 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
81 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
82 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
83 public readonly LocklessQueue<uint> PendingAcks = new LocklessQueue<uint>();
84
85 /// <summary>Reference to the IClientAPI for this client</summary>
86 public LLClientView ClientAPI;
87 /// <summary>Current packet sequence number</summary>
88 public int CurrentSequence;
89 /// <summary>Current ping sequence number</summary>
90 public byte CurrentPingSequence;
91 /// <summary>True when this connection is alive, otherwise false</summary>
92 public bool IsConnected = true;
93 /// <summary>True when this connection is paused, otherwise false</summary>
94 public bool IsPaused = true;
95 /// <summary>Environment.TickCount when the last packet was received for this client</summary>
96 public int TickLastPacketReceived;
97
98 /// <summary>Timer granularity. This is set to the measured resolution of Environment.TickCount</summary>
99 public readonly float G;
100 /// <summary>Smoothed round-trip time. A smoothed average of the round-trip time for sending a
101 /// reliable packet to the client and receiving an ACK</summary>
102 public float SRTT;
103 /// <summary>Round-trip time variance. Measures the consistency of round-trip times</summary>
104 public float RTTVAR;
105 /// <summary>Retransmission timeout. Packets that have not been acknowledged in this number of
106 /// milliseconds or longer will be resent</summary>
107 /// <remarks>Calculated from <seealso cref="SRTT"/> and <seealso cref="RTTVAR"/> using the
108 /// guidelines in RFC 2988</remarks>
109 public int RTO;
110 /// <summary>Number of bytes received since the last acknowledgement was sent out. This is used
111 /// to loosely follow the TCP delayed ACK algorithm in RFC 1122 (4.2.3.2)</summary>
112 public int BytesSinceLastACK;
113 /// <summary>Number of packets received from this client</summary>
114 public int PacketsReceived;
115 /// <summary>Number of packets sent to this client</summary>
116 public int PacketsSent;
117 /// <summary>Total byte count of unacked packets sent to this client</summary>
118 public int UnackedBytes;
119
120 /// <summary>Total number of received packets that we have reported to the OnPacketStats event(s)</summary>
121 private int m_packetsReceivedReported;
122 /// <summary>Total number of sent packets that we have reported to the OnPacketStats event(s)</summary>
123 private int m_packetsSentReported;
124
125 /// <summary>Throttle bucket for this agent's connection</summary>
126 private readonly TokenBucket throttle;
127 /// <summary>Throttle buckets for each packet category</summary>
128 private readonly TokenBucket[] throttleCategories;
129 /// <summary>Throttle rate defaults and limits</summary>
130 private readonly ThrottleRates defaultThrottleRates;
131 /// <summary>Outgoing queues for throttled packets</summary>
132 private readonly LocklessQueue<OutgoingPacket>[] packetOutboxes = new LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
133 /// <summary>A container that can hold one packet for each outbox, used to store
134 /// dequeued packets that are being held for throttling</summary>
135 private readonly OutgoingPacket[] nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
136 /// <summary>An optimization to store the length of dequeued packets being held
137 /// for throttling. This avoids expensive calls to Packet.Length</summary>
138 private readonly int[] nextPacketLengths = new int[THROTTLE_CATEGORY_COUNT];
139 /// <summary>A reference to the LLUDPServer that is managing this client</summary>
140 private readonly LLUDPServer udpServer;
141
142 /// <summary>
143 /// Default constructor
144 /// </summary>
145 /// <param name="server">Reference to the UDP server this client is connected to</param>
146 /// <param name="rates">Default throttling rates and maximum throttle limits</param>
147 /// <param name="parentThrottle">Parent HTB (hierarchical token bucket)
148 /// that the child throttles will be governed by</param>
149 /// <param name="circuitCode">Circuit code for this connection</param>
150 /// <param name="agentID">AgentID for the connected agent</param>
151 /// <param name="remoteEndPoint">Remote endpoint for this connection</param>
152 public LLUDPClient(LLUDPServer server, ThrottleRates rates, TokenBucket parentThrottle, uint circuitCode, UUID agentID, IPEndPoint remoteEndPoint)
153 {
154 udpServer = server;
155 AgentID = agentID;
156 RemoteEndPoint = remoteEndPoint;
157 CircuitCode = circuitCode;
158 defaultThrottleRates = rates;
159
160 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
161 packetOutboxes[i] = new LocklessQueue<OutgoingPacket>();
162
163 throttle = new TokenBucket(parentThrottle, 0, 0);
164 throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
165 throttleCategories[(int)ThrottleOutPacketType.Resend] = new TokenBucket(throttle, rates.ResendLimit, rates.Resend);
166 throttleCategories[(int)ThrottleOutPacketType.Land] = new TokenBucket(throttle, rates.LandLimit, rates.Land);
167 throttleCategories[(int)ThrottleOutPacketType.Wind] = new TokenBucket(throttle, rates.WindLimit, rates.Wind);
168 throttleCategories[(int)ThrottleOutPacketType.Cloud] = new TokenBucket(throttle, rates.CloudLimit, rates.Cloud);
169 throttleCategories[(int)ThrottleOutPacketType.Task] = new TokenBucket(throttle, rates.TaskLimit, rates.Task);
170 throttleCategories[(int)ThrottleOutPacketType.Texture] = new TokenBucket(throttle, rates.TextureLimit, rates.Texture);
171 throttleCategories[(int)ThrottleOutPacketType.Asset] = new TokenBucket(throttle, rates.AssetLimit, rates.Asset);
172
173 // Set the granularity variable used for retransmission calculations to
174 // the measured resolution of Environment.TickCount
175 G = server.TickCountResolution;
176
177 // Default the retransmission timeout to three seconds
178 RTO = 3000;
179 }
180
181 /// <summary>
182 /// Shuts down this client connection
183 /// </summary>
184 public void Shutdown()
185 {
186 // TODO: Do we need to invalidate the circuit?
187 IsConnected = false;
188 }
189
190 /// <summary>
191 /// Gets information about this client connection
192 /// </summary>
193 /// <returns>Information about the client connection</returns>
194 public ClientInfo GetClientInfo()
195 {
196 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
197 // of pending and needed ACKs for every client every time some method wants information about
198 // this connection is a recipe for poor performance
199 ClientInfo info = new ClientInfo();
200 info.pendingAcks = new Dictionary<uint, uint>();
201 info.needAck = new Dictionary<uint, byte[]>();
202
203 info.resendThrottle = throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
204 info.landThrottle = throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
205 info.windThrottle = throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
206 info.cloudThrottle = throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
207 info.taskThrottle = throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
208 info.assetThrottle = throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
209 info.textureThrottle = throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
210 info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
211 info.taskThrottle + info.assetThrottle + info.textureThrottle;
212
213 return info;
214 }
215
216 /// <summary>
217 /// Modifies the UDP throttles
218 /// </summary>
219 /// <param name="info">New throttling values</param>
220 public void SetClientInfo(ClientInfo info)
221 {
222 // TODO: Allowing throttles to be manually set from this function seems like a reasonable
223 // idea. On the other hand, letting external code manipulate our ACK accounting is not
224 // going to happen
225 throw new NotImplementedException();
226 }
227
228 public string GetStats()
229 {
230 // TODO: ???
231 return string.Format("{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7}",
232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
233 }
234
235 public void SendPacketStats()
236 {
237 PacketStats callback = OnPacketStats;
238 if (callback != null)
239 {
240 int newPacketsReceived = PacketsReceived - m_packetsReceivedReported;
241 int newPacketsSent = PacketsSent - m_packetsSentReported;
242
243 callback(newPacketsReceived, newPacketsSent, UnackedBytes);
244
245 m_packetsReceivedReported += newPacketsReceived;
246 m_packetsSentReported += newPacketsSent;
247 }
248 }
249
250 public void SetThrottles(byte[] throttleData)
251 {
252 byte[] adjData;
253 int pos = 0;
254
255 if (!BitConverter.IsLittleEndian)
256 {
257 byte[] newData = new byte[7 * 4];
258 Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4);
259
260 for (int i = 0; i < 7; i++)
261 Array.Reverse(newData, i * 4, 4);
262
263 adjData = newData;
264 }
265 else
266 {
267 adjData = throttleData;
268 }
269
270 int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
271 int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
272 int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
273 int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
274 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
275 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4;
276 int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
277
278 resend = (resend <= defaultThrottleRates.ResendLimit) ? resend : defaultThrottleRates.ResendLimit;
279 land = (land <= defaultThrottleRates.LandLimit) ? land : defaultThrottleRates.LandLimit;
280 wind = (wind <= defaultThrottleRates.WindLimit) ? wind : defaultThrottleRates.WindLimit;
281 cloud = (cloud <= defaultThrottleRates.CloudLimit) ? cloud : defaultThrottleRates.CloudLimit;
282 task = (task <= defaultThrottleRates.TaskLimit) ? task : defaultThrottleRates.TaskLimit;
283 texture = (texture <= defaultThrottleRates.TextureLimit) ? texture : defaultThrottleRates.TextureLimit;
284 asset = (asset <= defaultThrottleRates.AssetLimit) ? asset : defaultThrottleRates.AssetLimit;
285
286 SetThrottle(ThrottleOutPacketType.Resend, resend);
287 SetThrottle(ThrottleOutPacketType.Land, land);
288 SetThrottle(ThrottleOutPacketType.Wind, wind);
289 SetThrottle(ThrottleOutPacketType.Cloud, cloud);
290 SetThrottle(ThrottleOutPacketType.Task, task);
291 SetThrottle(ThrottleOutPacketType.Texture, texture);
292 SetThrottle(ThrottleOutPacketType.Asset, asset);
293 }
294
295 public byte[] GetThrottlesPacked()
296 {
297 byte[] data = new byte[7 * 4];
298 int i = 0;
299
300 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4;
301 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4;
302 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4;
303 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4;
304 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Task].DripRate), 0, data, i, 4); i += 4;
305 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4;
306 Buffer.BlockCopy(Utils.FloatToBytes((float)throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4;
307
308 return data;
309 }
310
311 public void SetThrottle(ThrottleOutPacketType category, int rate)
312 {
313 int i = (int)category;
314 if (i >= 0 && i < throttleCategories.Length)
315 {
316 TokenBucket bucket = throttleCategories[(int)category];
317 bucket.MaxBurst = rate;
318 bucket.DripRate = rate;
319 }
320 }
321
322 public bool EnqueueOutgoing(OutgoingPacket packet)
323 {
324 int category = (int)packet.Category;
325
326 if (category >= 0 && category < packetOutboxes.Length)
327 {
328 LocklessQueue<OutgoingPacket> queue = packetOutboxes[category];
329 TokenBucket bucket = throttleCategories[category];
330
331 if (throttleCategories[category].RemoveTokens(packet.Buffer.DataLength))
332 {
333 // Enough tokens were removed from the bucket, the packet will not be queued
334 return false;
335 }
336 else
337 {
338 // Not enough tokens in the bucket, queue this packet
339 queue.Enqueue(packet);
340 return true;
341 }
342 }
343 else
344 {
345 // We don't have a token bucket for this category, so it will not be queued
346 return false;
347 }
348 }
349
350 /// <summary>
351 /// Loops through all of the packet queues for this client and tries to send
352 /// any outgoing packets, obeying the throttling bucket limits
353 /// </summary>
354 /// <remarks>This function is only called from a synchronous loop in the
355 /// UDPServer so we don't need to bother making this thread safe</remarks>
356 /// <returns>True if any packets were sent, otherwise false</returns>
357 public bool DequeueOutgoing()
358 {
359 OutgoingPacket packet;
360 LocklessQueue<OutgoingPacket> queue;
361 TokenBucket bucket;
362 bool packetSent = false;
363
364 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
365 {
366 bucket = throttleCategories[i];
367
368 if (nextPackets[i] != null)
369 {
370 // This bucket was empty the last time we tried to send a packet,
371 // leaving a dequeued packet still waiting to be sent out. Try to
372 // send it again
373 if (bucket.RemoveTokens(nextPacketLengths[i]))
374 {
375 // Send the packet
376 udpServer.SendPacketFinal(nextPackets[i]);
377 nextPackets[i] = null;
378 packetSent = true;
379 }
380 }
381 else
382 {
383 // No dequeued packet waiting to be sent, try to pull one off
384 // this queue
385 queue = packetOutboxes[i];
386 if (queue.Dequeue(out packet))
387 {
388 // A packet was pulled off the queue. See if we have
389 // enough tokens in the bucket to send it out
390 if (bucket.RemoveTokens(packet.Buffer.DataLength))
391 {
392 // Send the packet
393 udpServer.SendPacketFinal(packet);
394 packetSent = true;
395 }
396 else
397 {
398 // Save the dequeued packet and the length calculation for
399 // the next iteration
400 nextPackets[i] = packet;
401 nextPacketLengths[i] = packet.Buffer.DataLength;
402 }
403 }
404 else
405 {
406 // No packets in this queue. Fire the queue empty callback
407 QueueEmpty callback = OnQueueEmpty;
408 if (callback != null)
409 callback((ThrottleOutPacketType)i);
410 }
411 }
412 }
413
414 return packetSent;
415 }
416
417 public void UpdateRoundTrip(float r)
418 {
419 const float ALPHA = 0.125f;
420 const float BETA = 0.25f;
421 const float K = 4.0f;
422
423 if (RTTVAR == 0.0f)
424 {
425 // First RTT measurement
426 SRTT = r;
427 RTTVAR = r * 0.5f;
428 }
429 else
430 {
431 // Subsequence RTT measurement
432 RTTVAR = (1.0f - BETA) * RTTVAR + BETA * Math.Abs(SRTT - r);
433 SRTT = (1.0f - ALPHA) * SRTT + ALPHA * r;
434 }
435
436 // Always round retransmission timeout up to two seconds
437 RTO = Math.Max(2000, (int)(SRTT + Math.Max(G, K * RTTVAR)));
438 //Logger.Debug("Setting agent " + this.Agent.FullName + "'s RTO to " + RTO + "ms with an RTTVAR of " +
439 // RTTVAR + " based on new RTT of " + r + "ms");
440 }
441 }
442}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
new file mode 100644
index 0000000..7d2da68
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClientCollection.cs
@@ -0,0 +1,185 @@
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 OpenSimulator 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 OpenSim.Framework;
32using OpenMetaverse;
33
34using ReaderWriterLockImpl = OpenMetaverse.ReaderWriterLockSlim;
35
36namespace OpenSim.Region.ClientStack.LindenUDP
37{
38 public sealed class UDPClientCollection
39 {
40 Dictionary<UUID, LLUDPClient> Dictionary1;
41 Dictionary<IPEndPoint, LLUDPClient> Dictionary2;
42 LLUDPClient[] Array;
43 ReaderWriterLockImpl rwLock = new ReaderWriterLockImpl();
44
45 public UDPClientCollection()
46 {
47 Dictionary1 = new Dictionary<UUID, LLUDPClient>();
48 Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>();
49 Array = new LLUDPClient[0];
50 }
51
52 public UDPClientCollection(int capacity)
53 {
54 Dictionary1 = new Dictionary<UUID, LLUDPClient>(capacity);
55 Dictionary2 = new Dictionary<IPEndPoint, LLUDPClient>(capacity);
56 Array = new LLUDPClient[0];
57 }
58
59 public void Add(UUID key1, IPEndPoint key2, LLUDPClient value)
60 {
61 rwLock.EnterWriteLock();
62
63 try
64 {
65 if (Dictionary1.ContainsKey(key1))
66 {
67 if (!Dictionary2.ContainsKey(key2))
68 throw new ArgumentException("key1 exists in the dictionary but not key2");
69 }
70 else if (Dictionary2.ContainsKey(key2))
71 {
72 if (!Dictionary1.ContainsKey(key1))
73 throw new ArgumentException("key2 exists in the dictionary but not key1");
74 }
75
76 Dictionary1[key1] = value;
77 Dictionary2[key2] = value;
78
79 LLUDPClient[] oldArray = Array;
80 int oldLength = oldArray.Length;
81
82 LLUDPClient[] newArray = new LLUDPClient[oldLength + 1];
83 for (int i = 0; i < oldLength; i++)
84 newArray[i] = oldArray[i];
85 newArray[oldLength] = value;
86
87 Array = newArray;
88 }
89 finally { rwLock.ExitWriteLock(); }
90 }
91
92 public bool Remove(UUID key1, IPEndPoint key2)
93 {
94 rwLock.EnterWriteLock();
95
96 try
97 {
98 LLUDPClient value;
99 if (Dictionary1.TryGetValue(key1, out value))
100 {
101 Dictionary1.Remove(key1);
102 Dictionary2.Remove(key2);
103
104 LLUDPClient[] oldArray = Array;
105 int oldLength = oldArray.Length;
106
107 LLUDPClient[] newArray = new LLUDPClient[oldLength - 1];
108 int j = 0;
109 for (int i = 0; i < oldLength; i++)
110 {
111 if (oldArray[i] != value)
112 newArray[j++] = oldArray[i];
113 }
114
115 Array = newArray;
116 return true;
117 }
118 }
119 finally { rwLock.ExitWriteLock(); }
120
121 return false;
122 }
123
124 public void Clear()
125 {
126 rwLock.EnterWriteLock();
127
128 try
129 {
130 Dictionary1.Clear();
131 Dictionary2.Clear();
132 Array = new LLUDPClient[0];
133 }
134 finally { rwLock.ExitWriteLock(); }
135 }
136
137 public int Count
138 {
139 get { return Array.Length; }
140 }
141
142 public bool ContainsKey(UUID key)
143 {
144 return Dictionary1.ContainsKey(key);
145 }
146
147 public bool ContainsKey(IPEndPoint key)
148 {
149 return Dictionary2.ContainsKey(key);
150 }
151
152 public bool TryGetValue(UUID key, out LLUDPClient value)
153 {
154 bool success;
155 bool doLock = !rwLock.IsUpgradeableReadLockHeld;
156 if (doLock) rwLock.EnterReadLock();
157
158 try { success = Dictionary1.TryGetValue(key, out value); }
159 finally { if (doLock) rwLock.ExitReadLock(); }
160
161 return success;
162 }
163
164 public bool TryGetValue(IPEndPoint key, out LLUDPClient value)
165 {
166 bool success;
167 bool doLock = !rwLock.IsUpgradeableReadLockHeld;
168 if (doLock) rwLock.EnterReadLock();
169
170 try { success = Dictionary2.TryGetValue(key, out value); }
171 finally { if (doLock) rwLock.ExitReadLock(); }
172
173 return success;
174 }
175
176 public void ForEach(Action<LLUDPClient> action)
177 {
178 bool doLock = !rwLock.IsUpgradeableReadLockHeld;
179 if (doLock) rwLock.EnterUpgradeableReadLock();
180
181 try { Parallel.ForEach<LLUDPClient>(Array, action); }
182 finally { if (doLock) rwLock.ExitUpgradeableReadLock(); }
183 }
184 }
185}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index c779b08..c0a84a8 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -26,616 +26,779 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Collections.Generic; 29using System.Collections.Generic;
31using System.Net; 30using System.Net;
32using System.Net.Sockets; 31using System.Net.Sockets;
33using System.Reflection; 32using System.Reflection;
33using System.Threading;
34using log4net; 34using log4net;
35using Nini.Config; 35using Nini.Config;
36using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Statistics;
38using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using OpenMetaverse;
39 41
40namespace OpenSim.Region.ClientStack.LindenUDP 42namespace OpenSim.Region.ClientStack.LindenUDP
41{ 43{
42 /// <summary> 44 /// <summary>
43 /// This class handles the initial UDP circuit setup with a client and passes on subsequent packets to the LLPacketServer 45 /// A shim around LLUDPServer that implements the IClientNetworkServer interface
44 /// </summary> 46 /// </summary>
45 public class LLUDPServer : ILLClientStackNetworkHandler, IClientNetworkServer 47 public sealed class LLUDPServerShim : IClientNetworkServer
46 { 48 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 LLUDPServer m_udpServer;
48
49 /// <value>
50 /// The client circuits established with this UDP server. If a client exists here we can also assume that
51 /// it is populated in clientCircuits_reverse and proxyCircuits (if relevant)
52 /// </value>
53 protected Dictionary<EndPoint, uint> clientCircuits = new Dictionary<EndPoint, uint>();
54 public Hashtable clientCircuits_reverse = Hashtable.Synchronized(new Hashtable());
55 protected Dictionary<uint, EndPoint> proxyCircuits = new Dictionary<uint, EndPoint>();
56
57 private Socket m_socket;
58 protected IPEndPoint ServerIncoming;
59 protected byte[] RecvBuffer = new byte[4096];
60 protected byte[] ZeroBuffer = new byte[8192];
61 50
62 /// <value> 51 public LLUDPServerShim()
63 /// This is an endpoint that is reused where we don't need to protect the information from potentially 52 {
64 /// being stomped on by other threads. 53 }
65 /// </value>
66 protected EndPoint reusedEpSender = new IPEndPoint(IPAddress.Any, 0);
67
68 protected int proxyPortOffset;
69
70 protected AsyncCallback ReceivedData;
71 protected LLPacketServer m_packetServer;
72 protected Location m_location;
73 54
74 protected uint listenPort; 55 public void Initialise(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
75 protected bool Allow_Alternate_Port; 56 {
76 protected IPAddress listenIP = IPAddress.Parse("0.0.0.0"); 57 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager);
77 protected IScene m_localScene; 58 }
78 protected int m_clientSocketReceiveBuffer = 0;
79 59
80 /// <value> 60 public void NetworkStop()
81 /// Manages authentication for agent circuits 61 {
82 /// </value> 62 m_udpServer.Stop();
83 protected AgentCircuitManager m_circuitManager; 63 }
84 64
85 public IScene LocalScene 65 public void AddScene(IScene scene)
86 { 66 {
87 set 67 m_udpServer.AddScene(scene);
88 { 68 }
89 m_localScene = value;
90 m_packetServer.LocalScene = m_localScene;
91 69
92 m_location = new Location(m_localScene.RegionInfo.RegionHandle); 70 public bool HandlesRegion(Location x)
93 } 71 {
72 return m_udpServer.HandlesRegion(x);
94 } 73 }
95 74
96 public ulong RegionHandle 75 public void Start()
97 { 76 {
98 get { return m_location.RegionHandle; } 77 m_udpServer.Start();
99 } 78 }
100 79
101 Socket IClientNetworkServer.Server 80 public void Stop()
102 { 81 {
103 get { return m_socket; } 82 m_udpServer.Stop();
104 } 83 }
84 }
105 85
106 public bool HandlesRegion(Location x) 86 /// <summary>
87 /// The LLUDP server for a region. This handles incoming and outgoing
88 /// packets for all UDP connections to the region
89 /// </summary>
90 public class LLUDPServer : UDPBase
91 {
92 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
93
94 /// <summary>Handlers for incoming packets</summary>
95 //PacketEventDictionary packetEvents = new PacketEventDictionary();
96 /// <summary>Incoming packets that are awaiting handling</summary>
97 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
98 /// <summary></summary>
99 private UDPClientCollection clients = new UDPClientCollection();
100 /// <summary>Bandwidth throttle for this UDP server</summary>
101 private TokenBucket m_throttle;
102 /// <summary>Bandwidth throttle rates for this UDP server</summary>
103 private ThrottleRates m_throttleRates;
104 /// <summary>Manages authentication for agent circuits</summary>
105 private AgentCircuitManager m_circuitManager;
106 /// <summary>Reference to the scene this UDP server is attached to</summary>
107 private IScene m_scene;
108 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
109 private Location m_location;
110 /// <summary>The measured resolution of Environment.TickCount</summary>
111 private float m_tickCountResolution;
112
113 /// <summary>The measured resolution of Environment.TickCount</summary>
114 public float TickCountResolution { get { return m_tickCountResolution; } }
115 public Socket Server { get { return null; } }
116
117 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
118 : base((int)port)
107 { 119 {
108 //return x.RegionHandle == m_location.RegionHandle; 120 #region Environment.TickCount Measurement
109 return x == m_location; 121
122 // Measure the resolution of Environment.TickCount
123 m_tickCountResolution = 0f;
124 for (int i = 0; i < 5; i++)
125 {
126 int start = Environment.TickCount;
127 int now = start;
128 while (now == start)
129 now = Environment.TickCount;
130 m_tickCountResolution += (float)(now - start) * 0.2f;
131 }
132 m_log.Info("[LLUDPSERVER]: Average Environment.TickCount resolution: " + TickCountResolution + "ms");
133
134 #endregion Environment.TickCount Measurement
135
136 m_circuitManager = circuitManager;
137
138 // TODO: Config support for throttling the entire connection
139 m_throttle = new TokenBucket(null, 0, 0);
140 m_throttleRates = new ThrottleRates(configSource);
110 } 141 }
111 142
112 public void AddScene(IScene x) 143 public new void Start()
113 { 144 {
114 LocalScene = x; 145 if (m_scene == null)
146 throw new InvalidOperationException("Cannot LLUDPServer.Start() without an IScene reference");
147
148 base.Start();
149
150 // Start the incoming packet processing thread
151 Thread incomingThread = new Thread(IncomingPacketHandler);
152 incomingThread.Name = "Incoming Packets (" + m_scene.RegionInfo.RegionName + ")";
153 incomingThread.Start();
154
155 Thread outgoingThread = new Thread(OutgoingPacketHandler);
156 outgoingThread.Name = "Outgoing Packets (" + m_scene.RegionInfo.RegionName + ")";
157 outgoingThread.Start();
115 } 158 }
116 159
117 public void Start() 160 public new void Stop()
118 { 161 {
119 ServerListener(); 162 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
163 base.Stop();
120 } 164 }
121 165
122 public void Stop() 166 public void AddScene(IScene scene)
123 { 167 {
124 m_socket.Close(); 168 if (m_scene == null)
169 {
170 m_scene = scene;
171 m_location = new Location(m_scene.RegionInfo.RegionHandle);
172 }
173 else
174 {
175 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
176 }
125 } 177 }
126 178
127 public LLUDPServer() 179 public bool HandlesRegion(Location x)
128 { 180 {
181 return x == m_location;
129 } 182 }
130 183
131 public LLUDPServer( 184 public void RemoveClient(IClientAPI client)
132 IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, IConfigSource configSource,
133 AgentCircuitManager authenticateClass)
134 { 185 {
135 Initialise(_listenIP, ref port, proxyPortOffset, allow_alternate_port, configSource, authenticateClass); 186 m_scene.ClientManager.Remove(client.CircuitCode);
187 client.Close(false);
188
189 LLUDPClient udpClient;
190 if (clients.TryGetValue(client.AgentId, out udpClient))
191 {
192 m_log.Debug("[LLUDPSERVER]: Removing LLUDPClient for " + client.Name);
193 udpClient.Shutdown();
194 clients.Remove(client.AgentId, udpClient.RemoteEndPoint);
195 }
196 else
197 {
198 m_log.Warn("[LLUDPSERVER]: Failed to remove LLUDPClient for " + client.Name);
199 }
136 } 200 }
137 201
138 /// <summary> 202 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
139 /// Initialize the server
140 /// </summary>
141 /// <param name="_listenIP"></param>
142 /// <param name="port"></param>
143 /// <param name="proxyPortOffsetParm"></param>
144 /// <param name="allow_alternate_port"></param>
145 /// <param name="configSource"></param>
146 /// <param name="assetCache"></param>
147 /// <param name="circuitManager"></param>
148 public void Initialise(
149 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource,
150 AgentCircuitManager circuitManager)
151 { 203 {
152 ClientStackUserSettings userSettings = new ClientStackUserSettings(); 204 // CoarseLocationUpdate packets cannot be split in an automated way
153 205 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
154 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 206 allowSplitting = false;
155 207
156 if (config != null) 208 if (allowSplitting && packet.HasVariableBlocks)
157 { 209 {
158 if (config.Contains("client_throttle_max_bps")) 210 byte[][] datas = packet.ToBytesMultiple();
159 { 211 int packetCount = datas.Length;
160 int maxBPS = config.GetInt("client_throttle_max_bps", 1500000);
161 userSettings.TotalThrottleSettings = new ThrottleSettings(0, maxBPS,
162 maxBPS > 28000 ? maxBPS : 28000);
163 }
164 212
165 if (config.Contains("client_throttle_multiplier")) 213 if (packetCount > 1)
166 userSettings.ClientThrottleMultipler = config.GetFloat("client_throttle_multiplier"); 214 m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets");
167 if (config.Contains("client_socket_rcvbuf_size"))
168 m_clientSocketReceiveBuffer = config.GetInt("client_socket_rcvbuf_size");
169 }
170
171 m_log.DebugFormat("[CLIENT]: client_throttle_multiplier = {0}", userSettings.ClientThrottleMultipler);
172 m_log.DebugFormat("[CLIENT]: client_socket_rcvbuf_size = {0}", (m_clientSocketReceiveBuffer != 0 ?
173 m_clientSocketReceiveBuffer.ToString() : "OS default"));
174
175 proxyPortOffset = proxyPortOffsetParm;
176 listenPort = (uint) (port + proxyPortOffsetParm);
177 listenIP = _listenIP;
178 Allow_Alternate_Port = allow_alternate_port;
179 m_circuitManager = circuitManager;
180 CreatePacketServer(userSettings);
181 215
182 // Return new port 216 for (int i = 0; i < packetCount; i++)
183 // This because in Grid mode it is not really important what port the region listens to as long as it is correctly registered. 217 {
184 // So the option allow_alternate_ports="true" was added to default.xml 218 byte[] data = datas[i];
185 port = (uint)(listenPort - proxyPortOffsetParm); 219 clients.ForEach(
220 delegate(LLUDPClient client)
221 { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); });
222 }
223 }
224 else
225 {
226 byte[] data = packet.ToBytes();
227 clients.ForEach(
228 delegate(LLUDPClient client)
229 { SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category); });
230 }
186 } 231 }
187 232
188 protected virtual void CreatePacketServer(ClientStackUserSettings userSettings) 233 public void SendPacket(UUID agentID, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
189 { 234 {
190 new LLPacketServer(this, userSettings); 235 LLUDPClient client;
236 if (clients.TryGetValue(agentID, out client))
237 SendPacket(client, packet, category, allowSplitting);
238 else
239 m_log.Warn("[LLUDPSERVER]: Attempted to send a packet to unknown agentID " + agentID);
191 } 240 }
192 241
193 /// <summary> 242 public void SendPacket(LLUDPClient client, Packet packet, ThrottleOutPacketType category, bool allowSplitting)
194 /// This method is called every time that we receive new UDP data.
195 /// </summary>
196 /// <param name="result"></param>
197 protected virtual void OnReceivedData(IAsyncResult result)
198 { 243 {
199 Packet packet = null; 244 // CoarseLocationUpdate packets cannot be split in an automated way
200 int numBytes = 1; 245 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
201 EndPoint epSender = new IPEndPoint(IPAddress.Any, 0); 246 allowSplitting = false;
202 EndPoint epProxy = null;
203 247
204 try 248 if (allowSplitting && packet.HasVariableBlocks)
205 { 249 {
206 if (EndReceive(out numBytes, result, ref epSender)) 250 byte[][] datas = packet.ToBytesMultiple();
207 { 251 int packetCount = datas.Length;
208 // Make sure we are getting zeroes when running off the 252
209 // end of grab / degrab packets from old clients 253 if (packetCount > 1)
210 Array.Clear(RecvBuffer, numBytes, RecvBuffer.Length - numBytes); 254 m_log.Debug("[LLUDPSERVER]: Split " + packet.Type + " packet into " + packetCount + " packets");
211 255
212 int packetEnd = numBytes - 1; 256 for (int i = 0; i < packetCount; i++)
213 if (proxyPortOffset != 0) packetEnd -= 6;
214
215 try
216 {
217 packet = PacketPool.Instance.GetPacket(RecvBuffer, ref packetEnd, ZeroBuffer);
218 }
219 catch (MalformedDataException e)
220 {
221 m_log.DebugFormat("[CLIENT]: Dropped Malformed Packet due to MalformedDataException: {0}", e.StackTrace);
222 }
223 catch (IndexOutOfRangeException e)
224 {
225 m_log.DebugFormat("[CLIENT]: Dropped Malformed Packet due to IndexOutOfRangeException: {0}", e.StackTrace);
226 }
227 catch (Exception e)
228 {
229 m_log.Debug("[CLIENT]: " + e);
230 }
231 }
232
233
234 if (proxyPortOffset != 0)
235 { 257 {
236 // If we've received a use circuit packet, then we need to decode an endpoint proxy, if one exists, 258 byte[] data = datas[i];
237 // before allowing the RecvBuffer to be overwritten by the next packet. 259 SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category);
238 if (packet != null && packet.Type == PacketType.UseCircuitCode)
239 {
240 epProxy = epSender;
241 }
242
243 // Now decode the message from the proxy server
244 epSender = ProxyCodec.DecodeProxyMessage(RecvBuffer, ref numBytes);
245 } 260 }
246 } 261 }
247 catch (Exception ex) 262 else
248 { 263 {
249 m_log.ErrorFormat("[CLIENT]: Exception thrown during EndReceive(): {0}", ex); 264 byte[] data = packet.ToBytes();
265 SendPacketData(client, data, data.Length, packet.Type, packet.Header.Zerocoded, category);
250 } 266 }
267 }
251 268
252 BeginRobustReceive(); 269 public void SendPacketData(LLUDPClient client, byte[] data, int dataLength, PacketType type, bool doZerocode, ThrottleOutPacketType category)
270 {
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
272 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
273 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
274 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200;
276
277 UDPPacketBuffer buffer = new UDPPacketBuffer(client.RemoteEndPoint, bufferSize);
253 278
254 if (packet != null) 279 // Zerocode if needed
280 if (doZerocode)
255 { 281 {
256 if (packet.Type == PacketType.UseCircuitCode) 282 try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); }
257 AddNewClient((UseCircuitCodePacket)packet, epSender, epProxy); 283 catch (IndexOutOfRangeException)
258 else 284 {
259 ProcessInPacket(packet, epSender); 285 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead
288 m_log.Info("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding. Removing MSG_ZEROCODED flag");
289 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
290 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
291 }
292 }
293 else
294 {
295 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
260 } 296 }
297 buffer.DataLength = dataLength;
298
299 #region Queue or Send
300
301 // Look up the UDPClient this is going to
302 OutgoingPacket outgoingPacket = new OutgoingPacket(client, buffer, category);
303
304 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
305 SendPacketFinal(outgoingPacket);
306
307 #endregion Queue or Send
261 } 308 }
262 309
263 /// <summary> 310 public void SendAcks(LLUDPClient client)
264 /// Process a successfully received packet.
265 /// </summary>
266 /// <param name="packet"></param>
267 /// <param name="epSender"></param>
268 protected virtual void ProcessInPacket(Packet packet, EndPoint epSender)
269 { 311 {
270 try 312 uint ack;
313
314 if (client.PendingAcks.Dequeue(out ack))
271 { 315 {
272 // do we already have a circuit for this endpoint 316 List<PacketAckPacket.PacketsBlock> blocks = new List<PacketAckPacket.PacketsBlock>();
273 uint circuit; 317 PacketAckPacket.PacketsBlock block = new PacketAckPacket.PacketsBlock();
274 bool ret; 318 block.ID = ack;
275 319 blocks.Add(block);
276 lock (clientCircuits) 320
321 while (client.PendingAcks.Dequeue(out ack))
277 { 322 {
278 ret = clientCircuits.TryGetValue(epSender, out circuit); 323 block = new PacketAckPacket.PacketsBlock();
324 block.ID = ack;
325 blocks.Add(block);
279 } 326 }
280 327
281 if (ret) 328 PacketAckPacket packet = new PacketAckPacket();
282 { 329 packet.Header.Reliable = false;
283 //if so then send packet to the packetserver 330 packet.Packets = blocks.ToArray();
284 //m_log.DebugFormat(
285 // "[UDPSERVER]: For circuit {0} {1} got packet {2}", circuit, epSender, packet.Type);
286 331
287 m_packetServer.InPacket(circuit, packet); 332 SendPacket(client, packet, ThrottleOutPacketType.Unknown, true);
288 }
289 }
290 catch (Exception e)
291 {
292 m_log.Error("[CLIENT]: Exception in processing packet - ignoring: ", e);
293 } 333 }
294 } 334 }
295 335
296 /// <summary> 336 public void SendPing(LLUDPClient client)
297 /// Begin an asynchronous receive of the next bit of raw data
298 /// </summary>
299 protected virtual void BeginReceive()
300 { 337 {
301 m_socket.BeginReceiveFrom( 338 IClientAPI api = client.ClientAPI;
302 RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref reusedEpSender, ReceivedData, null); 339 if (api != null)
340 api.SendStartPingCheck(client.CurrentPingSequence++);
303 } 341 }
304 342
305 /// <summary> 343 public void ResendUnacked(LLUDPClient client)
306 /// Begin a robust asynchronous receive of the next bit of raw data. Robust means that SocketExceptions are
307 /// automatically dealt with until the next set of valid UDP data is received.
308 /// </summary>
309 private void BeginRobustReceive()
310 { 344 {
311 bool done = false; 345 if (client.NeedAcks.Count > 0)
312
313 while (!done)
314 { 346 {
315 try 347 List<OutgoingPacket> expiredPackets = client.NeedAcks.GetExpiredPackets(client.RTO);
316 {
317 BeginReceive();
318 done = true;
319 }
320 catch (SocketException e)
321 {
322 // ENDLESS LOOP ON PURPOSE!
323 // Reset connection and get next UDP packet off the buffer
324 // If the UDP packet is part of the same stream, this will happen several hundreds of times before
325 // the next set of UDP data is for a valid client.
326 348
327 try 349 if (expiredPackets != null)
328 { 350 {
329 CloseCircuit(e); 351 // Resend packets
330 } 352 for (int i = 0; i < expiredPackets.Count; i++)
331 catch (Exception e2)
332 { 353 {
333 m_log.ErrorFormat( 354 OutgoingPacket outgoingPacket = expiredPackets[i];
334 "[CLIENT]: Exception thrown when trying to close the circuit for {0} - {1}", reusedEpSender, 355
335 e2); 356 // FIXME: Make this an .ini setting
357 if (outgoingPacket.ResendCount < 3)
358 {
359 //Logger.Debug(String.Format("Resending packet #{0} (attempt {1}), {2}ms have passed",
360 // outgoingPacket.SequenceNumber, outgoingPacket.ResendCount, Environment.TickCount - outgoingPacket.TickCount));
361
362 // Set the resent flag
363 outgoingPacket.Buffer.Data[0] = (byte)(outgoingPacket.Buffer.Data[0] | Helpers.MSG_RESENT);
364 outgoingPacket.Category = ThrottleOutPacketType.Resend;
365
366 // The TickCount will be set to the current time when the packet
367 // is actually sent out again
368 outgoingPacket.TickCount = 0;
369
370 // Bump up the resend count on this packet
371 Interlocked.Increment(ref outgoingPacket.ResendCount);
372 //Interlocked.Increment(ref Stats.ResentPackets);
373
374 // Queue or (re)send the packet
375 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
376 SendPacketFinal(outgoingPacket);
377 }
378 else
379 {
380 m_log.DebugFormat("[LLUDPSERVER]: Dropping packet #{0} for agent {1} after {2} failed attempts",
381 outgoingPacket.SequenceNumber, outgoingPacket.Client.RemoteEndPoint, outgoingPacket.ResendCount);
382
383 lock (client.NeedAcks.SyncRoot)
384 client.NeedAcks.RemoveUnsafe(outgoingPacket.SequenceNumber);
385
386 //Interlocked.Increment(ref Stats.DroppedPackets);
387
388 // Disconnect an agent if no packets are received for some time
389 //FIXME: Make 60 an .ini setting
390 if (Environment.TickCount - client.TickLastPacketReceived > 1000 * 60)
391 {
392 m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + client.ClientAPI.Name);
393
394 RemoveClient(client.ClientAPI);
395 return;
396 }
397 }
336 } 398 }
337 } 399 }
338 catch (ObjectDisposedException)
339 {
340 m_log.Info(
341 "[UDPSERVER]: UDP Object disposed. No need to worry about this if you're restarting the simulator.");
342
343 done = true;
344 }
345 catch (Exception ex)
346 {
347 m_log.ErrorFormat("[CLIENT]: Exception thrown during BeginReceive(): {0}", ex);
348 }
349 } 400 }
350 } 401 }
351 402
352 /// <summary> 403 public void Flush()
353 /// Close a client circuit. This is done in response to an exception on receive, and should not be called
354 /// normally.
355 /// </summary>
356 /// <param name="e">The exception that caused the close. Can be null if there was no exception</param>
357 private void CloseCircuit(Exception e)
358 { 404 {
359 uint circuit; 405 // FIXME: Implement?
360 lock (clientCircuits) 406 }
407
408 internal void SendPacketFinal(OutgoingPacket outgoingPacket)
409 {
410 UDPPacketBuffer buffer = outgoingPacket.Buffer;
411 byte flags = buffer.Data[0];
412 bool isResend = (flags & Helpers.MSG_RESENT) != 0;
413 bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0;
414 LLUDPClient client = outgoingPacket.Client;
415
416 // Keep track of when this packet was sent out (right now)
417 outgoingPacket.TickCount = Environment.TickCount;
418
419 #region ACK Appending
420
421 int dataLength = buffer.DataLength;
422
423 // Keep appending ACKs until there is no room left in the packet or there are
424 // no more ACKs to append
425 uint ackCount = 0;
426 uint ack;
427 while (dataLength + 5 < buffer.Data.Length && client.PendingAcks.Dequeue(out ack))
428 {
429 Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
430 dataLength += 4;
431 ++ackCount;
432 }
433
434 if (ackCount > 0)
435 {
436 // Set the last byte of the packet equal to the number of appended ACKs
437 buffer.Data[dataLength++] = (byte)ackCount;
438 // Set the appended ACKs flag on this packet
439 buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS);
440 }
441
442 buffer.DataLength = dataLength;
443
444 #endregion ACK Appending
445
446 if (!isResend)
361 { 447 {
362 if (clientCircuits.TryGetValue(reusedEpSender, out circuit)) 448 // Not a resend, assign a new sequence number
449 uint sequenceNumber = (uint)Interlocked.Increment(ref client.CurrentSequence);
450 Utils.UIntToBytesBig(sequenceNumber, buffer.Data, 1);
451 outgoingPacket.SequenceNumber = sequenceNumber;
452
453 if (isReliable)
363 { 454 {
364 m_packetServer.CloseCircuit(circuit); 455 // Add this packet to the list of ACK responses we are waiting on from the server
365 456 client.NeedAcks.Add(outgoingPacket);
366 if (e != null)
367 m_log.ErrorFormat(
368 "[CLIENT]: Closed circuit {0} {1} due to exception {2}", circuit, reusedEpSender, e);
369 } 457 }
370 } 458 }
459
460 // Stats tracking
461 Interlocked.Increment(ref client.PacketsSent);
462 if (isReliable)
463 Interlocked.Add(ref client.UnackedBytes, outgoingPacket.Buffer.DataLength);
464
465 // Put the UDP payload on the wire
466 AsyncBeginSend(buffer);
371 } 467 }
372 468
373 /// <summary> 469 protected override void PacketReceived(UDPPacketBuffer buffer)
374 /// Finish the process of asynchronously receiving the next bit of raw data
375 /// </summary>
376 /// <param name="numBytes">The number of bytes received. Will return 0 if no bytes were recieved
377 /// <param name="result"></param>
378 /// <param name="epSender">The sender of the data</param>
379 /// <returns></returns>
380 protected virtual bool EndReceive(out int numBytes, IAsyncResult result, ref EndPoint epSender)
381 { 470 {
382 bool hasReceivedOkay = false; 471 // Debugging/Profiling
383 numBytes = 0; 472 //try { Thread.CurrentThread.Name = "PacketReceived (" + scene.RegionName + ")"; }
384 473 //catch (Exception) { }
474
475 LLUDPClient client = null;
476 Packet packet = null;
477 int packetEnd = buffer.DataLength - 1;
478 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
479
480 #region Decoding
481
385 try 482 try
386 { 483 {
387 numBytes = m_socket.EndReceiveFrom(result, ref epSender); 484 packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
388 hasReceivedOkay = true; 485 // Only allocate a buffer for zerodecoding if the packet is zerocoded
486 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
389 } 487 }
390 catch (SocketException e) 488 catch (MalformedDataException)
391 { 489 {
392 // TODO : Actually only handle those states that we have control over, re-throw everything else, 490 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse packet:\n{0}",
393 // TODO: implement cases as we encounter them. 491 Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
394 //m_log.Error("[CLIENT]: Connection Error! - " + e.ToString()); 492 }
395 switch (e.SocketErrorCode) 493
494 // Fail-safe check
495 if (packet == null)
496 {
497 m_log.Warn("[LLUDPSERVER]: Couldn't build a message from the incoming data");
498 return;
499 }
500
501 //Stats.RecvBytes += (ulong)buffer.DataLength;
502 //++Stats.RecvPackets;
503
504 #endregion Decoding
505
506 #region UseCircuitCode Handling
507
508 if (packet.Type == PacketType.UseCircuitCode)
509 {
510 UseCircuitCodePacket useCircuitCode = (UseCircuitCodePacket)packet;
511 IClientAPI newuser;
512 uint circuitCode = useCircuitCode.CircuitCode.Code;
513
514 // Check if the client is already established
515 if (!m_scene.ClientManager.TryGetClient(circuitCode, out newuser))
396 { 516 {
397 case SocketError.AlreadyInProgress: 517 AddNewClient(useCircuitCode, (IPEndPoint)buffer.RemoteEndPoint);
398 return hasReceivedOkay; 518 }
519 }
520
521 // Determine which agent this packet came from
522 if (!clients.TryGetValue(address, out client))
523 {
524 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address);
525 return;
526 }
527
528 #endregion UseCircuitCode Handling
529
530 // Stats tracking
531 Interlocked.Increment(ref client.PacketsReceived);
399 532
400 case SocketError.NetworkReset: 533 #region ACK Receiving
401 case SocketError.ConnectionReset:
402 case SocketError.OperationAborted:
403 break;
404 534
405 default: 535 int now = Environment.TickCount;
406 throw; 536 client.TickLastPacketReceived = now;
537
538 // Handle appended ACKs
539 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
540 {
541 lock (client.NeedAcks.SyncRoot)
542 {
543 for (int i = 0; i < packet.Header.AckList.Length; i++)
544 AcknowledgePacket(client, packet.Header.AckList[i], now, packet.Header.Resent);
407 } 545 }
408 } 546 }
409 catch (ObjectDisposedException e) 547
548 // Handle PacketAck packets
549 if (packet.Type == PacketType.PacketAck)
550 {
551 PacketAckPacket ackPacket = (PacketAckPacket)packet;
552
553 lock (client.NeedAcks.SyncRoot)
554 {
555 for (int i = 0; i < ackPacket.Packets.Length; i++)
556 AcknowledgePacket(client, ackPacket.Packets[i].ID, now, packet.Header.Resent);
557 }
558 }
559
560 #endregion ACK Receiving
561
562 #region ACK Sending
563
564 if (packet.Header.Reliable)
565 client.PendingAcks.Enqueue((uint)packet.Header.Sequence);
566
567 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
568 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
569 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
570 // client.BytesSinceLastACK. Lockless thread safety
571 int bytesSinceLastACK = Interlocked.Exchange(ref client.BytesSinceLastACK, 0);
572 bytesSinceLastACK += buffer.DataLength;
573 if (bytesSinceLastACK > Packet.MTU * 2)
574 {
575 bytesSinceLastACK -= Packet.MTU * 2;
576 SendAcks(client);
577 }
578 Interlocked.Add(ref client.BytesSinceLastACK, bytesSinceLastACK);
579
580 #endregion ACK Sending
581
582 #region Incoming Packet Accounting
583
584 // Check the archive of received reliable packet IDs to see whether we already received this packet
585 if (packet.Header.Reliable && !client.PacketArchive.TryEnqueue(packet.Header.Sequence))
410 { 586 {
411 m_log.DebugFormat("[CLIENT]: ObjectDisposedException: Object {0} disposed.", e.ObjectName); 587 if (packet.Header.Resent)
412 // Uhh, what object, and why? this needs better handling. 588 m_log.Debug("[LLUDPSERVER]: Received a resend of already processed packet #" + packet.Header.Sequence + ", type: " + packet.Type);
589 else
590 m_log.Warn("[LLUDPSERVER]: Received a duplicate (not marked as resend) of packet #" + packet.Header.Sequence + ", type: " + packet.Type);
591
592 // Avoid firing a callback twice for the same packet
593 return;
594 }
595
596 #endregion Incoming Packet Accounting
597
598 // Don't bother clogging up the queue with PacketAck packets that are already handled here
599 if (packet.Type != PacketType.PacketAck)
600 {
601 // Inbox insertion
602 packetInbox.Enqueue(new IncomingPacket(client, packet));
413 } 603 }
414
415 return hasReceivedOkay;
416 } 604 }
417 605
418 /// <summary> 606 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
419 /// Add a new client circuit. 607 {
420 /// </summary> 608 }
421 /// <param name="packet"></param> 609
422 /// <param name="epSender"></param> 610 private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo)
423 /// <param name="epProxy"></param> 611 {
424 protected virtual void AddNewClient(UseCircuitCodePacket useCircuit, EndPoint epSender, EndPoint epProxy) 612 UUID agentID = useCircuitCode.CircuitCode.ID;
613 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
614 uint circuitCode = useCircuitCode.CircuitCode.Code;
615
616 sessionInfo = m_circuitManager.AuthenticateSession(sessionID, agentID, circuitCode);
617 return sessionInfo.Authorised;
618 }
619
620 private void AddNewClient(UseCircuitCodePacket useCircuitCode, IPEndPoint remoteEndPoint)
425 { 621 {
426 //Slave regions don't accept new clients 622 //Slave regions don't accept new clients
427 if (m_localScene.RegionStatus != RegionStatus.SlaveScene) 623 if (m_scene.RegionStatus != RegionStatus.SlaveScene)
428 { 624 {
429 AuthenticateResponse sessionInfo; 625 AuthenticateResponse sessionInfo;
430 bool isNewCircuit = false; 626 bool isNewCircuit = !clients.ContainsKey(remoteEndPoint);
431 627
432 if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo)) 628 if (!IsClientAuthorized(useCircuitCode, out sessionInfo))
433 { 629 {
434 m_log.WarnFormat( 630 m_log.WarnFormat(
435 "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}", 631 "[CONNECTION FAILURE]: Connection request for client {0} connecting with unnotified circuit code {1} from {2}",
436 useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, epSender); 632 useCircuitCode.CircuitCode.ID, useCircuitCode.CircuitCode.Code, remoteEndPoint);
437
438 return; 633 return;
439 } 634 }
440
441 lock (clientCircuits)
442 {
443 if (!clientCircuits.ContainsKey(epSender))
444 {
445 clientCircuits.Add(epSender, useCircuit.CircuitCode.Code);
446 isNewCircuit = true;
447 }
448 }
449 635
450 if (isNewCircuit) 636 if (isNewCircuit)
451 { 637 {
452 // This doesn't need locking as it's synchronized data 638 UUID agentID = useCircuitCode.CircuitCode.ID;
453 clientCircuits_reverse[useCircuit.CircuitCode.Code] = epSender; 639 UUID sessionID = useCircuitCode.CircuitCode.SessionID;
640 uint circuitCode = useCircuitCode.CircuitCode.Code;
454 641
455 lock (proxyCircuits) 642 AddClient(circuitCode, agentID, sessionID, remoteEndPoint, sessionInfo);
456 {
457 proxyCircuits[useCircuit.CircuitCode.Code] = epProxy;
458 }
459
460 m_packetServer.AddNewClient(epSender, useCircuit, sessionInfo, epProxy);
461
462 //m_log.DebugFormat(
463 // "[CONNECTION SUCCESS]: Incoming client {0} (circuit code {1}) received and authenticated for {2}",
464 // useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code, m_localScene.RegionInfo.RegionName);
465 } 643 }
466 } 644 }
467
468 // Ack the UseCircuitCode packet
469 PacketAckPacket ack_it = (PacketAckPacket)PacketPool.Instance.GetPacket(PacketType.PacketAck);
470 // TODO: don't create new blocks if recycling an old packet
471 ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
472 ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
473 ack_it.Packets[0].ID = useCircuit.Header.Sequence;
474 // ((useCircuit.Header.Sequence < uint.MaxValue) ? useCircuit.Header.Sequence : 0) is just a failsafe to ensure that we don't overflow.
475 ack_it.Header.Sequence = ((useCircuit.Header.Sequence < uint.MaxValue) ? useCircuit.Header.Sequence : 0) + 1;
476 ack_it.Header.Reliable = false;
477
478 byte[] ackmsg = ack_it.ToBytes();
479
480 // Need some extra space in case we need to add proxy
481 // information to the message later
482 byte[] msg = new byte[4096];
483 Buffer.BlockCopy(ackmsg, 0, msg, 0, ackmsg.Length);
484
485 SendPacketTo(msg, ackmsg.Length, SocketFlags.None, useCircuit.CircuitCode.Code);
486
487 PacketPool.Instance.ReturnPacket(useCircuit);
488 } 645 }
489 646
490 public void ServerListener() 647 private void AddClient(uint circuitCode, UUID agentID, UUID sessionID, IPEndPoint remoteEndPoint, AuthenticateResponse sessionInfo)
491 { 648 {
492 uint newPort = listenPort; 649 // Create the LLUDPClient
493 m_log.Info("[UDPSERVER]: Opening UDP socket on " + listenIP + " " + newPort + "."); 650 LLUDPClient client = new LLUDPClient(this, m_throttleRates, m_throttle, circuitCode, agentID, remoteEndPoint);
494
495 ServerIncoming = new IPEndPoint(listenIP, (int)newPort);
496 m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
497 if (0 != m_clientSocketReceiveBuffer)
498 m_socket.ReceiveBufferSize = m_clientSocketReceiveBuffer;
499 m_socket.Bind(ServerIncoming);
500 // Add flags to the UDP socket to prevent "Socket forcibly closed by host"
501 // uint IOC_IN = 0x80000000;
502 // uint IOC_VENDOR = 0x18000000;
503 // uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
504 // TODO: this apparently works in .NET but not in Mono, need to sort out the right flags here.
505 // m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
506 651
507 listenPort = newPort; 652 // Create the LLClientView
653 LLClientView clientApi = new LLClientView(remoteEndPoint, m_scene, this, client, sessionInfo, agentID, sessionID, circuitCode);
654 clientApi.OnViewerEffect += m_scene.ClientManager.ViewerEffectHandler;
655 clientApi.OnLogout += LogoutHandler;
656 clientApi.OnConnectionClosed += RemoveClient;
508 657
509 m_log.Info("[UDPSERVER]: UDP socket bound, getting ready to listen"); 658 // Start the IClientAPI
659 m_scene.ClientManager.Add(circuitCode, clientApi);
660 clientApi.Start();
510 661
511 ReceivedData = OnReceivedData; 662 // Give LLUDPClient a reference to IClientAPI
512 BeginReceive(); 663 client.ClientAPI = clientApi;
513 664
514 m_log.Info("[UDPSERVER]: Listening on port " + newPort); 665 // Add the new client to our list of tracked clients
666 clients.Add(agentID, client.RemoteEndPoint, client);
515 } 667 }
516 668
517 public virtual void RegisterPacketServer(LLPacketServer server) 669 private void AcknowledgePacket(LLUDPClient client, uint ack, int currentTime, bool fromResend)
518 { 670 {
519 m_packetServer = server; 671 OutgoingPacket ackedPacket;
672 if (client.NeedAcks.RemoveUnsafe(ack, out ackedPacket) && !fromResend)
673 {
674 // Update stats
675 Interlocked.Add(ref client.UnackedBytes, -ackedPacket.Buffer.DataLength);
676
677 // Calculate the round-trip time for this packet and its ACK
678 int rtt = currentTime - ackedPacket.TickCount;
679 if (rtt > 0)
680 client.UpdateRoundTrip(rtt);
681 }
520 } 682 }
521 683
522 public virtual void SendPacketTo(byte[] buffer, int size, SocketFlags flags, uint circuitcode) 684 private void IncomingPacketHandler()
523 //EndPoint packetSender)
524 { 685 {
525 // find the endpoint for this circuit 686 // Set this culture for the thread that incoming packets are received
526 EndPoint sendto; 687 // on to en-US to avoid number parsing issues
527 try 688 Culture.SetCurrentCulture();
528 {
529 sendto = (EndPoint)clientCircuits_reverse[circuitcode];
530 }
531 catch
532 {
533 // Exceptions here mean there is no circuit
534 m_log.Warn("[CLIENT]: Circuit not found, not sending packet");
535 return;
536 }
537 689
538 if (sendto != null) 690 IncomingPacket incomingPacket = null;
691
692 while (base.IsRunning)
539 { 693 {
540 //we found the endpoint so send the packet to it 694 if (packetInbox.Dequeue(100, ref incomingPacket))
541 if (proxyPortOffset != 0) 695 Util.FireAndForget(ProcessInPacket, incomingPacket);
542 {
543 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo proxy " + proxyCircuits[circuitcode].ToString() + ": client " + sendto.ToString());
544 ProxyCodec.EncodeProxyMessage(buffer, ref size, sendto);
545 m_socket.SendTo(buffer, size, flags, proxyCircuits[circuitcode]);
546 }
547 else
548 {
549 //MainLog.Instance.Verbose("UDPSERVER", "SendPacketTo : client " + sendto.ToString());
550 try
551 {
552 m_socket.SendTo(buffer, size, flags, sendto);
553 }
554 catch (SocketException SockE)
555 {
556 m_log.ErrorFormat("[UDPSERVER]: Caught Socket Error in the send buffer!. {0}",SockE.ToString());
557 }
558 }
559 } 696 }
697
698 if (packetInbox.Count > 0)
699 m_log.Warn("[LLUDPSERVER]: IncomingPacketHandler is shutting down, dropping " + packetInbox.Count + " packets");
700 packetInbox.Clear();
560 } 701 }
561 702
562 public virtual void RemoveClientCircuit(uint circuitcode) 703 private void OutgoingPacketHandler()
563 { 704 {
564 EndPoint sendto; 705 // Set this culture for the thread that outgoing packets are sent
565 if (clientCircuits_reverse.Contains(circuitcode)) 706 // on to en-US to avoid number parsing issues
707 Culture.SetCurrentCulture();
708
709 int now = Environment.TickCount;
710 int elapsedMS = 0;
711 int elapsed100MS = 0;
712 int elapsed500MS = 0;
713
714 while (base.IsRunning)
566 { 715 {
567 sendto = (EndPoint)clientCircuits_reverse[circuitcode]; 716 bool resendUnacked = false;
717 bool sendAcks = false;
718 bool sendPings = false;
719 bool packetSent = false;
568 720
569 clientCircuits_reverse.Remove(circuitcode); 721 elapsedMS += Environment.TickCount - now;
570 722
571 lock (clientCircuits) 723 // Check for pending outgoing resends every 100ms
724 if (elapsedMS >= 100)
572 { 725 {
573 if (sendto != null) 726 resendUnacked = true;
574 { 727 elapsedMS -= 100;
575 clientCircuits.Remove(sendto); 728 ++elapsed100MS;
576 }
577 else
578 {
579 m_log.DebugFormat(
580 "[CLIENT]: endpoint for circuit code {0} in RemoveClientCircuit() was unexpectedly null!", circuitcode);
581 }
582 } 729 }
583 lock (proxyCircuits) 730 // Check for pending outgoing ACKs every 500ms
731 if (elapsed100MS >= 5)
584 { 732 {
585 proxyCircuits.Remove(circuitcode); 733 sendAcks = true;
734 elapsed100MS = 0;
735 ++elapsed500MS;
586 } 736 }
737 // Send pings to clients every 5000ms
738 if (elapsed500MS >= 10)
739 {
740 sendPings = true;
741 elapsed500MS = 0;
742 }
743
744 clients.ForEach(
745 delegate(LLUDPClient client)
746 {
747 if (client.DequeueOutgoing())
748 packetSent = true;
749 if (resendUnacked)
750 ResendUnacked(client);
751 if (sendAcks)
752 {
753 SendAcks(client);
754 client.SendPacketStats();
755 }
756 if (sendPings)
757 SendPing(client);
758 }
759 );
760
761 if (!packetSent)
762 Thread.Sleep(20);
587 } 763 }
588 } 764 }
589 765
590 public void RestoreClient(AgentCircuitData circuit, EndPoint userEP, EndPoint proxyEP) 766 private void ProcessInPacket(object state)
591 { 767 {
592 //MainLog.Instance.Verbose("UDPSERVER", "RestoreClient"); 768 IncomingPacket incomingPacket = (IncomingPacket)state;
769 Packet packet = incomingPacket.Packet;
770 LLUDPClient client = incomingPacket.Client;
593 771
594 UseCircuitCodePacket useCircuit = new UseCircuitCodePacket(); 772 // Sanity check
595 useCircuit.CircuitCode.Code = circuit.circuitcode; 773 if (packet == null || client == null || client.ClientAPI == null)
596 useCircuit.CircuitCode.ID = circuit.AgentID;
597 useCircuit.CircuitCode.SessionID = circuit.SessionID;
598
599 AuthenticateResponse sessionInfo;
600
601 if (!m_packetServer.IsClientAuthorized(useCircuit, m_circuitManager, out sessionInfo))
602 { 774 {
603 m_log.WarnFormat( 775 m_log.WarnFormat("[LLUDPSERVER]: Processing a packet with incomplete state. Packet=\"{0}\", Client=\"{1}\", Client.ClientAPI=\"{2}\"",
604 "[CLIENT]: Restore request denied to avatar {0} connecting with unauthorized circuit code {1}", 776 packet, client, (client != null) ? client.ClientAPI : null);
605 useCircuit.CircuitCode.ID, useCircuit.CircuitCode.Code);
606
607 return;
608 } 777 }
609 778
610 lock (clientCircuits) 779 try
611 { 780 {
612 if (!clientCircuits.ContainsKey(userEP)) 781 // Process this packet
613 clientCircuits.Add(userEP, useCircuit.CircuitCode.Code); 782 client.ClientAPI.ProcessInPacket(packet);
614 else
615 m_log.Error("[CLIENT]: clientCircuits already contains entry for user " + useCircuit.CircuitCode.Code + ". NOT adding.");
616 } 783 }
617 784 catch (ThreadAbortException)
618 // This data structure is synchronized, so we don't need the lock
619 if (!clientCircuits_reverse.ContainsKey(useCircuit.CircuitCode.Code))
620 clientCircuits_reverse.Add(useCircuit.CircuitCode.Code, userEP);
621 else
622 m_log.Error("[CLIENT]: clientCurcuits_reverse already contains entry for user " + useCircuit.CircuitCode.Code + ". NOT adding.");
623
624 lock (proxyCircuits)
625 { 785 {
626 if (!proxyCircuits.ContainsKey(useCircuit.CircuitCode.Code)) 786 // If something is trying to abort the packet processing thread, take that as a hint that it's time to shut down
627 { 787 m_log.Info("[LLUDPSERVER]: Caught a thread abort, shutting down the LLUDP server");
628 proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP); 788 Stop();
629 }
630 else
631 {
632 // re-set proxy endpoint
633 proxyCircuits.Remove(useCircuit.CircuitCode.Code);
634 proxyCircuits.Add(useCircuit.CircuitCode.Code, proxyEP);
635 }
636 } 789 }
790 catch (Exception e)
791 {
792 // Don't let a failure in an individual client thread crash the whole sim.
793 m_log.ErrorFormat("[LLUDPSERVER]: Client packet handler for {0} for packet {1} threw an exception", client.AgentID, packet.Type);
794 m_log.Error(e.Message, e);
795 }
796 }
637 797
638 m_packetServer.AddNewClient(userEP, useCircuit, sessionInfo, proxyEP); 798 private void LogoutHandler(IClientAPI client)
799 {
800 client.SendLogoutPacket();
801 RemoveClient(client);
639 } 802 }
640 } 803 }
641} 804}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
index c45d11f..1a1a1cb 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUtil.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -25,27 +25,46 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using OpenSim.Framework;
28using OpenMetaverse; 30using OpenMetaverse;
29 31
30namespace OpenSim.Region.ClientStack.LindenUDP 32namespace OpenSim.Region.ClientStack.LindenUDP
31{ 33{
32 public class LLUtil 34 /// <summary>
35 /// Holds a reference to the <seealso cref="LLUDPClient"/> this packet is
36 /// destined for, along with the serialized packet data, sequence number
37 /// (if this is a resend), number of times this packet has been resent,
38 /// the time of the last resend, and the throttling category for this
39 /// packet
40 /// </summary>
41 public sealed class OutgoingPacket
33 { 42 {
43 /// <summary>Client this packet is destined for</summary>
44 public LLUDPClient Client;
45 /// <summary>Packet data to send</summary>
46 public UDPPacketBuffer Buffer;
47 /// <summary>Sequence number of the wrapped packet</summary>
48 public uint SequenceNumber;
49 /// <summary>Number of times this packet has been resent</summary>
50 public int ResendCount;
51 /// <summary>Environment.TickCount when this packet was last sent over the wire</summary>
52 public int TickCount;
53 /// <summary>Category this packet belongs to</summary>
54 public ThrottleOutPacketType Category;
55
34 /// <summary> 56 /// <summary>
35 /// Convert a string to bytes suitable for use in an LL UDP packet. 57 /// Default constructor
36 /// </summary> 58 /// </summary>
37 /// <param name="s">Truncated to 254 characters if necessary</param> 59 /// <param name="client">Reference to the client this packet is destined for</param>
38 /// <returns></returns> 60 /// <param name="buffer">Serialized packet data. If the flags or sequence number
39 public static byte[] StringToPacketBytes(string s) 61 /// need to be updated, they will be injected directly into this binary buffer</param>
62 /// <param name="category">Throttling category for this packet</param>
63 public OutgoingPacket(LLUDPClient client, UDPPacketBuffer buffer, ThrottleOutPacketType category)
40 { 64 {
41 // Anything more than 254 will cause libsecondlife to barf 65 Client = client;
42 // (libsl 1550) adds an \0 on the Utils.StringToBytes conversion if it isn't present 66 Buffer = buffer;
43 if (s.Length > 254) 67 Category = category;
44 {
45 s = s.Remove(254);
46 }
47
48 return Utils.StringToBytes(s);
49 } 68 }
50 } 69 }
51} 70}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs
index cde155b..7d0757f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/Tests/PacketHandlerTests.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
70 70
71 TestClient testClient = new TestClient(agent, scene); 71 TestClient testClient = new TestClient(agent, scene);
72 72
73 ILLPacketHandler packetHandler 73 LLPacketHandler packetHandler
74 = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings()); 74 = new LLPacketHandler(testClient, testLLPacketServer, new ClientStackUserSettings());
75 75
76 packetHandler.InPacket(new AgentAnimationPacket()); 76 packetHandler.InPacket(new AgentAnimationPacket());
diff --git a/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs b/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs
index 1fba847..e995d65 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/Tests/TestLLPacketServer.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
37 /// </summary> 37 /// </summary>
38 protected Dictionary<PacketType, int> m_packetsReceived = new Dictionary<PacketType, int>(); 38 protected Dictionary<PacketType, int> m_packetsReceived = new Dictionary<PacketType, int>();
39 39
40 public TestLLPacketServer(ILLClientStackNetworkHandler networkHandler, ClientStackUserSettings userSettings) 40 public TestLLPacketServer(LLUDPServer networkHandler, ClientStackUserSettings userSettings)
41 : base(networkHandler, userSettings) 41 : base(networkHandler, userSettings)
42 {} 42 {}
43 43
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
new file mode 100644
index 0000000..858a03c
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
@@ -0,0 +1,99 @@
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 OpenSimulator 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 Nini.Config;
30
31namespace OpenSim.Region.ClientStack.LindenUDP
32{
33 /// <summary>
34 /// Holds drip rates and maximum burst rates for throttling with hierarchical
35 /// token buckets. The maximum burst rates set here are hard limits and can
36 /// not be overridden by client requests
37 /// </summary>
38 public sealed class ThrottleRates
39 {
40 /// <summary>Drip rate for resent packets</summary>
41 public int Resend;
42 /// <summary>Drip rate for terrain packets</summary>
43 public int Land;
44 /// <summary>Drip rate for wind packets</summary>
45 public int Wind;
46 /// <summary>Drip rate for cloud packets</summary>
47 public int Cloud;
48 /// <summary>Drip rate for task (state and transaction) packets</summary>
49 public int Task;
50 /// <summary>Drip rate for texture packets</summary>
51 public int Texture;
52 /// <summary>Drip rate for asset packets</summary>
53 public int Asset;
54
55 /// <summary>Maximum burst rate for resent packets</summary>
56 public int ResendLimit;
57 /// <summary>Maximum burst rate for land packets</summary>
58 public int LandLimit;
59 /// <summary>Maximum burst rate for wind packets</summary>
60 public int WindLimit;
61 /// <summary>Maximum burst rate for cloud packets</summary>
62 public int CloudLimit;
63 /// <summary>Maximum burst rate for task (state and transaction) packets</summary>
64 public int TaskLimit;
65 /// <summary>Maximum burst rate for texture packets</summary>
66 public int TextureLimit;
67 /// <summary>Maximum burst rate for asset packets</summary>
68 public int AssetLimit;
69
70 /// <summary>
71 /// Default constructor
72 /// </summary>
73 /// <param name="config">Config source to load defaults from</param>
74 public ThrottleRates(IConfigSource config)
75 {
76 try
77 {
78 IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
79
80 Resend = throttleConfig.GetInt("ResendDefault", 12500);
81 Land = throttleConfig.GetInt("LandDefault", 500);
82 Wind = throttleConfig.GetInt("WindDefault", 500);
83 Cloud = throttleConfig.GetInt("CloudDefault", 500);
84 Task = throttleConfig.GetInt("TaskDefault", 500);
85 Texture = throttleConfig.GetInt("TextureDefault", 500);
86 Asset = throttleConfig.GetInt("AssetDefault", 500);
87
88 ResendLimit = throttleConfig.GetInt("ResendLimit", 18750);
89 LandLimit = throttleConfig.GetInt("LandLimit", 29750);
90 WindLimit = throttleConfig.GetInt("WindLimit", 18750);
91 CloudLimit = throttleConfig.GetInt("CloudLimit", 18750);
92 TaskLimit = throttleConfig.GetInt("TaskLimit", 55750);
93 TextureLimit = throttleConfig.GetInt("TextureLimit", 55750);
94 AssetLimit = throttleConfig.GetInt("AssetLimit", 27500);
95 }
96 catch (Exception) { }
97 }
98 }
99}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
new file mode 100644
index 0000000..195ca57
--- /dev/null
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -0,0 +1,160 @@
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 OpenSimulator 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 OpenMetaverse;
32
33namespace OpenSim.Region.ClientStack.LindenUDP
34{
35 /// <summary>
36 /// Special collection that is optimized for tracking unacknowledged packets
37 /// </summary>
38 public sealed class UnackedPacketCollection
39 {
40 /// <summary>Synchronization primitive. A lock must be acquired on this
41 /// object before calling any of the unsafe methods</summary>
42 public object SyncRoot = new object();
43
44 /// <summary>Holds the actual unacked packet data, sorted by sequence number</summary>
45 private SortedDictionary<uint, OutgoingPacket> packets = new SortedDictionary<uint, OutgoingPacket>();
46
47 /// <summary>Gets the total number of unacked packets</summary>
48 public int Count { get { return packets.Count; } }
49
50 /// <summary>
51 /// Default constructor
52 /// </summary>
53 public UnackedPacketCollection()
54 {
55 }
56
57 /// <summary>
58 /// Add an unacked packet to the collection
59 /// </summary>
60 /// <param name="packet">Packet that is awaiting acknowledgement</param>
61 /// <returns>True if the packet was successfully added, false if the
62 /// packet already existed in the collection</returns>
63 public bool Add(OutgoingPacket packet)
64 {
65 lock (SyncRoot)
66 {
67 if (!packets.ContainsKey(packet.SequenceNumber))
68 {
69 packets.Add(packet.SequenceNumber, packet);
70 return true;
71 }
72 return false;
73 }
74 }
75
76 /// <summary>
77 /// Removes a packet from the collection without attempting to obtain a
78 /// lock first
79 /// </summary>
80 /// <param name="sequenceNumber">Sequence number of the packet to remove</param>
81 /// <returns>True if the packet was found and removed, otherwise false</returns>
82 public bool RemoveUnsafe(uint sequenceNumber)
83 {
84 return packets.Remove(sequenceNumber);
85 }
86
87 /// <summary>
88 /// Removes a packet from the collection without attempting to obtain a
89 /// lock first
90 /// </summary>
91 /// <param name="sequenceNumber">Sequence number of the packet to remove</param>
92 /// <param name="packet">Returns the removed packet</param>
93 /// <returns>True if the packet was found and removed, otherwise false</returns>
94 public bool RemoveUnsafe(uint sequenceNumber, out OutgoingPacket packet)
95 {
96 if (packets.TryGetValue(sequenceNumber, out packet))
97 {
98 packets.Remove(sequenceNumber);
99 return true;
100 }
101
102 return false;
103 }
104
105 /// <summary>
106 /// Gets the packet with the lowest sequence number
107 /// </summary>
108 /// <returns>The packet with the lowest sequence number, or null if the
109 /// collection is empty</returns>
110 public OutgoingPacket GetOldest()
111 {
112 lock (SyncRoot)
113 {
114 using (SortedDictionary<uint, OutgoingPacket>.ValueCollection.Enumerator e = packets.Values.GetEnumerator())
115 {
116 if (e.MoveNext())
117 return e.Current;
118 else
119 return null;
120 }
121 }
122 }
123
124 /// <summary>
125 /// Returns a list of all of the packets with a TickCount older than
126 /// the specified timeout
127 /// </summary>
128 /// <param name="timeoutMS">Number of ticks (milliseconds) before a
129 /// packet is considered expired</param>
130 /// <returns>A list of all expired packets according to the given
131 /// expiration timeout</returns>
132 public List<OutgoingPacket> GetExpiredPackets(int timeoutMS)
133 {
134 List<OutgoingPacket> expiredPackets = null;
135
136 lock (SyncRoot)
137 {
138 int now = Environment.TickCount;
139 foreach (OutgoingPacket packet in packets.Values)
140 {
141 if (packet.TickCount == 0)
142 continue;
143
144 if (now - packet.TickCount >= timeoutMS)
145 {
146 if (expiredPackets == null)
147 expiredPackets = new List<OutgoingPacket>();
148 expiredPackets.Add(packet);
149 }
150 else
151 {
152 break;
153 }
154 }
155 }
156
157 return expiredPackets;
158 }
159 }
160}
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 45e724d..d78931a 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -323,7 +323,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
323 httpThread.IsBackground = true; 323 httpThread.IsBackground = true;
324 _finished = false; 324 _finished = false;
325 httpThread.Start(); 325 httpThread.Start();
326 ThreadTracker.Add(httpThread);
327 } 326 }
328 327
329 /* 328 /*
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index 8a169f8..97899a7 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -639,7 +639,6 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
639 httpThread.IsBackground = true; 639 httpThread.IsBackground = true;
640 _finished = false; 640 _finished = false;
641 httpThread.Start(); 641 httpThread.Start();
642 ThreadTracker.Add(httpThread);
643 } 642 }
644 643
645 /* 644 /*
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 05ed70a..4fb4c51 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -345,7 +345,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
345 mapItemReqThread.Priority = ThreadPriority.BelowNormal; 345 mapItemReqThread.Priority = ThreadPriority.BelowNormal;
346 mapItemReqThread.SetApartmentState(ApartmentState.MTA); 346 mapItemReqThread.SetApartmentState(ApartmentState.MTA);
347 mapItemReqThread.Start(); 347 mapItemReqThread.Start();
348 ThreadTracker.Add(mapItemReqThread);
349 } 348 }
350 349
351 /// <summary> 350 /// <summary>
@@ -447,7 +446,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
447 // end gracefully 446 // end gracefully
448 if (st.agentID == UUID.Zero) 447 if (st.agentID == UUID.Zero)
449 { 448 {
450 ThreadTracker.Remove(mapItemReqThread);
451 break; 449 break;
452 } 450 }
453 451
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 5f18a44..ceff28b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -903,7 +903,6 @@ namespace OpenSim.Region.Framework.Scenes
903 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 903 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
904 if (HeartbeatThread != null) 904 if (HeartbeatThread != null)
905 { 905 {
906 ThreadTracker.Remove(HeartbeatThread);
907 HeartbeatThread.Abort(); 906 HeartbeatThread.Abort();
908 HeartbeatThread = null; 907 HeartbeatThread = null;
909 } 908 }
@@ -912,7 +911,6 @@ namespace OpenSim.Region.Framework.Scenes
912 HeartbeatThread.SetApartmentState(ApartmentState.MTA); 911 HeartbeatThread.SetApartmentState(ApartmentState.MTA);
913 HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName); 912 HeartbeatThread.Name = string.Format("Heartbeat for region {0}", RegionInfo.RegionName);
914 HeartbeatThread.Priority = ThreadPriority.AboveNormal; 913 HeartbeatThread.Priority = ThreadPriority.AboveNormal;
915 ThreadTracker.Add(HeartbeatThread);
916 HeartbeatThread.Start(); 914 HeartbeatThread.Start();
917 } 915 }
918 916
@@ -1448,6 +1446,9 @@ namespace OpenSim.Region.Framework.Scenes
1448 m_log.Info("[SCENE]: Loading objects from datastore"); 1446 m_log.Info("[SCENE]: Loading objects from datastore");
1449 1447
1450 List<SceneObjectGroup> PrimsFromDB = m_storageManager.DataStore.LoadObjects(regionID); 1448 List<SceneObjectGroup> PrimsFromDB = m_storageManager.DataStore.LoadObjects(regionID);
1449
1450 m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count + " objects from the datastore");
1451
1451 foreach (SceneObjectGroup group in PrimsFromDB) 1452 foreach (SceneObjectGroup group in PrimsFromDB)
1452 { 1453 {
1453 if (group.RootPart == null) 1454 if (group.RootPart == null)
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index 9273fb5..cd401a6 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -360,7 +360,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
360 m_listener.Name = "IRCConnectorListenerThread"; 360 m_listener.Name = "IRCConnectorListenerThread";
361 m_listener.IsBackground = true; 361 m_listener.IsBackground = true;
362 m_listener.Start(); 362 m_listener.Start();
363 ThreadTracker.Add(m_listener);
364 363
365 // This is the message order recommended by RFC 2812 364 // This is the message order recommended by RFC 2812
366 if (m_password != null) 365 if (m_password != null)
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs
index 7202601..16fe9e9 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMController.cs
@@ -152,7 +152,6 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
152 m_thread.Name = "Content Management"; 152 m_thread.Name = "Content Management";
153 m_thread.IsBackground = true; 153 m_thread.IsBackground = true;
154 m_thread.Start(); 154 m_thread.Start();
155 ThreadTracker.Add(m_thread);
156 m_state = State.NONE; 155 m_state = State.NONE;
157 } 156 }
158 } 157 }
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
index 0feb967..583d2ff 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueThreadClass.cs
@@ -138,7 +138,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
138 EventQueueThread.Priority = MyThreadPriority; 138 EventQueueThread.Priority = MyThreadPriority;
139 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; 139 EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
140 EventQueueThread.Start(); 140 EventQueueThread.Start();
141 ThreadTracker.Add(EventQueueThread);
142 141
143 // Look at this... Don't you wish everyone did that solid 142 // Look at this... Don't you wish everyone did that solid
144 // coding everywhere? :P 143 // coding everywhere? :P
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
index 8bafe77..7ffdb1a 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/MaintenanceThread.cs
@@ -97,7 +97,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
97 MaintenanceThreadThread.Name = "ScriptMaintenanceThread"; 97 MaintenanceThreadThread.Name = "ScriptMaintenanceThread";
98 MaintenanceThreadThread.IsBackground = true; 98 MaintenanceThreadThread.IsBackground = true;
99 MaintenanceThreadThread.Start(); 99 MaintenanceThreadThread.Start();
100 ThreadTracker.Add(MaintenanceThreadThread);
101 } 100 }
102 } 101 }
103 102
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
index 3c91b29..9806218 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptEngine.cs
@@ -129,10 +129,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
129 129
130 public void AddRegion(Scene Sceneworld) 130 public void AddRegion(Scene Sceneworld)
131 { 131 {
132 m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing");
133
134 m_Scene = Sceneworld;
135
136 // Make sure we have config 132 // Make sure we have config
137 if (ConfigSource.Configs[ScriptEngineName] == null) 133 if (ConfigSource.Configs[ScriptEngineName] == null)
138 ConfigSource.AddConfig(ScriptEngineName); 134 ConfigSource.AddConfig(ScriptEngineName);
@@ -143,6 +139,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
143 if (!m_enabled) 139 if (!m_enabled)
144 return; 140 return;
145 141
142 m_log.Info("[" + ScriptEngineName + "]: ScriptEngine initializing");
143
144 m_Scene = Sceneworld;
145
146 // Create all objects we'll be using 146 // Create all objects we'll be using
147 m_EventQueueManager = new EventQueueManager(this); 147 m_EventQueueManager = new EventQueueManager(this);
148 m_EventManager = new EventManager(this, true); 148 m_EventManager = new EventManager(this, true);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index e454524..1607d34 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -142,7 +142,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
142 cmdHandlerThread.Priority = ThreadPriority.BelowNormal; 142 cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
143 cmdHandlerThread.IsBackground = true; 143 cmdHandlerThread.IsBackground = true;
144 cmdHandlerThread.Start(); 144 cmdHandlerThread.Start();
145 ThreadTracker.Add(cmdHandlerThread);
146 } 145 }
147 } 146 }
148 147
diff --git a/OpenSim/TestSuite/BotManager.cs b/OpenSim/TestSuite/BotManager.cs
index 62e0ec7..55ba687 100644
--- a/OpenSim/TestSuite/BotManager.cs
+++ b/OpenSim/TestSuite/BotManager.cs
@@ -115,7 +115,6 @@ namespace OpenSim.TestSuite
115 m_td[pos].IsBackground = true; 115 m_td[pos].IsBackground = true;
116 m_td[pos].Start(); 116 m_td[pos].Start();
117 m_lBot.Add(pb); 117 m_lBot.Add(pb);
118 ThreadTracker.Add(m_td[pos]);
119 } 118 }
120 119
121 /// <summary> 120 /// <summary>
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index 3f4e6ed..614b350 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -149,7 +149,6 @@ namespace pCampBot
149 m_td[pos].IsBackground = true; 149 m_td[pos].IsBackground = true;
150 m_td[pos].Start(); 150 m_td[pos].Start();
151 m_lBot.Add(pb); 151 m_lBot.Add(pb);
152 ThreadTracker.Add(m_td[pos]);
153 } 152 }
154 153
155 /// <summary> 154 /// <summary>