aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-09-06 00:11:47 +0100
committerJustin Clark-Casey (justincc)2012-09-06 00:11:47 +0100
commita0d0c9f751f45d54772af2e33866b27c9be33511 (patch)
treeb94a250c12264f8c44387e79e35b62893dab441b
parentBump master code up to 0.7.5 now that 0.7.4 is out. (diff)
downloadopensim-SC_OLD-a0d0c9f751f45d54772af2e33866b27c9be33511.zip
opensim-SC_OLD-a0d0c9f751f45d54772af2e33866b27c9be33511.tar.gz
opensim-SC_OLD-a0d0c9f751f45d54772af2e33866b27c9be33511.tar.bz2
opensim-SC_OLD-a0d0c9f751f45d54772af2e33866b27c9be33511.tar.xz
If the GetTexture capability receives a request for a range of data beyond that of an otherwise valid asset, return HTTP PartialContent rather than RequestedRangeNotSatisfiable.
This is because recent viewers (3.2.1, 3.3.4) and probably earlier ones using the http GetTexture capability will sometimes make such invalid range requests. This appears to happen if the viewer's estimate of texture sizes at discard levels > 0 (chiefly 2) exceeds the total texture size. I believe this does not normally happen but can occur for dynamic textures with are large but mainly blank. If this happens, returning a RequestedRangeNotSatisfiable will cause the viewer to not render the texture at the final resolution. However, returning a PartialContent (or OK) even with 0 data will allow the viewer to render the final texture.
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs34
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs16
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs20
3 files changed, 62 insertions, 8 deletions
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index ae6c44b..9b43a80 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -163,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
163 163
164 if (texture == null) 164 if (texture == null)
165 { 165 {
166 //m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache"); 166// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
167 167
168 // Fetch locally or remotely. Misses return a 404 168 // Fetch locally or remotely. Misses return a 404
169 texture = m_assetService.Get(textureID.ToString()); 169 texture = m_assetService.Get(textureID.ToString());
@@ -197,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
197 } 197 }
198 else // it was on the cache 198 else // it was on the cache
199 { 199 {
200 //m_log.DebugFormat("[GETTEXTURE]: texture was in the cache"); 200// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
201 WriteTextureData(httpRequest, httpResponse, texture, format); 201 WriteTextureData(httpRequest, httpResponse, texture, format);
202 return true; 202 return true;
203 } 203 }
@@ -219,12 +219,30 @@ namespace OpenSim.Capabilities.Handlers
219 int start, end; 219 int start, end;
220 if (TryParseRange(range, out start, out end)) 220 if (TryParseRange(range, out start, out end))
221 { 221 {
222
223 // Before clamping start make sure we can satisfy it in order to avoid 222 // Before clamping start make sure we can satisfy it in order to avoid
224 // sending back the last byte instead of an error status 223 // sending back the last byte instead of an error status
225 if (start >= texture.Data.Length) 224 if (start >= texture.Data.Length)
226 { 225 {
227 response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 226 m_log.DebugFormat(
227 "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
228 texture.ID, start, texture.Data.Length);
229
230 // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
231 // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
232 // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
233 // received a very small texture may attempt to fetch bytes from the server past the
234 // range of data that it received originally. Whether this happens appears to depend on whether
235 // the viewer's estimation of how large a request it needs to make for certain discard levels
236 // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
237 // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
238 // here will cause the viewer to treat the texture as bad and never display the full resolution
239 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
240
241// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
242// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
243// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
244 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
245 response.ContentType = texture.Metadata.ContentType;
228 } 246 }
229 else 247 else
230 { 248 {
@@ -232,12 +250,18 @@ namespace OpenSim.Capabilities.Handlers
232 start = Utils.Clamp(start, 0, end); 250 start = Utils.Clamp(start, 0, end);
233 int len = end - start + 1; 251 int len = end - start + 1;
234 252
235 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 253// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
236 254
237 // Always return PartialContent, even if the range covered the entire data length 255 // Always return PartialContent, even if the range covered the entire data length
238 // We were accidentally sending back 404 before in this situation 256 // We were accidentally sending back 404 before in this situation
239 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the 257 // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
240 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this. 258 // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
259 //
260 // We also do not want to send back OK even if the whole range was satisfiable since this causes
261 // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
262// if (end > maxEnd)
263// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
264// else
241 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; 265 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
242 266
243 response.ContentLength = len; 267 response.ContentLength = len;
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 3eedf49..e09f1a9 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 42{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
44 { 44 {
45 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int ALL_SIDES = -1; 47 private const int ALL_SIDES = -1;
48 48
@@ -249,10 +249,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
249 } 249 }
250 } 250 }
251 251
252// m_log.DebugFormat(
253// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
254// part.Name, part.ParentGroup.Scene.Name);
255
252 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 256 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
253 } 257 }
254 else 258 else
255 { 259 {
260// m_log.DebugFormat(
261// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
262// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
263
256 // No need to add to updaters as the texture is always the same. Not that this functionality 264 // No need to add to updaters as the texture is always the same. Not that this functionality
257 // apppears to be implemented anyway. 265 // apppears to be implemented anyway.
258 updater.UpdatePart(part, (UUID)objReusableTextureUUID); 266 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
@@ -448,8 +456,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
448 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 456 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
449 if (cacheLayerDecode != null) 457 if (cacheLayerDecode != null)
450 { 458 {
451 cacheLayerDecode.Decode(asset.FullID, asset.Data); 459 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
452 cacheLayerDecode = null; 460 m_log.WarnFormat(
461 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
462 asset.ID, part.Name, part.ParentGroup.Scene.Name);
453 } 463 }
454 464
455 UUID oldID = UpdatePart(part, asset.FullID); 465 UUID oldID = UpdatePart(part, asset.FullID);
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 4268f2e..0e7051e 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -46,6 +46,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
46{ 46{
47 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 47 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
48 { 48 {
49 // These fields exist for testing purposes, please do not remove.
50// private static bool s_flipper;
51// private static byte[] s_asset1Data;
52// private static byte[] s_asset2Data;
53
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 55
51 private Scene m_scene; 56 private Scene m_scene;
@@ -161,6 +166,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
161 { 166 {
162 m_textureManager.RegisterRender(GetContentType(), this); 167 m_textureManager.RegisterRender(GetContentType(), this);
163 } 168 }
169
170 // This code exists for testing purposes, please do not remove.
171// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
172// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
173
174 // Terrain dirt - smallest bin/assets file (6004 bytes)
175// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
164 } 176 }
165 177
166 public void Close() 178 public void Close()
@@ -364,6 +376,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
364 } 376 }
365 377
366 byte[] imageJ2000 = new byte[0]; 378 byte[] imageJ2000 = new byte[0];
379
380 // This code exists for testing purposes, please do not remove.
381// if (s_flipper)
382// imageJ2000 = s_asset1Data;
383// else
384// imageJ2000 = s_asset2Data;
385//
386// s_flipper = !s_flipper;
367 387
368 try 388 try
369 { 389 {