aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorJohn Hurliman2010-04-08 12:31:44 -0700
committerJohn Hurliman2010-04-08 12:31:44 -0700
commit3f6c4c150e3910e79ee3dc94f9304c16265512c0 (patch)
treeca83d44c56ab70535dfe04f068f5d0bfd1abb7da /OpenSim/Region
parent* Fixing incorrect documentation for the continuation passing style IAssetSer... (diff)
downloadopensim-SC-3f6c4c150e3910e79ee3dc94f9304c16265512c0.zip
opensim-SC-3f6c4c150e3910e79ee3dc94f9304c16265512c0.tar.gz
opensim-SC-3f6c4c150e3910e79ee3dc94f9304c16265512c0.tar.bz2
opensim-SC-3f6c4c150e3910e79ee3dc94f9304c16265512c0.tar.xz
* Adds IAssetService.GetCached() to allow asset fetching from the local cache only
* Adds GetTextureModule that implements the "GetTexture" capability, aka HTTP texture fetching. This is a significantly optimized path that does not require any server-side JPEG2000 decoding, texture priority queue, or UDP file transfer * Sanity check for null reference in LLClientView.RefreshGroupMembership()
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs7
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs220
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs8
5 files changed, 246 insertions, 2 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 516c23b..51ab281 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -11302,9 +11302,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11302 11302
11303 m_groupPowers.Clear(); 11303 m_groupPowers.Clear();
11304 11304
11305 for (int i = 0; i < GroupMembership.Length; i++) 11305 if (GroupMembership != null)
11306 { 11306 {
11307 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; 11307 for (int i = 0; i < GroupMembership.Length; i++)
11308 {
11309 m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers;
11310 }
11308 } 11311 }
11309 } 11312 }
11310 } 11313 }
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 37cdaae..9eaa758 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -406,6 +406,11 @@ namespace Flotsam.RegionModules.AssetCache
406 return asset; 406 return asset;
407 } 407 }
408 408
409 public AssetBase GetCached(string id)
410 {
411 return Get(id);
412 }
413
409 public void Expire(string id) 414 public void Expire(string id)
410 { 415 {
411 if (m_LogLevel >= 2) 416 if (m_LogLevel >= 2)
diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs
new file mode 100644
index 0000000..53d2cef
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs
@@ -0,0 +1,220 @@
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;
30using System.Collections.Specialized;
31using System.Reflection;
32using System.IO;
33using System.Web;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using Caps = OpenSim.Framework.Capabilities.Caps;
45
46namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps
47{
48 #region Stream Handler
49
50 public delegate byte[] StreamHandlerCallback(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse);
51
52 public class StreamHandler : BaseStreamHandler
53 {
54 StreamHandlerCallback m_callback;
55
56 public StreamHandler(string httpMethod, string path, StreamHandlerCallback callback)
57 : base(httpMethod, path)
58 {
59 m_callback = callback;
60 }
61
62 public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
63 {
64 return m_callback(path, request, httpRequest, httpResponse);
65 }
66 }
67
68 #endregion Stream Handler
69
70 public class GetTextureModule : IRegionModule
71 {
72 private static readonly ILog m_log =
73 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
74 private Scene m_scene;
75 private IAssetService m_assetService;
76
77 #region IRegionModule Members
78
79 public void Initialise(Scene pScene, IConfigSource pSource)
80 {
81 m_scene = pScene;
82 }
83
84 public void PostInitialise()
85 {
86 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
87 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
88 }
89
90 public void Close() { }
91
92 public string Name { get { return "GetTextureModule"; } }
93 public bool IsSharedModule { get { return false; } }
94
95 public void RegisterCaps(UUID agentID, Caps caps)
96 {
97 UUID capID = UUID.Random();
98
99 m_log.Info("[GETTEXTURE]: /CAPS/" + capID);
100 caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
101 }
102
103 #endregion
104
105 private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
106 {
107 // TODO: Change this to a config option
108 const string REDIRECT_URL = null;
109
110 // Try to parse the texture ID from the request URL
111 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
112 string textureStr = query.GetOne("texture_id");
113
114 if (m_assetService == null)
115 {
116 m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service");
117 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
118 return null;
119 }
120
121 UUID textureID;
122 if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
123 {
124 AssetBase texture;
125
126 if (!String.IsNullOrEmpty(REDIRECT_URL))
127 {
128 // Only try to fetch locally cached textures. Misses are redirected
129 texture = m_assetService.GetCached(textureID.ToString());
130
131 if (texture != null)
132 {
133 SendTexture(httpRequest, httpResponse, texture);
134 }
135 else
136 {
137 string textureUrl = REDIRECT_URL + textureID.ToString();
138 m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
139 httpResponse.RedirectLocation = textureUrl;
140 }
141 }
142 else
143 {
144 // Fetch locally or remotely. Misses return a 404
145 texture = m_assetService.Get(textureID.ToString());
146
147 if (texture != null)
148 {
149 SendTexture(httpRequest, httpResponse, texture);
150 }
151 else
152 {
153 m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
154 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
155 }
156 }
157 }
158 else
159 {
160 m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
161 }
162
163 httpResponse.Send();
164 return null;
165 }
166
167 private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture)
168 {
169 string range = request.Headers.GetOne("Range");
170 if (!String.IsNullOrEmpty(range))
171 {
172 // Range request
173 int start, end;
174 if (TryParseRange(range, out start, out end))
175 {
176 end = Utils.Clamp(end, 1, texture.Data.Length);
177 start = Utils.Clamp(start, 0, end - 1);
178
179 m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
180
181 if (end - start < texture.Data.Length)
182 response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
183
184 response.ContentLength = end - start;
185 response.ContentType = texture.Metadata.ContentType;
186
187 response.Body.Write(texture.Data, start, end - start);
188 }
189 else
190 {
191 m_log.Warn("Malformed Range header: " + range);
192 response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
193 }
194 }
195 else
196 {
197 // Full content request
198 response.ContentLength = texture.Data.Length;
199 response.ContentType = texture.Metadata.ContentType;
200 response.Body.Write(texture.Data, 0, texture.Data.Length);
201 }
202 }
203
204 private bool TryParseRange(string header, out int start, out int end)
205 {
206 if (header.StartsWith("bytes="))
207 {
208 string[] rangeValues = header.Substring(6).Split('-');
209 if (rangeValues.Length == 2)
210 {
211 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
212 return true;
213 }
214 }
215
216 start = end = 0;
217 return false;
218 }
219 }
220}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index af2f3d6..ebd6bbd 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -229,6 +229,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
229 return asset; 229 return asset;
230 } 230 }
231 231
232 public AssetBase GetCached(string id)
233 {
234 if (m_Cache != null)
235 return m_Cache.Get(id);
236
237 return null;
238 }
239
232 public AssetMetadata GetMetadata(string id) 240 public AssetMetadata GetMetadata(string id)
233 { 241 {
234 AssetBase asset = null; 242 AssetBase asset = null;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 50348da..1b3419d 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -165,6 +165,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
165 return asset; 165 return asset;
166 } 166 }
167 167
168 public AssetBase GetCached(string id)
169 {
170 if (m_Cache != null)
171 return m_Cache.Get(id);
172
173 return null;
174 }
175
168 public AssetMetadata GetMetadata(string id) 176 public AssetMetadata GetMetadata(string id)
169 { 177 {
170 AssetBase asset = null; 178 AssetBase asset = null;