aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs164
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs5
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs66
4 files changed, 137 insertions, 101 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index 9869a99..5c17b0e 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 m_stopPacket = TexturePacketCount(); 202 m_stopPacket = TexturePacketCount();
203 } 203 }
204 204
205 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
205 m_currentPacket = StartPacket; 208 m_currentPacket = StartPacket;
206 } 209 }
207 } 210 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index d2824bd..14b716b 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -339,6 +339,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
339 private AgentUpdateArgs lastarg; 339 private AgentUpdateArgs lastarg;
340 private bool m_IsActive = true; 340 private bool m_IsActive = true;
341 private bool m_IsLoggingOut = false; 341 private bool m_IsLoggingOut = false;
342 private bool m_IsPresenceReady = false;
342 343
343 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 344 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
344 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 345 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -362,6 +363,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
362 363
363 private Timer m_propertiesPacketTimer; 364 private Timer m_propertiesPacketTimer;
364 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); 365 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
366 private List<Packet> m_pendingPackets;
365 367
366 #endregion Class Members 368 #endregion Class Members
367 369
@@ -402,6 +404,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
402 get { return m_IsActive; } 404 get { return m_IsActive; }
403 set { m_IsActive = value; } 405 set { m_IsActive = value; }
404 } 406 }
407
405 public bool IsLoggingOut 408 public bool IsLoggingOut
406 { 409 {
407 get { return m_IsLoggingOut; } 410 get { return m_IsLoggingOut; }
@@ -466,18 +469,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
466 469
467 #region Client Methods 470 #region Client Methods
468 471
472
469 /// <summary> 473 /// <summary>
470 /// Shut down the client view 474 /// Shut down the client view
471 /// </summary> 475 /// </summary>
472 public void Close() 476 public void Close()
473 { 477 {
478 Close(true);
479 }
480
481 /// <summary>
482 /// Shut down the client view
483 /// </summary>
484 public void Close(bool sendStop)
485 {
474 m_log.DebugFormat( 486 m_log.DebugFormat(
475 "[CLIENT]: Close has been called for {0} attached to scene {1}", 487 "[CLIENT]: Close has been called for {0} attached to scene {1}",
476 Name, m_scene.RegionInfo.RegionName); 488 Name, m_scene.RegionInfo.RegionName);
477 489
478 // Send the STOP packet 490 if (sendStop)
479 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 491 {
480 OutPacket(disable, ThrottleOutPacketType.Unknown); 492 // Send the STOP packet
493 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
494 OutPacket(disable, ThrottleOutPacketType.Unknown);
495 }
481 496
482 IsActive = false; 497 IsActive = false;
483 498
@@ -1043,6 +1058,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1043 public virtual void SendLayerData(float[] map) 1058 public virtual void SendLayerData(float[] map)
1044 { 1059 {
1045 Util.FireAndForget(DoSendLayerData, map); 1060 Util.FireAndForget(DoSendLayerData, map);
1061
1062 // Send it sync, and async. It's not that much data
1063 // and it improves user experience just so much!
1064 DoSendLayerData(map);
1046 } 1065 }
1047 1066
1048 /// <summary> 1067 /// <summary>
@@ -1055,16 +1074,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1055 1074
1056 try 1075 try
1057 { 1076 {
1058 //for (int y = 0; y < 16; y++) 1077 for (int y = 0; y < 16; y++)
1059 //{ 1078 {
1060 // for (int x = 0; x < 16; x++) 1079 for (int x = 0; x < 16; x+=4)
1061 // { 1080 {
1062 // SendLayerData(x, y, map); 1081 SendLayerPacket(x, y, map);
1063 // } 1082 }
1064 //} 1083 }
1065
1066 // Send LayerData in a spiral pattern. Fun!
1067 SendLayerTopRight(map, 0, 0, 15, 15);
1068 } 1084 }
1069 catch (Exception e) 1085 catch (Exception e)
1070 { 1086 {
@@ -1072,51 +1088,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1072 } 1088 }
1073 } 1089 }
1074 1090
1075 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1076 {
1077 // Row
1078 for (int i = x1; i <= x2; i++)
1079 SendLayerData(i, y1, map);
1080
1081 // Column
1082 for (int j = y1 + 1; j <= y2; j++)
1083 SendLayerData(x2, j, map);
1084
1085 if (x2 - x1 > 0)
1086 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1087 }
1088
1089 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1090 {
1091 // Row in reverse
1092 for (int i = x2; i >= x1; i--)
1093 SendLayerData(i, y2, map);
1094
1095 // Column in reverse
1096 for (int j = y2 - 1; j >= y1; j--)
1097 SendLayerData(x1, j, map);
1098
1099 if (x2 - x1 > 0)
1100 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1101 }
1102
1103 /// <summary> 1091 /// <summary>
1104 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1092 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1105 /// </summary> 1093 /// </summary>
1106 /// <param name="map">heightmap</param> 1094 /// <param name="map">heightmap</param>
1107 /// <param name="px">X coordinate for patches 0..12</param> 1095 /// <param name="px">X coordinate for patches 0..12</param>
1108 /// <param name="py">Y coordinate for patches 0..15</param> 1096 /// <param name="py">Y coordinate for patches 0..15</param>
1109 // private void SendLayerPacket(float[] map, int y, int x) 1097 private void SendLayerPacket(int x, int y, float[] map)
1110 // { 1098 {
1111 // int[] patches = new int[4]; 1099 int[] patches = new int[4];
1112 // patches[0] = x + 0 + y * 16; 1100 patches[0] = x + 0 + y * 16;
1113 // patches[1] = x + 1 + y * 16; 1101 patches[1] = x + 1 + y * 16;
1114 // patches[2] = x + 2 + y * 16; 1102 patches[2] = x + 2 + y * 16;
1115 // patches[3] = x + 3 + y * 16; 1103 patches[3] = x + 3 + y * 16;
1116 1104
1117 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1105 float[] heightmap = (map.Length == 65536) ?
1118 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1106 map :
1119 // } 1107 LLHeightFieldMoronize(map);
1108
1109 try
1110 {
1111 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1112 OutPacket(layerpack, ThrottleOutPacketType.Land);
1113 }
1114 catch
1115 {
1116 for (int px = x ; px < x + 4 ; px++)
1117 SendLayerData(px, y, map);
1118 }
1119 }
1120 1120
1121 /// <summary> 1121 /// <summary>
1122 /// Sends a specified patch to a client 1122 /// Sends a specified patch to a client
@@ -1136,7 +1136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1136 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1136 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1137 layerpack.Header.Reliable = true; 1137 layerpack.Header.Reliable = true;
1138 1138
1139 OutPacket(layerpack, ThrottleOutPacketType.Land); 1139 OutPacket(layerpack, ThrottleOutPacketType.Task);
1140 } 1140 }
1141 catch (Exception e) 1141 catch (Exception e)
1142 { 1142 {
@@ -2208,6 +2208,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2208 OutPacket(sound, ThrottleOutPacketType.Task); 2208 OutPacket(sound, ThrottleOutPacketType.Task);
2209 } 2209 }
2210 2210
2211 public void SendTransferAbort(TransferRequestPacket transferRequest)
2212 {
2213 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2214 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2215 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2216 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2217 OutPacket(abort, ThrottleOutPacketType.Task);
2218 }
2219
2211 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2220 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2212 { 2221 {
2213 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2222 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3935,6 +3944,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3935 { 3944 {
3936 m_propertiesPacketTimer.Stop(); 3945 m_propertiesPacketTimer.Stop();
3937 3946
3947 if (m_propertiesBlocks.Count == 0)
3948 return;
3949
3938 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 3950 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
3939 3951
3940 int index = 0; 3952 int index = 0;
@@ -4926,6 +4938,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4926 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 4938 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
4927 (x.CameraUpAxis != lastarg.CameraUpAxis) || 4939 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
4928 (x.ControlFlags != lastarg.ControlFlags) || 4940 (x.ControlFlags != lastarg.ControlFlags) ||
4941 (x.ControlFlags != 0) ||
4929 (x.Far != lastarg.Far) || 4942 (x.Far != lastarg.Far) ||
4930 (x.Flags != lastarg.Flags) || 4943 (x.Flags != lastarg.Flags) ||
4931 (x.State != lastarg.State) || 4944 (x.State != lastarg.State) ||
@@ -5297,7 +5310,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5297 args.Channel = ch; 5310 args.Channel = ch;
5298 args.From = String.Empty; 5311 args.From = String.Empty;
5299 args.Message = Utils.BytesToString(msg); 5312 args.Message = Utils.BytesToString(msg);
5300 args.Type = ChatTypeEnum.Shout; 5313 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5301 args.Position = new Vector3(); 5314 args.Position = new Vector3();
5302 args.Scene = Scene; 5315 args.Scene = Scene;
5303 args.Sender = this; 5316 args.Sender = this;
@@ -11215,18 +11228,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11215 } 11228 }
11216 11229
11217 /// <summary> 11230 /// <summary>
11231 /// This processes packets which have accumulated while the presence was still in the process of initialising.
11232 /// </summary>
11233 public void ProcessPendingPackets()
11234 {
11235 m_IsPresenceReady = true;
11236 if (m_pendingPackets == null)
11237 return;
11238 foreach (Packet p in m_pendingPackets)
11239 {
11240 ProcessInPacket(p);
11241 }
11242 m_pendingPackets.Clear();
11243 }
11244
11245 /// <summary>
11218 /// Entryway from the client to the simulator. All UDP packets from the client will end up here 11246 /// Entryway from the client to the simulator. All UDP packets from the client will end up here
11219 /// </summary> 11247 /// </summary>
11220 /// <param name="Pack">OpenMetaverse.packet</param> 11248 /// <param name="Pack">OpenMetaverse.packet</param>
11221 public void ProcessInPacket(Packet Pack) 11249 public void ProcessInPacket(Packet Pack)
11222 { 11250 {
11223 if (m_debugPacketLevel >= 255) 11251 if (!m_IsPresenceReady)
11224 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); 11252 {
11253 if (m_pendingPackets == null)
11254 {
11255 m_pendingPackets = new List<Packet>();
11256 }
11257 m_pendingPackets.Add(Pack);
11258 }
11259 else
11260 {
11261 if (m_debugPacketLevel >= 255)
11262 m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type);
11225 11263
11226 if (!ProcessPacketMethod(Pack)) 11264 if (!ProcessPacketMethod(Pack))
11227 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); 11265 m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type);
11228 11266
11229 PacketPool.Instance.ReturnPacket(Pack); 11267 PacketPool.Instance.ReturnPacket(Pack);
11268 }
11230 } 11269 }
11231 11270
11232 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 11271 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -11472,7 +11511,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11472 11511
11473// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11512// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11474 11513
11475 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11514 if (!m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived))
11515 {
11516 //We need to send a TransferAbort here, so the client doesn't wait forever for the asset,
11517 //which causes it to not request any more for a while. Which is bad.
11518 SendTransferAbort(transferRequest);
11519 }
11476 } 11520 }
11477 11521
11478 /// <summary> 11522 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 1b81105..cda461c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -899,7 +899,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
899 client.OnLogout += LogoutHandler; 899 client.OnLogout += LogoutHandler;
900 900
901 // Start the IClientAPI 901 // Start the IClientAPI
902 client.Start(); 902 // Spin it off so that it doesn't clog up the LLUDPServer
903 Util.FireAndForget(delegate(object o) { client.Start(); });
903 } 904 }
904 else 905 else
905 { 906 {
@@ -915,7 +916,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
915 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 916 if (m_scene.TryGetClient(udpClient.AgentID, out client))
916 { 917 {
917 client.IsLoggingOut = true; 918 client.IsLoggingOut = true;
918 client.Close(); 919 client.Close(false);
919 } 920 }
920 } 921 }
921 922
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index bdbd284..91e3d20 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
133 this.parent = parent; 133 this.parent = parent;
134 MaxBurst = maxBurst; 134 MaxBurst = maxBurst;
135 DripRate = dripRate; 135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 136 lastDrip = Environment.TickCount;
137 } 137 }
138 138
139 /// <summary> 139 /// <summary>
@@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
144 /// the bucket, otherwise false</returns> 144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount) 145 public bool RemoveTokens(int amount)
146 { 146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0) 147 if (maxBurst == 0)
162 { 148 {
163 dripSucceeded = true;
164 return true; 149 return true;
165 } 150 }
166 151
167 dripSucceeded = Drip(); 152 if (amount > maxBurst)
168
169 if (content - amount >= 0)
170 { 153 {
171 if (parent != null && !parent.RemoveTokens(amount)) 154 throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst);
172 return false; 155 }
173 156
174 content -= amount; 157 Drip();
175 return true; 158
159 if (content < amount)
160 {
161 return false;
176 } 162 }
177 else 163
164 if (parent != null && !parent.RemoveTokens(amount))
178 { 165 {
179 return false; 166 return false;
180 } 167 }
168
169 content -= amount;
170 return true;
181 } 171 }
182 172
183 /// <summary> 173 /// <summary>
@@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 content = maxBurst; 183 content = maxBurst;
194 return true; 184 return true;
195 } 185 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200 186
201 if (deltaMS <= 0) 187 int now = Environment.TickCount;
202 { 188 int deltaMS = now - lastDrip;
203 if (deltaMS < 0) 189 lastDrip = now;
204 lastDrip = now;
205 return false;
206 }
207 190
208 int dripAmount = deltaMS * tokensPerMS; 191 if (deltaMS <= 0)
209 192 {
210 content = Math.Min(content + dripAmount, maxBurst); 193 return false;
211 lastDrip = now; 194 }
212 195
213 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
214 } 200 }
201 content = (int)dripAmount;
202 return true;
215 } 203 }
216 } 204 }
217} 205}