예제 #1
0
        //----------------------------------//

        /// <summary>
        /// Start a web site and server with the specified path as the root directory.
        /// </summary>
        public HttpSite(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                Log.Warning("No path specified for site. A path should be set.");
            }

            // persist and clean the path
            Path = Fs.Combine(path);

            // get the configuration for the web site
            ManagerResources.LoadConfig(Fs.Combine(Path, "site.config"), new Act <Configuration>(OnConfiguration));

            // create the authentication dictionary
            Authentication = new Dictionary <string, HttpRequirement>();
            // create the redirects collection
            Redirects = new Dictionary <string, HttpRedirect>();

            // create the cache
            _cache = new Cache <string, WebResource>(Global.Megabyte * 100, r => r.Size);

            _onAccessDenied    = new ActionPop <HttpRequest>();
            _onInvalidResource = new ActionPop <HttpRequest>();

            _defaultSendOptions = new HttpSendOptions {
                ContentType = "text/html"
            };
        }
예제 #2
0
        //----------------------------------//

        /// <summary>
        /// Process the send options into headers for a following send operation.
        /// </summary>
        protected void ProcessOptions(HttpSendOptions options)
        {
            if (options == null)
            {
                SetCompression(_defaultCompression);
                return;
            }

            // was the content type specified? set the content type
            if (options.ContentType != null)
            {
                Headers.SetSingle(HttpResponseHeader.ContentType, options.ContentType);
            }

            // is the data to be cached?
            if (options.CacheTime.HasValue)
            {
                if (options.CacheTime.Value == 0)
                {
                    Headers.SetSingle(HttpResponseHeader.CacheControl, "no-cache, no-store");
                }
                else
                {
                    Headers.SetSingle(HttpResponseHeader.CacheControl, "private, max-age=" + options.CacheTime);
                }
            }

            // assign the status code if different
            if (options.StatusCode != Headers.StatusCode)
            {
                Headers.StatusCode = options.StatusCode;
            }

            SetCompression(options.Compression);
        }
예제 #3
0
        /// <summary>
        /// On the stream being compressed.
        /// </summary>
        protected void StartSendStream(MemoryStream stream, HttpSendOptions options, IAction onSent)
        {
            _lock.Take();

            // process the options
            ProcessOptions(options);

            // send the headers
            SendHeaders((int)stream.Length);

            Log.Info("Sending stream of length '" + (int)stream.Length + "' to client " + this + ".");

            // send the stream
            Socket.Send(stream, (int)stream.Length);

            _lock.Release();

            // is the callback set? yes, run it
            if (onSent != null)
            {
                onSent.Run();
            }

            // dispose of the memory stream
            stream.Dispose();
        }
예제 #4
0
        /// <summary>
        /// Send the specified web resource.
        /// </summary>
        public void Send(WebResource resource, HttpSendOptions options = null, IAction onSent = null)
        {
            Log.Info("Sending web resource " + resource + " bytes to client " + this + ".");

            // get the resource stream then prepare to send the resource stream data
            resource.GetStream(ActionSet.New(SendResource, (Stream)null, (Lock)null, resource, options, onSent));
        }
예제 #5
0
        /// <summary>
        /// Send the file at the specified local path.
        /// </summary>
        public void SendLocal(string path, HttpSendOptions options = null, IAction onSent = null)
        {
            Log.Info("Sending local file '" + path + "' bytes to client " + this + ".");

            // get the extension from the path
            string extension;
            int    extensionIndex = path.LastIndexOf(Chars.Stop);

            if (extensionIndex == -1)
            {
                extension = null;
            }
            else
            {
                extension = path.Substring(extensionIndex);
            }

            if (options == null)
            {
                options = new HttpSendOptions {
                    ContentType = Mime.GetType(extension)
                }
            }
            ;

            // open a file stream to the resource
            var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);

            // start sending the file
            StartSendStream(fileStream, (int)fileStream.Length, options, onSent);
        }
예제 #6
0
        /// <summary>
        /// Send the specified string to the client.
        /// </summary>
        public unsafe void Send(string str, HttpSendOptions options = null, IAction onSent = null)
        {
            Log.Info("Sending string '" + str + "' to client " + this + ".");

            // is the string empty? skip
            if (string.IsNullOrEmpty(str))
            {
                return;
            }

            _lock.Take();

            // process send options
            ProcessOptions(options);

            _onSent = onSent;

            var buffer = BufferCache.Get(str.Length + str.Length);
            int count;

            // get pointers to the string and the send byte buffer
            fixed(char *src = str)
            fixed(byte *dst = &buffer[0])
            {
                // get the bytes that the string represents
                count = _encoder.GetBytes(src, str.Length, dst, buffer.Length, true);
            }

            SendBytes(buffer, 0, count);

            BufferCache.Set(buffer);
        }
예제 #7
0
 /// <summary>
 /// Send only the headers with 0 content length.
 /// </summary>
 public void Send(HttpSendOptions options)
 {
     _lock.Take();
     // process the send options
     ProcessOptions(options);
     SendHeaders(0);
     _lock.Release();
 }
예제 #8
0
        /// <summary>
        /// Send the specified byte collection to the client. This may take a number of buffers to complete
        /// and therefore not be synchronous.
        /// </summary>
        public void Send(byte[] buffer, int offset, int count, HttpSendOptions options = null, IAction onSent = null)
        {
            _lock.Take();

            // process the options
            ProcessOptions(options);

            _onSent = onSent;

            // perform the send
            SendBytes(buffer, offset, count);
        }
예제 #9
0
        /// <summary>
        /// Send the specified element to the client.
        /// </summary>
        public unsafe void Send(Element element, bool buildStyle = true, HttpSendOptions options = null, IAction onSent = null)
        {
            Log.Info("Sending element '" + element + "' to client " + this + ".");

            if (buildStyle)
            {
                // build the style
                var style = element.FindChild("style");
                style.ContentString   = element.BuildCss();
                element.EncodeContent = false;
            }

            // build the element into a string
            string str =
                "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">" +
                element.Build();

            _lock.Take();

            // have the options been specified? yes, process them
            if (options == null || options.ContentType == null)
            {
                Headers[HttpResponseHeader.ContentType] = "text/html; charset=UTF-8";
            }
            ProcessOptions(options);

            _onSent = onSent;

            // resize buffer as required
            var buffer = BufferCache.Get(str.Length + str.Length);

            // get pointers to the string and the send byte buffer
            int count;

            fixed(char *src = str)
            fixed(byte *dst = &buffer[0])
            {
                // get the bytes that the string represents
                count = _encoder.GetBytes(src, str.Length, dst, buffer.Length, true);
            }

            // send the bytes
            SendBytes(buffer, 0, count);

            BufferCache.Set(buffer);
        }
예제 #10
0
        /// <summary>
        /// Start sending the stream. The client is locked until the stream is complete.
        /// </summary>
        protected void StartSendStream(Stream stream, int length, HttpSendOptions options = null, IAction onSent = null)
        {
            // does the buffer need to be compressed?
            if (options != null && options.Compression == DecompressionMethods.None ||
                _defaultCompression == DecompressionMethods.None)
            {
                // no, take the send lock
                _lock.Take();

                // process the options
                ProcessOptions(options);

                // send the header
                SendHeaders(length);

                Log.Info("Sending stream of length '" + length + "' to client " + this + ".");

                // send the stream
                Socket.Send(stream, length);

                _lock.Release();

                // is the callback set? yes, run it
                if (onSent != null)
                {
                    onSent.Run();
                }
            }
            else
            {
                // yes, compress the bytes
                StreamHelper.Compress(new Act <MemoryStream, HttpSendOptions, IAction>(StartSendStream, null, options, onSent),
                                      options == null ? _defaultCompression : options.Compression,
                                      System.IO.Compression.CompressionLevel.Fastest, stream, length, false);
            }
        }
예제 #11
0
        /// <summary>
        /// Begin sending the stream of a web resource and prepare to release the resource lock on completion.
        /// </summary>
        protected void SendResource(Stream stream, Lock resourceLock, WebResource resource, HttpSendOptions options, IAction onSent)
        {
            // was the stream retrieved?
            if (stream == null)
            {
                // no, unlock the resource
                resourceLock.Release();

                // callback
                _client.OnErrorRoll.Run(new Exception("A resource stream '" + resource.FullPath + "' was unable to be resolved."));
                return;
            }

            _lock.Take();

            if (onSent == null)
            {
                _onSent = new ActionSet(resourceLock.Release);
            }
            else
            {
                _onSent = new ActionPair(resourceLock.Release, onSent);
            }

            // set the content type
            ProcessOptions(options);
            if (options == null)
            {
                Headers[HttpResponseHeader.ContentType] = resource.MimeType;
            }

            int length = resource.Size == -1 ? (int)stream.Length : (int)resource.Size;

            // start sending the stream
            StartSendStream(stream, length, resource);
        }
예제 #12
0
 /// <summary>
 /// Send the specified stream, optionally with a byte length. This method is
 /// asynchronous and will close the stream on completion.
 /// </summary>
 public void Send(Stream stream, int length = -1, HttpSendOptions options = null, IAction onSent = null)
 {
     // start sending the stream
     StartSendStream(stream, length == -1 ? (int)(stream.Length - stream.Position) : length, options, onSent);
 }