context: /*
   * Copyright (c) Contributors, http://opensimulator.org/
   * See CONTRIBUTORS.TXT for a full list of copyright holders.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *     * Redistributions of source code must retain the above copyright
   *       notice, this list of conditions and the following disclaimer.
   *     * Redistributions in binary form must reproduce the above copyright
   *       notice, this list of conditions and the following disclaimer in the
   *       documentation and/or other materials provided with the distribution.
   *     * Neither the name of the OpenSimulator Project nor the
   *       names of its contributors may be used to endorse or promote products
   *       derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
   * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */
  
  using System;
  using System.Threading;
  using System.Collections.Generic;
  using System.Collections;
  using System.Reflection;
  using log4net;
  using Mono.Addins;
  using Nini.Config;
  using OpenMetaverse;
  using OpenSim.Framework;
  using OpenSim.Framework.Servers;
  using OpenSim.Framework.Servers.HttpServer;
  using OpenSim.Region.Framework.Interfaces;
  using OpenSim.Region.Framework.Scenes;
  
  namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
  {
      /// <summary>
      /// Data describing an external URL set up by a script.
      /// </summary>
      public class UrlData
      {
          /// <summary>
          /// Scene object part hosting the script
          /// </summary>
          public UUID hostID;
  
          /// <summary>
          /// The item ID of the script that requested the URL.
          /// </summary>
          public UUID itemID;
  
          /// <summary>
          /// The script engine that runs the script.
          /// </summary>
          public IScriptModule engine;
  
          /// <summary>
          /// The generated URL.
          /// </summary>
          public string url;
  
          /// <summary>
          /// The random UUID component of the generated URL.
          /// </summary>
          public UUID urlcode;
  
          /// <summary>
          /// The external requests currently being processed or awaiting retrieval for this URL.
          /// </summary>
          public Dictionary<UUID, RequestData> requests;
      }
  
      public class RequestData
      {
          public UUID requestID;
          public Dictionary<string, string> headers;
          public string body;
          public int responseCode;
          public string responseBody;
          public string responseType = "text/plain";
          //public ManualResetEvent ev;
          public bool requestDone;
          public int startTime;
          public string uri;
      }
  
      /// <summary>
      /// This module provides external URLs for in-world scripts.
      /// </summary>
      [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UrlModule")]
      public class UrlModule : ISharedRegionModule, IUrlModule
      {
          private static readonly ILog m_log =
                  LogManager.GetLogger(
                  MethodBase.GetCurrentMethod().DeclaringType);
  
          /// <summary>
          /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the request ID
          /// randomly generated when a request is received for this URL.
          /// </summary>
          /// <remarks>
          /// Manipulation or retrieval from this dictionary must be locked on m_UrlMap to preserve consistency with
          /// m_UrlMap
          /// </remarks>
          private Dictionary<UUID, UrlData> m_RequestMap = new Dictionary<UUID, UrlData>();
  
          /// <summary>
          /// Indexs the URL request metadata (which script requested it, outstanding requests, etc.) by the full URL
          /// </summary>
          private Dictionary<string, UrlData> m_UrlMap = new Dictionary<string, UrlData>();
  
          /// <summary>
          /// Maximum number of external urls that can be set up by this module.
          /// </summary>
          private int m_TotalUrls = 100;
  
          private uint https_port = 0;
          private IHttpServer m_HttpServer = null;
          private IHttpServer m_HttpsServer = null;
  
          private string m_ExternalHostNameForLSL = "";
          public string ExternalHostNameForLSL
          {
              get { return m_ExternalHostNameForLSL; } 
          }
  
          public Type ReplaceableInterface 
          {
              get { return null; }
          }
  
          public string Name
          {
              get { return "UrlModule"; }
          }
  
          public void Initialise(IConfigSource config)
          {
              m_ExternalHostNameForLSL = config.Configs["Network"].GetString("ExternalHostNameForLSL", System.Environment.MachineName);
              bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener",false);
  
              if (ssl_enabled)
                  https_port = (uint) config.Configs["Network"].GetInt("https_port",0);
  
              IConfig llFunctionsConfig = config.Configs["LL-Functions"];
  
              if (llFunctionsConfig != null)
                  m_TotalUrls = llFunctionsConfig.GetInt("max_external_urls_per_simulator", m_TotalUrls);
          }
  
          public void PostInitialise()
          {
          }
  
          public void AddRegion(Scene scene)
          {
              if (m_HttpServer == null)
              {
                  // There can only be one
                  //
                  m_HttpServer = MainServer.Instance;
                  //
                  // We can use the https if it is enabled
                  if (https_port > 0)
                  {
                      m_HttpsServer = MainServer.GetHttpServer(https_port);
                  }
              }
  
              scene.RegisterModuleInterface<IUrlModule>(this);
  
              scene.EventManager.OnScriptReset += OnScriptReset;
          }
  
          public void RegionLoaded(Scene scene)
          {
              IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
              foreach (IScriptModule scriptModule in scriptModules)
              {
                  scriptModule.OnScriptRemoved += ScriptRemoved;
                  scriptModule.OnObjectRemoved += ObjectRemoved;
              }
          }
  
          public void RemoveRegion(Scene scene)
          {
          }
  
          public void Close()
          {
          }
  
          public UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID)
          {
              UUID urlcode = UUID.Random();
  
              lock (m_UrlMap)
              {
                  if (m_UrlMap.Count >= m_TotalUrls)
                  {
                      engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" });
                      return urlcode;
                  }
                  string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/";
  
                  UrlData urlData = new UrlData();
                  urlData.hostID = host.UUID;
                  urlData.itemID = itemID;
                  urlData.engine = engine;
                  urlData.url = url;
                  urlData.urlcode = urlcode;
                  urlData.requests = new Dictionary<UUID, RequestData>();
                  
                  m_UrlMap[url] = urlData;
                  
                  string uri = "/lslhttp/" + urlcode.ToString() + "/";
                 
                  m_HttpServer.AddPollServiceHTTPHandler(
                      uri,
                      new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode));
  
                  m_log.DebugFormat(
                      "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}",
                      uri, itemID, host.Name, host.LocalId);
  
                  engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_GRANTED", url });
              }
  
              return urlcode;
          }
  
          public UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID)
          {
              UUID urlcode = UUID.Random();
  
  
gt:             if (m_HttpsServer == null)