OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
LoadImageURLModule.cs
Go to the documentation of this file.
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 
28 using System;
29 using System.Drawing;
30 using System.IO;
31 using System.Net;
32 using Nini.Config;
33 using OpenMetaverse;
34 using OpenMetaverse.Imaging;
35 using OpenSim.Framework;
36 using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
37 using OpenSim.Region.Framework.Interfaces;
38 using OpenSim.Region.Framework.Scenes;
39 using log4net;
40 using System.Reflection;
41 using Mono.Addins;
42 
43 namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
44 {
45  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LoadImageURLModule")]
47  {
48  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 
50  private string m_name = "LoadImageURL";
51  private Scene m_scene;
52  private IDynamicTextureManager m_textureManager;
53 
54  private OutboundUrlFilter m_outboundUrlFilter;
55  private string m_proxyurl = "";
56  private string m_proxyexcepts = "";
57 
58  #region IDynamicTextureRender Members
59 
60  public string GetName()
61  {
62  return m_name;
63  }
64 
65  public string GetContentType()
66  {
67  return ("image");
68  }
69 
70  public bool SupportsAsynchronous()
71  {
72  return true;
73  }
74 
75 // public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
76 // {
77 // // We don't support conversion of body data.
78 // return false;
79 // }
80 
81  public IDynamicTexture ConvertUrl(string url, string extraParams)
82  {
83  return null;
84  }
85 
86  public IDynamicTexture ConvertData(string bodyData, string extraParams)
87  {
88  return null;
89  }
90 
91  public bool AsyncConvertUrl(UUID id, string url, string extraParams)
92  {
93  return MakeHttpRequest(url, id);
94  }
95 
96  public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
97  {
98  return false;
99  }
100 
101  public void GetDrawStringSize(string text, string fontName, int fontSize,
102  out double xSize, out double ySize)
103  {
104  xSize = 0;
105  ySize = 0;
106  }
107 
108  #endregion
109 
110  #region ISharedRegionModule Members
111 
112  public void Initialise(IConfigSource config)
113  {
114  m_outboundUrlFilter = new OutboundUrlFilter("Script dynamic texture image module", config);
115  m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
116  m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
117  }
118 
119  public void PostInitialise()
120  {
121  }
122 
123  public void AddRegion(Scene scene)
124  {
125  if (m_scene == null)
126  m_scene = scene;
127 
128  }
129 
130  public void RemoveRegion(Scene scene)
131  {
132  }
133 
134  public void RegionLoaded(Scene scene)
135  {
136  if (m_textureManager == null && m_scene == scene)
137  {
138  m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
139  if (m_textureManager != null)
140  {
141  m_textureManager.RegisterRender(GetContentType(), this);
142  }
143  }
144  }
145 
146  public void Close()
147  {
148  }
149 
150  public string Name
151  {
152  get { return m_name; }
153  }
154 
155  public Type ReplaceableInterface
156  {
157  get { return null; }
158  }
159 
160  #endregion
161 
162  private bool MakeHttpRequest(string url, UUID requestID)
163  {
164  if (!m_outboundUrlFilter.CheckAllowed(new Uri(url)))
165  return false;
166 
167  HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
168  request.AllowAutoRedirect = false;
169 
170  if (!string.IsNullOrEmpty(m_proxyurl))
171  {
172  if (!string.IsNullOrEmpty(m_proxyexcepts))
173  {
174  string[] elist = m_proxyexcepts.Split(';');
175  request.Proxy = new WebProxy(m_proxyurl, true, elist);
176  }
177  else
178  {
179  request.Proxy = new WebProxy(m_proxyurl, true);
180  }
181  }
182 
183  RequestState state = new RequestState(request, requestID);
184  // IAsyncResult result = request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
185  request.BeginGetResponse(new AsyncCallback(HttpRequestReturn), state);
186 
187  TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
188  state.TimeOfRequest = (int) t.TotalSeconds;
189 
190  return true;
191  }
192 
193  private void HttpRequestReturn(IAsyncResult result)
194  {
195  if (m_textureManager == null)
196  {
197  m_log.WarnFormat("[LOADIMAGEURLMODULE]: No texture manager. Can't function.");
198  return;
199  }
200 
201  RequestState state = (RequestState) result.AsyncState;
202  WebRequest request = (WebRequest) state.Request;
203  Stream stream = null;
204  byte[] imageJ2000 = new byte[0];
205  Size newSize = new Size(0, 0);
206  HttpWebResponse response = null;
207 
208  try
209  {
210  response = (HttpWebResponse)request.EndGetResponse(result);
211  if (response != null && response.StatusCode == HttpStatusCode.OK)
212  {
213  stream = response.GetResponseStream();
214  if (stream != null)
215  {
216  try
217  {
218  Bitmap image = new Bitmap(stream);
219 
220  // TODO: make this a bit less hard coded
221  if ((image.Height < 64) && (image.Width < 64))
222  {
223  newSize.Width = 32;
224  newSize.Height = 32;
225  }
226  else if ((image.Height < 128) && (image.Width < 128))
227  {
228  newSize.Width = 64;
229  newSize.Height = 64;
230  }
231  else if ((image.Height < 256) && (image.Width < 256))
232  {
233  newSize.Width = 128;
234  newSize.Height = 128;
235  }
236  else if ((image.Height < 512 && image.Width < 512))
237  {
238  newSize.Width = 256;
239  newSize.Height = 256;
240  }
241  else if ((image.Height < 1024 && image.Width < 1024))
242  {
243  newSize.Width = 512;
244  newSize.Height = 512;
245  }
246  else
247  {
248  newSize.Width = 1024;
249  newSize.Height = 1024;
250  }
251 
252  using (Bitmap resize = new Bitmap(image, newSize))
253  {
254  imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
255  }
256  }
257  catch (Exception)
258  {
259  m_log.Error("[LOADIMAGEURLMODULE]: OpenJpeg Conversion Failed. Empty byte data returned!");
260  }
261  }
262  else
263  {
264  m_log.WarnFormat("[LOADIMAGEURLMODULE] No data returned");
265  }
266  }
267  }
268  catch (WebException)
269  {
270  }
271  finally
272  {
273  if (stream != null)
274  stream.Close();
275 
276  if (response != null)
277  {
278  if (response.StatusCode == HttpStatusCode.MovedPermanently
279  || response.StatusCode == HttpStatusCode.Found
280  || response.StatusCode == HttpStatusCode.SeeOther
281  || response.StatusCode == HttpStatusCode.TemporaryRedirect)
282  {
283  string redirectedUrl = response.Headers["Location"];
284 
285  MakeHttpRequest(redirectedUrl, state.RequestID);
286  }
287  else
288  {
289  m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
290  imageJ2000.Length, state.RequestID);
291 
292  m_textureManager.ReturnData(
293  state.RequestID,
295  request.RequestUri, null, imageJ2000, newSize, false));
296  }
297  response.Close();
298  }
299  }
300  }
301 
302  #region Nested type: RequestState
303 
304  public class RequestState
305  {
306  public HttpWebRequest Request = null;
307  public UUID RequestID = UUID.Zero;
308  public int TimeOfRequest = 0;
309 
310  public RequestState(HttpWebRequest request, UUID requestID)
311  {
312  Request = request;
313  RequestID = requestID;
314  }
315  }
316 
317  #endregion
318  }
319 }
IDynamicTexture ConvertData(string bodyData, string extraParams)
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize)
IDynamicTexture ConvertUrl(string url, string extraParams)
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
Interactive OpenSim region server
Definition: OpenSim.cs:55
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
bool AsyncConvertData(UUID id, string bodyData, string extraParams)
bool AsyncConvertUrl(UUID id, string url, string extraParams)
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...