Пример #1
0
        private static int findFirst(IDataStream stream, string needle, int offset)
        {
            if (needle.Length == 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            int endIndex = -1;

            while (offset < stream.Length)
            {
                var len2 = (int)Math.Min(stream.Length - offset, 512);
                var buff = stream.ReadBytes(offset, len2);
                var str  = ASCIIEncoding.ASCII.GetString(buff);
                // find end
                endIndex = (int)str.IndexOf(needle);
                if (endIndex > -1)
                {
                    offset += endIndex + needle.Length;
                    return(offset);
                }
                offset += len2;
            }
            if (endIndex < 0)
            {
                throw new PartialChunkException();
            }
            return(-1);
        }
Пример #2
0
 /// <inheritdoc/>
 public void Send(IDataStream response)
 {
     try
     {
         // TODO: improve this
         socket.SendTo(response.ReadBytes(), remoteEP);
         OnResponseSent(response);
     }
     catch (ObjectDisposedException)
     { }
     catch (Exception e)
     {
         OnErrorOccured(e);
     }
 }
Пример #3
0
        /// <inheritdoc/>
        public void Send(IDataStream request)
        {
            try
            {
                // TODO: improve this
                socket.SendTo(request.ReadBytes(), remoteEP);
            }
            catch (ObjectDisposedException)
            {
                return;
            }
            catch (Exception e)
            {
                OnErrorOccured(e);
                return;
            }

            OnRequestSent(request);
        }
Пример #4
0
 public static void Send(Socket socket, IDataStream stream)
 {
     if (stream.Length < socket.SendBufferSize)
     {
         socket.Send(stream.ReadBytes());
     }
     else
     {
         var  buffer    = new byte[socket.SendBufferSize];
         var  remaining = stream.Length;
         long start     = 0;
         while (remaining > 0)
         {
             var read = (int)Math.Min(remaining, buffer.Length);
             stream.ReadBytesToBuffer(buffer, start, read);
             start     += read;
             remaining -= read;
             socket.Send(buffer, read, SocketFlags.None);
         }
     }
 }
Пример #5
0
 /// <summary>
 /// Creates new ByteArray from a copy of the given stream
 /// </summary>
 /// <param name="stream"></param>
 /// <param name="start"></param>
 /// <param name="length">length to copy, or -1 to copy from start to the end</param>
 public ByteArray(IDataStream stream, long start = 0, int length = -1)
 {
     if (length == -1) length = (int)Math.Min(int.MaxValue, stream.Length - start);
     // ReadBytes copies data, so no extra copying is required
     arr = stream.ReadBytes(start, length);
 }
Пример #6
0
 public void SetValue(IDataStream s)
 {
     // can't really improve this, because the data has to be in memory in order to manipulate them
     // effectively
     data.ByteProvider = new Be.Windows.Forms.DynamicByteProvider(s.ReadBytes());
 }
Пример #7
0
        /// <summary>
        /// Parses response/request header
        /// </summary>
        /// <param name="s">data to parse, must be long enough to contain at least the start line</param>
        /// <param name="isResponse"></param>
        /// <returns>is header parsing finished</returns>
        /// <exception cref="InvalidHttpHeaderException">Thrown when parsing is unsuccessful</exception>
        /// <remarks>Max headers size is limited by 512KiB</remarks>
        public bool Parse(IDataStream s, bool isResponse)
        {
            lock (builder)
            {
                if (stage == ParsingStage.Finished)
                {
                    return(true);
                }
                if (s.Length <= nextRead)
                {
                    return(false);
                }

                byte[] arr;
                // max 512KiB
                int len = (int)Math.Min(s.Length - nextRead, 524288);
                arr = s.ReadBytes(nextRead, len);
                var str = ASCIIEncoding.ASCII.GetString(arr);
                if (stage == ParsingStage.StatusLine)
                {
                    if (isResponse)
                    {
                        var match = statusLineRegex.Match(str);
                        if (!match.Success && str.Length < s.Length)
                        {
                            throw new InvalidHttpHeaderException();
                        }

                        builder.IsRequest    = false;
                        builder.HttpVersion  = match.Groups["Version"].Value;
                        builder.StatusCode   = int.Parse(match.Groups["Code"].Value);
                        builder.ReasonPhrase = match.Groups["ReasonPhrase"].Value;
                        nextRead             = match.Length;
                        stage = ParsingStage.Headers;
                        str   = str.Substring(nextRead);
                    }
                    else
                    {
                        var match = requestLineRegex.Match(str);
                        if (!match.Success && str.Length < s.Length)
                        {
                            throw new InvalidHttpHeaderException();
                        }

                        var target = match.Groups["Target"].Value;
                        HttpRequestMethod method;
                        if (!Enum.TryParse(match.Groups["Method"].Value, out method))
                        {
                            throw new InvalidHttpHeaderException();
                        }
                        builder.IsRequest     = true;
                        builder.HttpVersion   = match.Groups["Version"].Value;
                        builder.Method        = method;
                        builder.RequestTarget = target;
                        nextRead = match.Length;
                        stage    = ParsingStage.Headers;
                        str      = str.Substring(nextRead);
                    }
                }
                if (stage == ParsingStage.Headers)
                {
                    int   read = 0;
                    Match match;
                    while ((match = headerRegex.Match(str, read)).Success)
                    {
                        // Check for end of the string
                        if (str.Length - (match.Length + read) < 2)
                        {
                            nextRead += read;
                            return(false);
                        }
                        var key   = match.Groups["Key"].Value;
                        var value = match.Groups["Value"].Value;
                        builder.AddHeader(key, value);
                        read += match.Length;
                        if (str.Substring(read, 2) != "\r\n")
                        {
                            throw new InvalidHttpHeaderException();
                        }
                        read += 2;
                    }
                    if (str.Length > 0 && read == 0)
                    {
                        throw new InvalidHttpHeaderException();
                    }
                    str       = str.Substring(read);
                    nextRead += read;
                }
                if (stage != ParsingStage.Finished && str.Length >= 2 && str.Substring(0, 2) == "\r\n")
                {
                    stage     = ParsingStage.Finished;
                    nextRead += 2;
                    return(true);
                }
                return(false);
            }
        }
Пример #8
0
        /// <summary>
        /// Decodes one chunk from stream (chunk must begin at the beggining of the stream)
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">stream is null</exception>
        /// <exception cref="InvalidChunkException">chunk is invalid</exception>
        /// <exception cref="PartialChunkException">not enough data in the stream to decode the whole chunk</exception>
        /// <remarks>
        /// Last chunk info's ChunkLength doesn't include trailer and final CRLF.
        /// </remarks>
        public static DecodeOneInfo DecodeOneChunk(IDataStream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException();
            }

            var len   = (int)Math.Min(stream.Length, 10);
            var buff  = stream.ReadBytes(0, len);
            var str   = ASCIIEncoding.ASCII.GetString(buff);
            var match = chunkHeaderRegex.Match(str);

            if (match.Success)
            {
                try
                {
                    if (!match.Groups["ChunkExt"].Success && !match.Groups["HeaderEnd"].Success)
                    {
                        if (len == stream.Length)
                        {
                            throw new PartialChunkException();
                        }
                        // chunk size too large
                        else
                        {
                            throw new InvalidChunkException();
                        }
                    }
                    // parse next chunk size
                    var size = Convert.ToInt32(match.Groups["Size"].Value, 16);
                    if (size < 0)
                    {
                        throw new InvalidChunkException();
                    }
                    // locate \r\n terminating the chunk header
                    if (match.Groups["HeaderEnd"].Success)
                    {
                        len = match.Length;
                    }
                    else
                    {
                        // \r can already be matched
                        len = findFirst(stream, "\r\n", Math.Max(0, len - 1));
                    }
                    // len points to the beggining of chunk data
                    long dataStart = len;
                    // last chunk
                    if (size == 0)
                    {
                        return(new DecodeOneInfo(dataStart, 0, len));
                    }
                    // size > 0
                    // not enough data
                    if (stream.Length - len < size + 2)
                    {
                        throw new PartialChunkException();
                    }
                    // check that chunk data is ended with CRLF
                    buff = stream.ReadBytes(len + size, 2);
                    if (buff[0] != 13 || buff[1] != 10)
                    {
                        throw new InvalidChunkException();
                    }

                    return(new DecodeOneInfo(len, size, len + size + 2));
                }
                catch (ChunkedDecoderException)
                {
                    throw;
                }
                catch
                {
                    throw new InvalidChunkException();
                }
            }
            else
            {
                // unable to parse chunk size
                throw new InvalidChunkException();
            }
        }
Пример #9
0
 /// <inheritdoc/>
 public void Show(IDataStream s)
 {
     textBox1.Text = UTF8Encoding.UTF8.GetString(s.ReadBytes());
 }