Пример #1
0
        private void HandleSimulatorFeaturesRequest(IOSHttpRequest request, IOSHttpResponse response, UUID agentID)
        {
            //            m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");

            if (request.HttpMethod != "GET")
            {
                response.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }

            ScenePresence sp = m_scene.GetScenePresence(agentID);

            if (sp == null)
            {
                response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
                response.AddHeader("Retry-After", "5");
                return;
            }

            OSDMap copy = DeepCopy();

            // Let's add the agentID to the destination guide, if it is expecting that.
            if (copy.ContainsKey("OpenSimExtras") && ((OSDMap)(copy["OpenSimExtras"])).ContainsKey("destination-guide-url"))
            {
                ((OSDMap)copy["OpenSimExtras"])["destination-guide-url"] = Replace(((OSDMap)copy["OpenSimExtras"])["destination-guide-url"], "[USERID]", agentID.ToString());
            }

            OnSimulatorFeaturesRequest?.Invoke(agentID, ref copy);

            //Send back data
            response.RawBuffer  = Util.UTF8.GetBytes(OSDParser.SerializeLLSDXmlString(copy));
            response.StatusCode = (int)HttpStatusCode.OK;
        }
 private byte[] OKResponse(IOSHttpResponse httpResponse)
 {
     m_log.Debug("[HELO]: hi, GET was called");
     httpResponse.AddHeader("X-Handlers-Provided", m_HandlersType);
     httpResponse.StatusCode = (int)HttpStatusCode.OK;
     httpResponse.StatusDescription = "OK";
     return new byte[0];
 }
 private byte[] OKResponse(IOSHttpResponse httpResponse)
 {
     m_log.Debug("[HELO]: hi, HEAD was called");
     httpResponse.AddHeader("X-Handlers-Provided", m_HandlersType);
     httpResponse.StatusCode        = (int)HttpStatusCode.OK;
     httpResponse.StatusDescription = "OK";
     return(new byte[0]);
 }
Пример #4
0
        private void GetEnvironmentSettings(IOSHttpResponse response, UUID agentID)
        {
            // m_log.DebugFormat("[{0}]: Environment GET handle for agentID {1} in region {2}",
            //      Name, agentID, caps.RegionName);

            ViewerEnvironment VEnv = null;
            ScenePresence     sp   = m_scene.GetScenePresence(agentID);

            if (sp == null)
            {
                response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
                response.AddHeader("Retry-After", "5");
                return;
            }

            if (sp.Environment != null)
            {
                VEnv = sp.Environment;
            }
            else
            {
                if (m_scene.RegionInfo.EstateSettings.AllowEnvironmentOverride)
                {
                    ILandObject land = m_scene.LandChannel.GetLandObject(sp.AbsolutePosition.X, sp.AbsolutePosition.Y);
                    if (land != null && land.LandData != null && land.LandData.Environment != null)
                    {
                        VEnv = land.LandData.Environment;
                    }
                }
            }
            if (VEnv == null)
            {
                VEnv = GetRegionEnvironment();
            }

            byte[] envBytes = VEnv.ToCapWLBytes(UUID.Zero, regionID);
            if (envBytes == null)
            {
                osUTF8 sb = LLSDxmlEncode2.Start();
                LLSDxmlEncode2.AddArray(sb);
                LLSDxmlEncode2.AddMap(sb);
                LLSDxmlEncode2.AddElem("messageID", UUID.Zero, sb);
                LLSDxmlEncode2.AddElem("regionID", regionID, sb);
                LLSDxmlEncode2.AddEndMap(sb);
                LLSDxmlEncode2.AddEndArray(sb);
                response.RawBuffer = LLSDxmlEncode2.EndToBytes(sb);
            }
            else
            {
                response.RawBuffer = envBytes;
            }

            response.StatusCode = (int)HttpStatusCode.OK;
        }
Пример #5
0
        public override byte[] Handle(string path, Stream requestData,
                                      IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            string resource = GetParam(path);
            string region   = "DEFAULT";

            if (resource != string.Empty)
            {
                string[] parts = resource.Split('/');
                region = HttpUtility.UrlDecode(parts[1]);
            }
            m_log.DebugFormat("[PotamOS]: region is {0} ({1})", region, resource);

            Scene scene = m_Scenes[0];

            if (region != "DEFAULT")
            {
                scene = m_Scenes.Find(s => s.RegionInfo.RegionName == region);
                if (scene == null)
                {
                    m_log.WarnFormat("[PotamOS]: Requested region {0} not found here. Sending the first region.", region);
                    scene = m_Scenes[0];
                }
            }

            httpResponse.StatusCode  = (int)OSHttpStatusCode.SuccessOk;
            httpResponse.ContentType = "application/xml";
            httpResponse.AddHeader("Content-Encoding", "gzip");
            IRegionSerialiserModule serial = scene.RequestModuleInterface <IRegionSerialiserModule>();

            byte[] xml = new byte[0];
            if (serial != null)
            {
                using (MemoryStream mem = new MemoryStream())
                {
                    using (GZipStream zip = new GZipStream(mem, CompressionMode.Compress))
                        using (TextWriter writer = new StreamWriter(zip))
                        {
                            serial.SavePrimsToXml2(scene, writer, new Vector3(0.01f, 0.01f, 0.01f), new Vector3(1000, 1000, 1000));
                        }
                    string xmlstr = Encoding.UTF8.GetString(mem.ToArray());
                    xml = mem.ToArray();
                    m_log.DebugFormat("[PotamOS]: size of xml scene is {0}", xml.Length);
                }
            }
            return(xml);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="httpRequest"></param>
        /// <param name="httpResponse"></param>
        /// <param name="textureID"></param>
        /// <param name="format"></param>
        /// <returns>False for "caller try another codec"; true otherwise</returns>
        private bool FetchTexture(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID textureID, string format)
        {
            // m_log.DebugFormat("[GETTEXTURE]: {0} with requested format {1}", textureID, format);
            if (!String.IsNullOrEmpty(m_RedirectURL))
            {
                string textureUrl = m_RedirectURL + "?texture_id=" + textureID.ToString();
                m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl);
                httpResponse.StatusCode = (int)HttpStatusCode.Moved;
                httpResponse.AddHeader("Location:", textureUrl);
                return(true);
            }

            // Fetch,  Misses or invalid return a 404
            AssetBase texture = m_assetService.Get(textureID.ToString());

            if (texture != null)
            {
                if (texture.Type != (sbyte)AssetType.Texture)
                {
                    httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
                    return(true);
                }
                if (format == DefaultFormat)
                {
                    WriteTextureData(httpRequest, httpResponse, texture, format);
                    return(true);
                }

                // need to convert format
                AssetBase newTexture = new AssetBase(texture.ID + "-" + format, texture.Name, (sbyte)AssetType.Texture, texture.Metadata.CreatorID);
                newTexture.Data = ConvertTextureData(texture, format);
                if (newTexture.Data.Length == 0)
                {
                    return(false); // !!! Caller try another codec, please!
                }
                newTexture.Flags     = AssetFlags.Collectable;
                newTexture.Temporary = true;
                newTexture.Local     = true;
                WriteTextureData(httpRequest, httpResponse, newTexture, format);
                return(true);
            }

            // not found
            // m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found");
            httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
            return(true);
        }
Пример #7
0
 protected override void ProcessRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
 {
     if (httpRequest.HttpMethod == "GET")
     {
         //Obsolete
         m_log.Debug("[HELO]: hi, GET was called");
     }
     else if (httpRequest.HttpMethod == "HEAD")
     {
         m_log.Debug("[HELO]: hi, HEAD was called");
     }
     else
     {
         httpResponse.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
         return;
     }
     httpResponse.AddHeader("X-Handlers-Provided", m_HandlersType);
     httpResponse.StatusCode = (int)HttpStatusCode.OK;
 }
Пример #8
0
        protected override byte[] ProcessRequest(string path, Stream request,
                                                 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            byte[] result = new byte[0];

            string[] p = SplitParams(path);

            if (p.Length == 0)
            {
                return(result);
            }

            string id = string.Empty;

            if (p.Length > 1)
            {
                id = p[0];
                string cmd = p[1];

                if (cmd == "data")
                {
                    result = m_AssetService.GetData(id);
                    if (result == null)
                    {
                        httpResponse.StatusCode  = (int)HttpStatusCode.NotFound;
                        httpResponse.ContentType = "text/plain";
                        result = new byte[0];
                    }
                    else
                    {
                        httpResponse.StatusCode  = (int)HttpStatusCode.OK;
                        httpResponse.ContentType = "application/octet-stream";
                    }
                }
                else if (cmd == "metadata")
                {
                    AssetMetadata metadata = m_AssetService.GetMetadata(id);

                    if (metadata != null)
                    {
                        XmlSerializer xs =
                            new XmlSerializer(typeof(AssetMetadata));
                        result = ServerUtils.SerializeResult(xs, metadata);

                        httpResponse.StatusCode  = (int)HttpStatusCode.OK;
                        httpResponse.ContentType =
                            SLUtil.SLAssetTypeToContentType(metadata.Type);
                    }
                    else
                    {
                        httpResponse.StatusCode  = (int)HttpStatusCode.NotFound;
                        httpResponse.ContentType = "text/plain";
                        result = new byte[0];
                    }
                }
                else
                {
                    // Unknown request
                    httpResponse.StatusCode  = (int)HttpStatusCode.BadRequest;
                    httpResponse.ContentType = "text/plain";
                    result = new byte[0];
                }
            }
            else if (p.Length == 1)
            {
                // Get the entire asset (metadata + data)

                id = p[0];
                AssetBase asset = m_AssetService.Get(id);

                if (asset != null)
                {
                    XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
                    result = ServerUtils.SerializeResult(xs, asset);

                    httpResponse.StatusCode  = (int)HttpStatusCode.OK;
                    httpResponse.ContentType =
                        SLUtil.SLAssetTypeToContentType(asset.Type);
                }
                else
                {
                    httpResponse.StatusCode  = (int)HttpStatusCode.NotFound;
                    httpResponse.ContentType = "text/plain";
                    result = new byte[0];
                }
            }
            else
            {
                // Unknown request
                httpResponse.StatusCode  = (int)HttpStatusCode.BadRequest;
                httpResponse.ContentType = "text/plain";
                result = new byte[0];
            }

            if (httpResponse.StatusCode == (int)HttpStatusCode.NotFound && !string.IsNullOrEmpty(m_RedirectURL) && !string.IsNullOrEmpty(id))
            {
                httpResponse.StatusCode = (int)HttpStatusCode.Redirect;
                string rurl = m_RedirectURL;
                if (!path.StartsWith("/"))
                {
                    rurl += "/";
                }
                rurl += path;
                httpResponse.AddHeader("Location", rurl);
                m_log.DebugFormat("[ASSET GET HANDLER]: Asset not found, redirecting to {0} ({1})", rurl, httpResponse.StatusCode);
            }
            return(result);
        }
        private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
        {
            string range = request.Headers.GetOne("Range");
 
            if (!String.IsNullOrEmpty(range)) // JP2's only
            {
                // Range request
                int start, end;
                if (TryParseRange(range, out start, out end))
                {
                    // Before clamping start make sure we can satisfy it in order to avoid
                    // sending back the last byte instead of an error status
                    if (start >= texture.Data.Length)
                    {
//                        m_log.DebugFormat(
//                            "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
//                            texture.ID, start, texture.Data.Length);
 
                        // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
                        // Requested Range Not Satisfiable (416) here.  However, it appears that at least recent implementations
                        // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
                        // received a very small texture  may attempt to fetch bytes from the server past the
                        // range of data that it received originally.  Whether this happens appears to depend on whether
                        // the viewer's estimation of how large a request it needs to make for certain discard levels
                        // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
                        // level 2.  If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
                        // here will cause the viewer to treat the texture as bad and never display the full resolution
                        // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
 
//                        response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
//                        response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
//                        response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
                        response.ContentType = texture.Metadata.ContentType;
                    }
                    else
                    {
                        // Handle the case where no second range value was given.  This is equivalent to requesting
                        // the rest of the entity.
                        if (end == -1)
                            end = int.MaxValue;
 
                        end = Utils.Clamp(end, 0, texture.Data.Length - 1);
                        start = Utils.Clamp(start, 0, end);
                        int len = end - start + 1;
 
//                        m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
 
                        // Always return PartialContent, even if the range covered the entire data length
                        // We were accidentally sending back 404 before in this situation
                        // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
                        // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
                        //
                        // We also do not want to send back OK even if the whole range was satisfiable since this causes
                        // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
//                        if (end > maxEnd)
//                            response.StatusCode = (int)System.Net.HttpStatusCode.OK;
//                        else
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
 
                        response.ContentLength = len;
                        response.ContentType = texture.Metadata.ContentType;
                        response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
 
                        response.Body.Write(texture.Data, start, len);
                    }
                }
                else
                {
                    m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
                    response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                }
            }
            else // JP2's or other formats
            {
                // Full content request
                response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                response.ContentLength = texture.Data.Length;
                if (format == DefaultFormat)
                    response.ContentType = texture.Metadata.ContentType;
                else
                    response.ContentType = "image/" + format;
                response.Body.Write(texture.Data, 0, texture.Data.Length);
            }
 
//            if (response.StatusCode < 200 || response.StatusCode > 299)
//                m_log.WarnFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
//            else
//                m_log.DebugFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
        }
Пример #10
0
        private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
        {
            string range = request.Headers.GetOne("Range");

            if (!String.IsNullOrEmpty(range))
            {
                // Range request
                int start, end;
                if (TryParseRange(range, out start, out end))
                {
                    // Before clamping start make sure we can satisfy it in order to avoid
                    // sending back the last byte instead of an error status
                    if (start >= texture.Data.Length)
                    {
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
                        response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
                        response.ContentType = texture.Metadata.ContentType;
                    }
                    else
                    {
                        // Handle the case where no second range value was given.  This is equivalent to requesting
                        // the rest of the entity.
                        if (end == -1)
                        {
                            end = int.MaxValue;
                        }

                        end   = Utils.Clamp(end, 0, texture.Data.Length - 1);
                        start = Utils.Clamp(start, 0, end);
                        int len = end - start + 1;

                        if (0 == start && len == texture.Data.Length)
                        {
                            response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                        }
                        else
                        {
                            response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
                            response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
                        }

                        response.ContentLength = len;
                        response.ContentType   = "application/vnd.ll.mesh";

                        response.Body.Write(texture.Data, start, len);
                    }
                }
                else
                {
                    m_log.Warn("[GETMESH]: Malformed Range header: " + range);
                    response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                }
            }
            else
            {
                // Full content request
                response.StatusCode    = (int)System.Net.HttpStatusCode.OK;
                response.ContentLength = texture.Data.Length;
                response.ContentType   = "application/vnd.ll.mesh";
                response.Body.Write(texture.Data, 0, texture.Data.Length);
            }
        }
Пример #11
0
        private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
        {
            string range = request.Headers.GetOne("Range");

            if (!String.IsNullOrEmpty(range)) // JP2's only
            {
                // Range request
                int start, end;
                if (TryParseRange(range, out start, out end))
                {
                    // Before clamping start make sure we can satisfy it in order to avoid
                    // sending back the last byte instead of an error status
                    if (start >= texture.Data.Length)
                    {
//                        m_log.DebugFormat(
//                            "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
//                            texture.ID, start, texture.Data.Length);

                        // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
                        // Requested Range Not Satisfiable (416) here.  However, it appears that at least recent implementations
                        // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
                        // received a very small texture  may attempt to fetch bytes from the server past the
                        // range of data that it received originally.  Whether this happens appears to depend on whether
                        // the viewer's estimation of how large a request it needs to make for certain discard levels
                        // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
                        // level 2.  If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
                        // here will cause the viewer to treat the texture as bad and never display the full resolution
                        // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.

//                        response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
//                        response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
//                        response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                        response.StatusCode  = (int)System.Net.HttpStatusCode.PartialContent;
                        response.ContentType = texture.Metadata.ContentType;
                    }
                    else
                    {
                        // Handle the case where no second range value was given.  This is equivalent to requesting
                        // the rest of the entity.
                        if (end == -1)
                        {
                            end = int.MaxValue;
                        }

                        end   = Utils.Clamp(end, 0, texture.Data.Length - 1);
                        start = Utils.Clamp(start, 0, end);
                        int len = end - start + 1;

//                        m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);

                        // Always return PartialContent, even if the range covered the entire data length
                        // We were accidentally sending back 404 before in this situation
                        // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
                        // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
                        //
                        // We also do not want to send back OK even if the whole range was satisfiable since this causes
                        // HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
//                        if (end > maxEnd)
//                            response.StatusCode = (int)System.Net.HttpStatusCode.OK;
//                        else
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;

                        response.ContentLength = len;
                        response.ContentType   = texture.Metadata.ContentType;
                        response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));

                        response.Body.Write(texture.Data, start, len);
                    }
                }
                else
                {
                    m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
                    response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                }
            }
            else // JP2's or other formats
            {
                // Full content request
                response.StatusCode    = (int)System.Net.HttpStatusCode.OK;
                response.ContentLength = texture.Data.Length;
                if (format == DefaultFormat)
                {
                    response.ContentType = texture.Metadata.ContentType;
                }
                else
                {
                    response.ContentType = "image/" + format;
                }
                response.Body.Write(texture.Data, 0, texture.Data.Length);
            }

//            if (response.StatusCode < 200 || response.StatusCode > 299)
//                m_log.WarnFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
//            else
//                m_log.DebugFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
        }
 private void ProcessServerReleaseNotes(IOSHttpResponse httpResponse)
 {
     httpResponse.StatusCode = (int)HttpStatusCode.Moved;
     httpResponse.AddHeader("Location", m_ServerReleaseNotesURL);
 }
Пример #13
0
        private void GetExtEnvironmentSettings(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse, UUID agentID)
        {
            int parcelid = -1;

            if (httpRequest.Query.Count > 0)
            {
                if (httpRequest.Query.ContainsKey("parcelid"))
                {
                    Int32.TryParse((string)httpRequest.Query["parcelid"], out parcelid);
                }
            }

            ScenePresence sp = m_scene.GetScenePresence(agentID);

            if (sp == null)
            {
                httpResponse.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
                httpResponse.AddHeader("Retry-After", "5");
                return;
            }

            ViewerEnvironment VEnv = null;

            if (sp.Environment != null)
            {
                VEnv = sp.Environment;
            }
            else if (parcelid == -1)
            {
                VEnv = GetRegionEnvironment();
            }
            else
            {
                if (m_scene.RegionInfo.EstateSettings.AllowEnvironmentOverride)
                {
                    ILandObject land = m_scene.LandChannel.GetLandObject(parcelid);
                    if (land != null && land.LandData != null && land.LandData.Environment != null)
                    {
                        VEnv = land.LandData.Environment;
                    }
                }
                if (VEnv == null)
                {
                    OSD def = ViewerEnvironment.DefaultToOSD(regionID, parcelid);
                    httpResponse.RawBuffer  = OSDParser.SerializeLLSDXmlToBytes(def);
                    httpResponse.StatusCode = (int)HttpStatusCode.OK;
                    return;
                }
            }

            byte[] envBytes = VEnv.ToCapBytes(regionID, parcelid);
            if (envBytes == null)
            {
                osUTF8 sb = LLSDxmlEncode2.Start();
                LLSDxmlEncode2.AddArray(sb);
                LLSDxmlEncode2.AddMap(sb);
                LLSDxmlEncode2.AddElem("messageID", UUID.Zero, sb);
                LLSDxmlEncode2.AddElem("regionID", regionID, sb);
                LLSDxmlEncode2.AddEndMap(sb);
                LLSDxmlEncode2.AddEndArray(sb);
                httpResponse.RawBuffer = LLSDxmlEncode2.EndToBytes(sb);
            }
            else
            {
                httpResponse.RawBuffer = envBytes;
            }

            httpResponse.StatusCode = (int)HttpStatusCode.OK;
        }
Пример #14
0
        private void WriteMeshData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture)
        {
            string range = request.Headers.GetOne("Range");

            if (!String.IsNullOrEmpty(range))
            {
                // Range request
                int start, end;
                if (TryParseRange(range, out start, out end))
                {
                    // Before clamping start make sure we can satisfy it in order to avoid
                    // sending back the last byte instead of an error status
                    if (start >= texture.Data.Length)
                    {
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
                        response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
                        response.ContentType = texture.Metadata.ContentType;
                    }
                    else
                    {
                        // Handle the case where no second range value was given.  This is equivalent to requesting
                        // the rest of the entity.
                        if (end == -1)
                            end = int.MaxValue;

                        end = Utils.Clamp(end, 0, texture.Data.Length - 1);
                        start = Utils.Clamp(start, 0, end);
                        int len = end - start + 1;

                        if (0 == start && len == texture.Data.Length)
                        {
                            response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                        }
                        else
                        {
                            response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
                            response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
                        }
                        
                        response.ContentLength = len;
                        response.ContentType = "application/vnd.ll.mesh";
    
                        response.Body.Write(texture.Data, start, len);
                    }
                }
                else
                {
                    m_log.Warn("[GETMESH]: Malformed Range header: " + range);
                    response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                }
            }
            else 
            {
                // Full content request
                response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                response.ContentLength = texture.Data.Length;
                response.ContentType = "application/vnd.ll.mesh";
                response.Body.Write(texture.Data, 0, texture.Data.Length);
            }
        }
Пример #15
0
        /// <summary>
        /// Handles all GET and POST requests for OpenID identifier pages and endpoint
        /// server communication
        /// </summary>
        protected override void ProcessRequest(
            string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            Uri providerEndpoint = new Uri(String.Format("{0}://{1}{2}", httpRequest.Url.Scheme, httpRequest.Url.Authority, httpRequest.Url.AbsolutePath));

            // Defult to returning HTML content
            httpResponse.ContentType = ContentType;

            try
            {
                string forPost;
                using (StreamReader sr = new StreamReader(httpRequest.InputStream))
                    forPost = sr.ReadToEnd();
                NameValueCollection postQuery   = HttpUtility.ParseQueryString(forPost);
                NameValueCollection getQuery    = HttpUtility.ParseQueryString(httpRequest.Url.Query);
                NameValueCollection openIdQuery = (postQuery.GetValues("openid.mode") != null ? postQuery : getQuery);

                OpenIdProvider provider = new OpenIdProvider(m_openidStore, providerEndpoint, httpRequest.Url, openIdQuery);

                if (provider.Request != null)
                {
                    if (!provider.Request.IsResponseReady && provider.Request is IAuthenticationRequest)
                    {
                        IAuthenticationRequest authRequest = (IAuthenticationRequest)provider.Request;
                        string[] passwordValues            = postQuery.GetValues("pass");

                        UserAccount account;
                        if (TryGetAccount(new Uri(authRequest.ClaimedIdentifier.ToString()), out account))
                        {
                            // Check for form POST data
                            if (passwordValues != null && passwordValues.Length == 1)
                            {
                                if (account != null &&
                                    (m_authenticationService.Authenticate(account.PrincipalID, Util.Md5Hash(passwordValues[0]), 30) != string.Empty))
                                {
                                    authRequest.IsAuthenticated = true;
                                }
                                else
                                {
                                    authRequest.IsAuthenticated = false;
                                }
                            }
                            else
                            {
                                // Authentication was requested, send the client a login form
                                using (StreamWriter writer = new StreamWriter(response))
                                    writer.Write(String.Format(LOGIN_PAGE, account.FirstName, account.LastName));
                                return;
                            }
                        }
                        else
                        {
                            // Cannot find an avatar matching the claimed identifier
                            authRequest.IsAuthenticated = false;
                        }
                    }

                    // Add OpenID headers to the response
                    foreach (string key in provider.Request.Response.Headers.Keys)
                    {
                        httpResponse.AddHeader(key, provider.Request.Response.Headers[key]);
                    }

                    string[] contentTypeValues = provider.Request.Response.Headers.GetValues("Content-Type");
                    if (contentTypeValues != null && contentTypeValues.Length == 1)
                    {
                        httpResponse.ContentType = contentTypeValues[0];
                    }

                    // Set the response code and document body based on the OpenID result
                    httpResponse.StatusCode = (int)provider.Request.Response.Code;
                    response.Write(provider.Request.Response.Body, 0, provider.Request.Response.Body.Length);
                    response.Close();
                }
                else if (httpRequest.Url.AbsolutePath.Contains("/openid/server"))
                {
                    // Standard HTTP GET was made on the OpenID endpoint, send the client the default error page
                    using (StreamWriter writer = new StreamWriter(response))
                        writer.Write(ENDPOINT_PAGE);
                }
                else
                {
                    // Try and lookup this avatar
                    UserAccount account;
                    if (TryGetAccount(httpRequest.Url, out account))
                    {
                        using (StreamWriter writer = new StreamWriter(response))
                        {
                            // TODO: Print out a full profile page for this avatar
                            writer.Write(String.Format(OPENID_PAGE, httpRequest.Url.Scheme,
                                                       httpRequest.Url.Authority, account.FirstName, account.LastName));
                        }
                    }
                    else
                    {
                        // Couldn't parse an avatar name, or couldn't find the avatar in the user server
                        using (StreamWriter writer = new StreamWriter(response))
                            writer.Write(INVALID_OPENID_PAGE);
                    }
                }
            }
            catch (Exception ex)
            {
                httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
                using (StreamWriter writer = new StreamWriter(response))
                    writer.Write(ex.Message);
            }
        }
Пример #16
0
        protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            if (!Monitor.TryEnter(ev, 5000))
            {
                httpResponse.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
                httpResponse.AddHeader("Retry-After", "10");
                return(new byte[0]);
            }

            byte[] result = new byte[0];
            string format = string.Empty;

            //UUID scopeID = new UUID("07f8d88e-cd5e-4239-a0ed-843f75d09992");
            UUID scopeID = UUID.Zero;

            // This will be map/tilefile.ext, but on multitenancy it will be
            // map/scope/teilefile.ext
            path = path.Trim('/');
            string[] bits = path.Split(new char[] { '/' });
            if (bits.Length > 2)
            {
                try
                {
                    scopeID = new UUID(bits[1]);
                }
                catch
                {
                    return(new byte[9]);
                }
                path = bits[2];
                path = path.Trim('/');
            }

            if (path.Length == 0)
            {
                httpResponse.StatusCode  = (int)HttpStatusCode.NotFound;
                httpResponse.ContentType = "text/plain";
                return(new byte[0]);
            }

            result = m_MapService.GetMapTile(path, scopeID, out format);
            if (result.Length > 0)
            {
                httpResponse.StatusCode = (int)HttpStatusCode.OK;
                if (format.Equals(".png"))
                {
                    httpResponse.ContentType = "image/png";
                }
                else if (format.Equals(".jpg") || format.Equals(".jpeg"))
                {
                    httpResponse.ContentType = "image/jpeg";
                }
            }
            else
            {
                httpResponse.StatusCode  = (int)HttpStatusCode.NotFound;
                httpResponse.ContentType = "text/plain";
            }

            Monitor.Exit(ev);

            return(result);
        }
Пример #17
0
        private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
        {
            string range = request.Headers.GetOne("Range");

            if (!String.IsNullOrEmpty(range)) // JP2's only
            {
                // Range request
                int start, end;
                if (TryParseRange(range, out start, out end))
                {

                    // Before clamping start make sure we can satisfy it in order to avoid
                    // sending back the last byte instead of an error status
                    if (start >= texture.Data.Length)
                    {
                        response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
                    }
                    else
                    {
                        end = Utils.Clamp(end, 0, texture.Data.Length - 1);
                        start = Utils.Clamp(start, 0, end);
                        int len = end - start + 1;

                        //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);

                        // Always return PartialContent, even if the range covered the entire data length
                        // We were accidentally sending back 404 before in this situation
                        // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
                        // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;

                        response.ContentLength = len;
                        response.ContentType = texture.Metadata.ContentType;
                        response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));
    
                        response.Body.Write(texture.Data, start, len);
                    }
                }
                else
                {
                    m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
                    response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                }
            }
            else // JP2's or other formats
            {
                // Full content request
                response.StatusCode = (int)System.Net.HttpStatusCode.OK;
                response.ContentLength = texture.Data.Length;
                if (format == DefaultFormat)
                    response.ContentType = texture.Metadata.ContentType;
                else
                    response.ContentType = "image/" + format;
                response.Body.Write(texture.Data, 0, texture.Data.Length);
            }

//            if (response.StatusCode < 200 || response.StatusCode > 299)
//                m_log.WarnFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
//            else
//                m_log.DebugFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
        }
Пример #18
0
        private void WriteTextureData(IOSHttpRequest request, IOSHttpResponse response, AssetBase texture, string format)
        {
            string range = request.Headers.GetOne("Range");

            if (!String.IsNullOrEmpty(range)) // JP2's only
            {
                // Range request
                int start, end;
                if (TryParseRange(range, out start, out end))
                {
                    // Before clamping start make sure we can satisfy it in order to avoid
                    // sending back the last byte instead of an error status
                    if (start >= texture.Data.Length)
                    {
                        response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
                    }
                    else
                    {
                        end   = Utils.Clamp(end, 0, texture.Data.Length - 1);
                        start = Utils.Clamp(start, 0, end);
                        int len = end - start + 1;

                        //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);

                        // Always return PartialContent, even if the range covered the entire data length
                        // We were accidentally sending back 404 before in this situation
                        // https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
                        // entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
                        response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;

                        response.ContentLength = len;
                        response.ContentType   = texture.Metadata.ContentType;
                        response.AddHeader("Content-Range", String.Format("bytes {0}-{1}/{2}", start, end, texture.Data.Length));

                        response.Body.Write(texture.Data, start, len);
                    }
                }
                else
                {
                    m_log.Warn("[GETTEXTURE]: Malformed Range header: " + range);
                    response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                }
            }
            else // JP2's or other formats
            {
                // Full content request
                response.StatusCode    = (int)System.Net.HttpStatusCode.OK;
                response.ContentLength = texture.Data.Length;
                if (format == DefaultFormat)
                {
                    response.ContentType = texture.Metadata.ContentType;
                }
                else
                {
                    response.ContentType = "image/" + format;
                }
                response.Body.Write(texture.Data, 0, texture.Data.Length);
            }

//            if (response.StatusCode < 200 || response.StatusCode > 299)
//                m_log.WarnFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
//            else
//                m_log.DebugFormat(
//                    "[GETTEXTURE]: For texture {0} requested range {1} responded {2} with content length {3} (actual {4})",
//                    texture.FullID, range, response.StatusCode, response.ContentLength, texture.Data.Length);
        }
        protected override byte[] ProcessRequest(string path, Stream request,
                IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            byte[] result = new byte[0];

            string[] p = SplitParams(path);

            if (p.Length == 0)
                return result;

            string id = string.Empty;
            if (p.Length > 1)
            {
                id = p[0];
                string cmd = p[1];

                if (cmd == "data")
                {
                    result = m_AssetService.GetData(id);
                    if (result == null)
                    {
                        httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                        httpResponse.ContentType = "text/plain";
                        result = new byte[0];
                    }
                    else
                    {
                        httpResponse.StatusCode = (int)HttpStatusCode.OK;
                        httpResponse.ContentType = "application/octet-stream";
                    }
                }
                else if (cmd == "metadata")
                {
                    AssetMetadata metadata = m_AssetService.GetMetadata(id);

                    if (metadata != null)
                    {
                        XmlSerializer xs =
                                new XmlSerializer(typeof(AssetMetadata));
                        result = ServerUtils.SerializeResult(xs, metadata);

                        httpResponse.StatusCode = (int)HttpStatusCode.OK;
                        httpResponse.ContentType =
                                SLUtil.SLAssetTypeToContentType(metadata.Type);
                    }
                    else
                    {
                        httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                        httpResponse.ContentType = "text/plain";
                        result = new byte[0];
                    }
                }
                else
                {
                    // Unknown request
                    httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
                    httpResponse.ContentType = "text/plain";
                    result = new byte[0];
                }
            }
            else if (p.Length == 1)
            {
                // Get the entire asset (metadata + data)

                id = p[0];
                AssetBase asset = m_AssetService.Get(id);

                if (asset != null)
                {
                    XmlSerializer xs = new XmlSerializer(typeof(AssetBase));
                    result = ServerUtils.SerializeResult(xs, asset);

                    httpResponse.StatusCode = (int)HttpStatusCode.OK;
                    httpResponse.ContentType =
                            SLUtil.SLAssetTypeToContentType(asset.Type);
                }
                else
                {
                    httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                    httpResponse.ContentType = "text/plain";
                    result = new byte[0];
                }
            }
            else
            {
                // Unknown request
                httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
                httpResponse.ContentType = "text/plain";
                result = new byte[0];
            }
            
            if (httpResponse.StatusCode == (int)HttpStatusCode.NotFound && !string.IsNullOrEmpty(m_RedirectURL) && !string.IsNullOrEmpty(id))
            {
                httpResponse.StatusCode = (int)HttpStatusCode.Redirect;
                string rurl = m_RedirectURL;
                if (!path.StartsWith("/"))
                    rurl += "/";
                rurl += path;
                httpResponse.AddHeader("Location", rurl);
            }
            return result;
        }
        /// <summary>
        /// Returns information about a mumble server via a REST Request
        /// </summary>
        /// <param name="request"></param>
        /// <param name="path"></param>
        /// <param name="param">A string representing the sim's UUID</param>
        /// <param name="httpRequest">HTTP request header object</param>
        /// <param name="httpResponse">HTTP response header object</param>
        /// <returns>Information about the mumble server in http response headers</returns>
        public string RestGetMumbleServerInfo(Scene scene, string request, string path, string param,
                                       IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
        {
            if (m_murmurd_host == null)
            {
                httpResponse.StatusCode = 404;
                httpResponse.StatusDescription = "Not Found";

                string message = "[MurmurVoice]: Server info request from " + httpRequest.RemoteIPEndPoint.Address + ". Cannot send response, module is not configured properly.";
                m_log.Warn(message);
                return "Mumble server info is not available.";
            }

            if (httpRequest.Headers.GetValues("avatar_uuid") == null)
            {
                httpResponse.StatusCode = 400;
                httpResponse.StatusDescription = "Bad Request";

                string message = "[MurmurVoice]: Invalid server info request from " + httpRequest.RemoteIPEndPoint.Address + "";
                m_log.Warn(message);
                return "avatar_uuid header is missing";
            }
                
            string avatar_uuid = httpRequest.Headers.GetValues("avatar_uuid")[0];
            string responseBody = String.Empty;
            UUID avatarId;
            if (UUID.TryParse(avatar_uuid, out avatarId))
            {
                if (scene == null) throw new Exception("[MurmurVoice] Invalid scene.");

                ServerManager manager = GetServerManager(scene);
                Agent agent = manager.Agent.GetOrCreate(avatarId, scene);

                string channel_uri;

                ScenePresence avatar = scene.GetScenePresence(avatarId);
                
                // get channel_uri: check first whether estate
                // settings allow voice, then whether parcel allows
                // voice, if all do retrieve or obtain the parcel
                // voice channel
                LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
                if (null == land) 
                    throw new Exception(String.Format("region \"{0}\": avatar \"{1}\": land data not yet available",
                                                      scene.RegionInfo.RegionName, avatar.Name));

                m_log.DebugFormat("[MurmurVoice] region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
                                  scene.RegionInfo.RegionName, land.Name, land.LocalID, avatar.Name, request, path, param);

                if (((land.Flags & (uint)ParcelFlags.AllowVoiceChat) > 0) && scene.RegionInfo.EstateSettings.AllowVoice)
                {
                    agent.channel = manager.Channel.GetOrCreate(ChannelName(scene, land));

                    // Host/port pair for voice server
                    channel_uri = String.Format("{0}:{1}", m_murmurd_host, m_murmurd_port);

                    if (agent.session > 0)
                    {
                        Murmur.User state = manager.Server.getState(agent.session);
                        GetServerCallback(scene).AddUserToChan(state, agent.channel);
                    }

                    m_log.InfoFormat("[MurmurVoice] channel_uri {0}", channel_uri);
                }
                else
                {
                    m_log.DebugFormat("[MurmurVoice] Voice not enabled.");
                    channel_uri = "";
                }
                string m_context = "Mumble voice system";

                httpResponse.AddHeader("Mumble-Server", m_murmurd_host);
                httpResponse.AddHeader("Mumble-Version", m_server_version);
                httpResponse.AddHeader("Mumble-Channel", channel_uri);
                httpResponse.AddHeader("Mumble-User", avatar_uuid);
                httpResponse.AddHeader("Mumble-Password", agent.pass);
                httpResponse.AddHeader("Mumble-Avatar-Id", avatar_uuid);
                httpResponse.AddHeader("Mumble-Context-Id", m_context);

                responseBody += "Mumble-Server: " + m_murmurd_host + "\n";
                responseBody += "Mumble-Version: " + m_server_version + "\n";
                responseBody += "Mumble-Channel: " + channel_uri + "\n";
                responseBody += "Mumble-User: "******"\n";
                responseBody += "Mumble-Password: "******"\n";
                responseBody += "Mumble-Avatar-Id: " + avatar_uuid + "\n";
                responseBody += "Mumble-Context-Id: " + m_context + "\n";

                string log_message = "[MurmurVoice]: Server info request handled for " + httpRequest.RemoteIPEndPoint.Address + "";
                m_log.Info(log_message);
            }
            else
            {
                httpResponse.StatusCode = 400;
                httpResponse.StatusDescription = "Bad Request";

                m_log.Warn("[MurmurVoice]: Could not parse avatar uuid from request");
                return "could not parse avatar_uuid header";
            }

            return responseBody;
        }