Beispiel #1
0
        public static bool ValidateHttpHeaders(HttpPacket packet)
        {
            if (!packet.Headers.ContainsKey(CONTENTTYPE))
            {
                throw new HttpProtocolException("Mandatory Content-Type header not found.");
            }

            string contentTypeHeader = packet.Headers[CONTENTTYPE];

            string[] contentTypeDefinitions = contentTypeHeader.Split(';');
            if (contentTypeDefinitions.Length == 0)
            {
                throw new HttpProtocolException("Content-Type not defined");
            }
            else
            {
                string contentType = contentTypeDefinitions[0];
                // todo: remove this?
                if (StringComparer.InvariantCultureIgnoreCase.Compare(contentType, APPLICATIONSOAPXML) != 0)
                {
                    //throw new HttpProtocolException(string.Format("Content-Type mismatch; expected: application/soap+xml, actual: {0}", contentType));
                }
                packet.ContentType = contentType;
                for (int i = 1; i < contentTypeDefinitions.Length; i++)
                {
                    string[] parameters = contentTypeDefinitions[i].Trim().Split('=');
                    if (parameters.Length > 1)
                    {
                        if (StringComparer.InvariantCultureIgnoreCase.Compare(parameters[0], "charset") == 0)
                        {
                            packet.Encoding = parameters[1].Trim();

                            if (StringComparer.InvariantCultureIgnoreCase.Compare(packet.Encoding, UTF8) != 0)
                            {
                                throw new HttpProtocolException(string.Format("Charset mismatch. Expected: utf-8, actual: {0}", packet.Encoding));
                            }
                        }
                    }
                }
            }

            return(true);
        }
Beispiel #2
0
        public static bool ContinueReading(MemoryStream responseStream, out HttpPacket header)
        {
            System.Diagnostics.Debug.WriteLine("check if we still have to wait for message.");
            MemoryStream streamCopy = new MemoryStream(responseStream.GetBuffer());
            StreamReader rdr        = new StreamReader(streamCopy);

            header = new HttpPacket();

            int contentLength = 0;
            int bodyOffset    = 0;

            bool bFound = false;
            bool bFirst = true;

            bool noBodySupposed = false;

            while (!rdr.EndOfStream)
            {
                string nextLine = rdr.ReadLine();

                System.Diagnostics.Debug.WriteLine(nextLine);

                bodyOffset += (2 + nextLine.Length);

                if (nextLine == null)
                {
                    System.Diagnostics.Debug.WriteLine("NULL instead of line");
                    break;
                }

                if (bFirst)
                {
                    // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

                    string[] statusParts = nextLine.Split(' ');

                    if (statusParts.Length > 2)
                    {
                        string code = statusParts[1].Trim();
                        header.HttpVersion       = statusParts[0];
                        header.StatusCode        = int.Parse(code);
                        header.StatusDescription = statusParts[2];

                        if (code == "204" || code == "304" || code.StartsWith("1"))
                        {
                            System.Diagnostics.Debug.WriteLine("No body supposed");
                            noBodySupposed = true;
                        }
                    }
                    else
                    {
                        throw new HttpProtocolException(string.Format("The first line of a Response message is incorrect: {0}", nextLine));
                    }
                    bFirst = false;
                }
                else
                {
                    // header:        header-field   = field-name ":" OWS [ field-value ] OWS
                    // field-name     = token
                    // field-value    = *( field-content / OWS )
                    // field-content  = *( WSP / VCHAR / obs-text )

                    int colonPos = nextLine.IndexOf(':');

                    if (colonPos > 0)
                    {
                        string headerName  = nextLine.Substring(0, colonPos).Trim();
                        string headerValue = nextLine.Substring(colonPos + 1).Trim();

                        header.Headers.Add(headerName, headerValue);

                        if (StringComparer.InvariantCultureIgnoreCase.Compare(headerName, CONTENTLENGTH) == 0)
                        {
                            System.Diagnostics.Debug.WriteLine(string.Format("Content-Length found: {0}", headerValue));

                            if (!int.TryParse(headerValue, out contentLength))
                            {
                                throw new HttpProtocolException(string.Format("Content-Length incorrect: {0}, integer expected", headerValue));
                            }

                            header.ContentLength = contentLength;
                        }
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(nextLine))
                        {
                            System.Diagnostics.Debug.WriteLine("Empty line - end of headers");
                            bFound = true;
                            break;
                        }
                        else
                        {
                            throw new HttpProtocolException(string.Format("Unexpected header format: {0}", nextLine));
                        }
                    }
                }
            }

            header.BodyOffset = bodyOffset;

            // empty line found - body can be checked
            if (bFound)
            {
                // message must not have a body;
                if (noBodySupposed)
                {
                    System.Diagnostics.Debug.WriteLine("Stop read");
                    return(false);
                }
                else
                {
                    if (contentLength <= responseStream.Length - bodyOffset)
                    {
                        System.Diagnostics.Debug.WriteLine("Content length OK - stop read");
                        return(false);
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine("Content length NOT OK, continue reading");
                    }
                }
            }
            return(true);
        }
Beispiel #3
0
        public Message Request(Message message, TimeSpan timeout)
        {
            Message message3 = null;

            // check input parameters
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (timeout < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException("timeout");
            }

            // check if underling stream has not been closed by the server
            _networkStream.EnsureOpen();

            base.ThrowIfDisposedOrNotOpen();

            // clear headers
            message.Headers.Clear();

            // send message
            WriteMessageToStream(message);

            // Start reading
            // Wait first byte for timeout.TotalMilliseconds
            int readTimeout = (int)timeout.TotalMilliseconds;

            // initialize variables
            MemoryStream responseStream = new MemoryStream();
            int          bytes          = 0;

            byte[]     responseBuffer = new byte[2048];
            bool       bContinue      = false;
            HttpPacket header         = null;

            // read response
            do
            {
                IAsyncResult result = _networkStream.BeginRead(responseBuffer, 0, responseBuffer.Length);

                // wait for bytes receied, stop event or timeout
                WaitHandle[] handles;
                if (_executionController != null && _executionController.StopEvent != null)
                {
                    handles = new WaitHandle[] { result.AsyncWaitHandle, _executionController.StopEvent };
                }
                else
                {
                    handles = new WaitHandle[] { result.AsyncWaitHandle };
                }
                int handle = System.Threading.WaitHandle.WaitAny(handles, readTimeout);

                if (handle == WaitHandle.WaitTimeout)
                {
                    _networkStream.Close(true);
                    throw new IOException("The HTTP request has exceeded the allotted timeout");
                }
                if (handle == 1)
                {
                    System.Diagnostics.Debug.WriteLine("Stop event");
                    throw new StopEventException("Stop waiting for the answer");
                }

                bytes = _networkStream.EndRead(result);

                responseStream.Write(responseBuffer, 0, bytes);

                // timeout for next part of answer
                readTimeout = READTIMEOUT;

                // parse response received by this moment.
                try
                {
                    bContinue = HttpHelper.ContinueReading(responseStream, out header);
                }
                catch (Exception exc)
                {
                    // clean resources somehow ?
                    throw new Exception("An error occurred while parsing HTTP packet", exc);
                }
            }while (_networkStream.DataAvailable || bContinue);

            int count = (int)responseStream.Length - header.BodyOffset;

            if (header.ContentLength < count)
            {
                throw new HttpProtocolException(
                          string.Format("An error occurred while receiving packet. Expected length: {0}, received: {1}",
                                        header.ContentLength, count));
            }

            // validate headers
            HttpHelper.ValidateHttpHeaders(header);

            // check if connection is to be closed
            if (header.Headers.ContainsKey("Connection"))
            {
                string connState = header.Headers["Connection"];
                if (connState.ToLower() == "close")
                {
                    _networkStream.Close(true);
                }
            }

            // parse response
            string response = Encoding.UTF8.GetString(responseStream.GetBuffer());

            foreach (ITrafficListener listener in _listeners)
            {
                listener.LogResponse(response);
            }

            int start = header.BodyOffset;

            if (start >= 0)
            {
                byte[] buffer = bufferManager.TakeBuffer(count);
                Array.Copy(responseStream.GetBuffer(), start, buffer, 0, count);

                message3 = _encoder.ReadMessage(new ArraySegment <byte>(buffer, 0, count), bufferManager);

                bufferManager.ReturnBuffer(buffer);

                if (message3.IsFault)
                {
                    Console.WriteLine("FAULT");
                    ThrowFaultException(message3);
                }
            }
            else
            {
                throw new ProtocolException(string.Format("The server returned unexpected reply: {0} {1}", header.StatusCode, header.StatusDescription));
            }
            return(message3);
        }