Ejemplo n.º 1
0
        /// <summary>
        /// Parses 'rangeStr' for HTTP range sets, and adds the sets into
        /// 'rangeSets'... should an overlapping range set be provided
        /// or if an otherwise invalid range is requested, then we clear
        /// the 'rangeSets'... behavior is taken from http://www.freesoft.org/CIE/RFC/2068/178.htm.
        ///
        /// <para>
        /// If the server ignores a byte-range-spec because it is invalid,
        /// the server should treat the request as if the invalid Range header
        /// field did not exist.
        /// (Normally, this means return a 200 response containing the full entity).
        /// The reason is that the only time a client will make such an invalid
        /// request is when the entity is smaller than the entity retrieved by a prior request.
        /// [source: http://www.freesoft.org/CIE/RFC/2068/178.htm]
        /// </para>
        /// </summary>
        /// <param name="rangeSets">this ArrayList has range sets added to it</param>
        /// <param name="rangeStr">
        /// This is the HTTP header with the desired ranges.
        /// Text is assumed to be all lower case and trimmed.
        /// </param>
        /// <param name="contentLength">
        /// The entire length of the content, from byte 0.
        /// </param>
        public static void AddRange(this List <HTTPSession.Range> rangeSets, string rangeStr, long contentLength)
        {
            if (String.IsNullOrEmpty(rangeStr))
            {
                return;
            }

            bool errorEncountered = true;

            errorEncountered = false;
            DText dt = new DText();

            dt.ATTRMARK = "=";
            dt.MULTMARK = ",";
            dt.SUBVMARK = "-";
            dt[0]       = rangeStr;

            int numSets = dt.DCOUNT(2);

            for (int i = 1; i <= numSets; i++)
            {
                string sOffset = dt[2, i, 1].Trim();
                string sEnd = dt[2, i, 2].Trim();
                long   offset = -1, length = -1, end = -1;

                if ((sOffset == "") && (sEnd == ""))
                {
                    // royally screwed up request
                    errorEncountered = true;
                    break;
                }
                else if ((sOffset == "") && (sEnd != ""))
                {
                    // retrieve the last set of bytes identified by sEnd
                    try
                    {
                        offset = 0;
                        end    = long.Parse(sEnd);
                        length = end + 1;
                    }
                    catch
                    {
                        errorEncountered = true;
                        break;
                    }
                }
                else if ((sOffset != "") && (sEnd == ""))
                {
                    // retrieve all bytes starting from sOffset
                    try
                    {
                        offset = long.Parse(sOffset);
                        end    = contentLength - 1;
                        length = contentLength - offset;
                    }
                    catch
                    {
                        errorEncountered = true;
                        break;
                    }
                }
                else
                {
                    // retrieve bytes from sOffset through sEnd,
                    // inclusive so be sure to add 1 to difference
                    try
                    {
                        offset = long.Parse(sOffset);
                        end    = long.Parse(sEnd);

                        if (offset <= end)
                        {
                            length = end - offset + 1;
                        }
                        else
                        {
                            errorEncountered = true;
                        }
                    }
                    catch
                    {
                        errorEncountered = true;
                        break;
                    }
                }

                if (errorEncountered == false)
                {
                    Debug.Assert(offset >= 0);
                    Debug.Assert(length >= 0);
                    Debug.Assert(end >= 0);

                    HTTPSession.Range newRange = new HTTPSession.Range(offset, length);
                    rangeSets.Add(newRange);
                }
            }

            if (errorEncountered)
            {
                // error parsing value, this is invalid so clear and return
                rangeSets.Clear();
            }
        }
Ejemplo n.º 2
0
        private void SendStreamObject(HTTPSession webSession, HTTPMessage msg, string fileName)
        {
            Stream stream = null;

            try
            {
                if (!fileName.Contains("/"))
                {
                    fileName = HttpUtility.UrlDecode(fileName);
                }
                string str       = (fileName[0] == '1' ? fileName.Substring(2, fileName.LastIndexOf('/') - 2) : fileName.Substring(2));
                int    idx       = str.Length;
                string freeboxV5 = GetString(str, ref idx);
                string file      = str.Substring(0, idx);

                string mimeType      = null;
                long   contentLength = -1;
                bool   liveStream    = MimeType.IsLiveStream(file);
                string rangeStr      = (msg == null ? null : msg.GetTag("RANGE"));
                List <HTTPSession.Range> rangeSets = new List <HTTPSession.Range>();
                if (!String.IsNullOrEmpty(rangeStr))
                {
                    rangeStr = rangeStr.Trim().ToLower();
                }

                if (liveStream)
                {
                    Web.CreateWebRequest(rangeSets, rangeStr, file, ref stream, ref contentLength, ref mimeType);
                    if (!String.IsNullOrEmpty(mimeType) && mimeType.ToUpperInvariant() == "AUDIO/X-SCPLS")
                    {
                        file = new PLSPlaylist().GetMediaUrl(Web.GetStringAndCloseStream(stream, Encoding.UTF8));
                        Web.CreateWebRequest(rangeSets, rangeStr, file, ref stream, ref contentLength, ref mimeType);
                    }
                }
                else
                {
                    stream   = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
                    mimeType = MimeType.GetMimeTypeFromFileName(file);
                }

                if (stream == null)
                {
                    SendErrorMessage(webSession, null);
                    return;
                }

                bool canSeek = stream.CanSeek;
                if (canSeek)
                {
                    contentLength = stream.Length;
                }

                PreventSystemStandBy();
                if (msg != null && String.Compare(msg.Directive, "HEAD", true) == 0)
                {
                    HTTPMessage head = new HTTPMessage();
                    head.StatusCode  = 200;
                    head.StatusData  = "OK";
                    head.ContentType = mimeType;
                    if (contentLength >= 0)
                    {
                        head.OverrideContentLength = true;
                        if (String.IsNullOrEmpty(rangeStr))
                        {
                            head.AddTag("Content-Length", contentLength.ToString());
                            head.AddTag("Accept-Ranges", "bytes");
                        }
                        else
                        {
                            head.StatusCode = 206;
                            rangeSets.AddRange(rangeStr.Trim().ToLower(), contentLength);
                            if (rangeSets.Count == 1)
                            {
                                HTTPSession.Range range = rangeSets[0];
                                head.AddTag("Content-Range", "bytes " + range.Position.ToString() + "-" + ((long)(range.Position + range.Length - 1)).ToString() + "/" + contentLength.ToString());
                                head.AddTag("Content-Length", range.Length.ToString());
                            }
                        }
                    }
                    else
                    {
                        // Can't calculate length => can't do range
                        head.AddTag("Accept-Ranges", "none");
                    }

                    webSession.Send(head);
                }
                else
                {
                    if (canSeek && contentLength >= 0 && rangeSets.Count == 0)
                    {
                        rangeSets.AddRange(rangeStr, contentLength);
                    }

                    lock (webSession)
                    {
                        webSession.OnStreamDone += new HTTPSession.StreamDoneHandler(WebSession_OnStreamDone);
                        if (freeboxV5 == "1" && mimeType == "audio/mpeg")
                        {
                            webSession.StateObject = file;
                        }

                        bool image = (MimeType.GetMediaKind(mimeType) == MediaKind.Image);
                        if (freeboxV5 == "1")
                        {
                            if (!image)
                            {
                                webSession.BUFFER_SIZE = Settings.Default.V5BufferSize;
                            }
                        }
                        else
                        {
                            webSession.BUFFER_SIZE = Settings.Default.V6BufferSize;
                        }

                        if (rangeSets.Count > 0)
                        {
                            webSession.SendStreamObject(stream, rangeSets.ToArray(), mimeType);
                        }
                        else
                        {
                            if (canSeek)
                            {
                                stream.Seek(0, SeekOrigin.Begin);
                            }
                            if (contentLength >= 0)
                            {
                                webSession.SendStreamObject(stream, contentLength, mimeType, image);
                            }
                            else
                            {
                                webSession.SendStreamObject(stream, mimeType);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Utils.WriteException(ex);
                SendErrorMessage(webSession, stream);
            }
        }