Example #1
0
        public async Task <Task> SendStream(Stream s)
        {
            header.Add("$response_code", response_code.ToString());
            header.Add("$response_text", response_text);

            await proxy.WriteHeader(header);

            return(await proxy.BodyWriteStream(s));
        }
        /// <summary>
        /// The function responsible for handling each request. This function can be implemented by subclassing
        /// of this class and using override. The function is provided with the request header, request body, and
        /// the response encoder which allows setting of headers and data if any.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="body"></param>
        /// <param name="encoder"></param>
        /// <returns></returns>
        public virtual async Task <Task> HandleRequest(Dictionary <String, String> header, Stream body, IProxyHTTPEncoder encoder)
        {
            var outheader = new Dictionary <String, String>();

            outheader.Add("$response_code", "200");
            outheader.Add("$response_text", "OK");

            await encoder.WriteHeader(outheader);

            MemoryStream ms = new MemoryStream();

            byte[] something = Encoding.UTF8.GetBytes("hello world\n");

            ms.Write(something, 0, something.Length);
            ms.Write(something, 0, something.Length);
            ms.Write(something, 0, something.Length);
            ms.Write(something, 0, something.Length);
            ms.Write(something, 0, something.Length);

            ms.Position = 0;

            //await encoder.BodyWriteSingleChunk("response test body");
            await encoder.BodyWriteStream(ms);

            return(Task.CompletedTask);
        }
Example #3
0
        /// <summary>
        /// Performs higher-level interpretation of application layer data and provides that in a higher level form
        /// for consumption by the upper layers.
        /// </summary>
        /// <param name="header"></param>
        /// <param name="body"></param>
        /// <param name="encoder"></param>
        /// <returns></returns>
        /// <remarks>This implementation needs cleaning on variable names for query string processing.</remarks>
        public override async Task <Task> HandleRequest(Dictionary <String, String> header, Stream body, IProxyHTTPEncoder encoder)
        {
            var outheader = new Dictionary <String, String>();

            // Ensure the URL parameter actually exists instead of crashing.
            if (!header.ContainsKey("$url"))
            {
                outheader.Add("$response_code", "500");
                outheader.Add("$response_text", "ERROR");
                await encoder.WriteHeader(outheader);

                await encoder.BodyWriteSingleChunk("The request did not specify a URL.");

                return(Task.CompletedTask);
            }

            var    url             = header["$url"];
            var    url_absolute    = url;
            var    query_string    = new Dictionary <String, String>();
            String query_as_string = null;

            // Break down any query string into its key and value parts.
            if (url.IndexOf("?") > -1)
            {
                var qsndx = url.IndexOf("?");
                query_as_string = url.Substring(qsndx + 1);
                var qstring_parts = query_as_string.Split('&');

                foreach (var part in qstring_parts)
                {
                    var eqndx = part.IndexOf("=");

                    if (eqndx < 0)
                    {
                        query_string.Add(part, part);
                    }
                    else
                    {
                        query_string.Add(part.Substring(0, eqndx), part.Substring(eqndx + 1));
                    }
                }

                url_absolute = url.Substring(0, qsndx);
            }

            HTTPRequest request;

            switch (header["$method"].ToLower())
            {
            case "get":
                request.method = HTTPRequestMethod.GET;
                break;

            case "post":
                request.method = HTTPRequestMethod.POST;
                break;

            default:
                request.method = HTTPRequestMethod.UNKNOWN;
                break;
            }

            // Package everything up nice. Hide away the messy implementation details.
            request.internal_headers = header;
            request.query            = query_string;
            request.url          = url;
            request.url_absolute = url_absolute;
            request.query_string = query_as_string;

            return(await HandleRequest2(request, body, encoder));
        }
        static public async Task <Task> Action(ServerHandler shandler, HTTPRequest request, Stream body, IProxyHTTPEncoder encoder)
        {
            // This URL route was never implemented with user security. The security ID itself is the security, but that
            // could be revised.
            //var auth = await ReadMessageFromStreamAndAuthenticate(1024 * 16, body);
            //if (!auth.success)
            //{
            //    throw new UnauthorizedException();
            //}

            String download_sid;

            if (request.query_string.Length > 0)
            {
                download_sid = request.query_string;
            }
            else
            {
                //req = JsonConvert.DeserializeObject<HandleDownloadRequest>(auth.payload);
                //download_sid = req.security_id;
                throw new InvalidArgumentException();
            }

            Item item;

            lock (shandler.items)
            {
                if (!shandler.items.ContainsKey(download_sid))
                {
                    throw new InvalidArgumentException();
                }

                item = shandler.items[download_sid];
            }

            var item_data_path = Path.Combine(shandler.data_path, item.node);

            var fd = File.OpenRead(item_data_path);

            ulong offset_start = 0;
            // How can a stream be negative? Could this stream ever be negative? What purpose does it suit?
            ulong offset_size = (ulong)fd.Length;
            ulong total_size  = (ulong)fd.Length;

            String response_code = "200";

            if (request.internal_headers.ContainsKey("range"))
            {
                var range_str = request.internal_headers["range"];

                var eqndx = range_str.IndexOf("=");

                if (eqndx > -1)
                {
                    var range_sub_str   = range_str.Substring(eqndx + 1).Trim();
                    var range_nums_strs = range_sub_str.Split("-");

                    if (range_nums_strs.Length > 1)
                    {
                        offset_start = ulong.Parse(range_nums_strs[0]);

                        if (range_nums_strs[1].Equals(""))
                        {
                            offset_size = (ulong)fd.Length - offset_start;
                        }
                        else
                        {
                            offset_size = ulong.Parse(range_nums_strs[1]) - offset_start + 1;
                        }
                        response_code = "206";
                    }
                }
            }

            checked
            {
                fd.Seek((long)offset_start, SeekOrigin.Begin);
            }

            fd.Seek((long)offset_start, SeekOrigin.Begin);

            String mime_type = null;

            switch (item.datatype)
            {
            case "mp4":
                mime_type = "video/mp4";
                break;

            case "jpg":
                mime_type = "image/jpeg";
                break;
            }

            using (var de_stream = new LimitedStream(fd, offset_size))
            {
                var header = new Dictionary <String, String>();

                header.Add("$response_code", response_code);
                header.Add("$response_text", "Partial Content");
                header.Add("content-disposition",
                           String.Format("inline; filename=\"{0}_{1}_{2}_{3}.{4}\"",
                                         item.datestr,
                                         item.userstr,
                                         item.devicestr,
                                         item.timestr,
                                         item.datatype
                                         )
                           );
                header.Add("accept-ranges", "bytes");
                header.Add("content-range",
                           String.Format("bytes {0}-{1}/{2}",
                                         offset_start,
                                         offset_size + offset_start - 1,
                                         total_size
                                         )
                           );

                if (mime_type != null)
                {
                    header.Add("content-type", mime_type);
                }

                await encoder.WriteHeader(header);

                await encoder.BodyWriteStream(de_stream);

                return(Task.CompletedTask);
            }
        }