Ejemplo n.º 1
0
        /// <summary>
        /// Handles the HTTP response.
        /// </summary>
        /// <param name="iEvent">Socket event arguments object.</param>
        private void ProcessHttp(SocketAsyncEventArgs iEvent)
        {
            // resize response buffer if not enough
            if ((_RspLength + iEvent.BytesTransferred) < _RspBfr.Length)
            {
                Array.Resize(ref _RspBfr, _RspLength + iEvent.BytesTransferred);
            }
            // append new data to response buffer
            Array.Copy(iEvent.Buffer, 0, _RspBfr, _RspLength, iEvent.BytesTransferred);

            // update new response length
            _RspLength += iEvent.BytesTransferred;
            Int32  aBeg       = 0;
            Int32  aB         = 0;
            Int32  aEnd       = _RspLength;
            String aTemp      = String.Empty;
            Int32  aMsgLength = 0;

            byte[] aCookie = null;
            bool   aClear  = true;

            // process response buffer loop
            while (aBeg < aEnd)
            {                   // skip whitespaces
                while ((Char.IsWhiteSpace((char)_RspBfr[aBeg])) && (aBeg < aEnd))
                {
                    aBeg++;
                }
                // buffer overflow protection
                if (aBeg == aEnd)
                {
                    aClear = false;
                    break;                     // not enough bytes
                }
                // make sure we can read the protocol header
                if (aBeg + HTTP_HDR.Length > aEnd)
                {
                    aClear = false;
                    break;                     // not enough bytes
                }
                // read the protocol header
                aTemp = System.Text.Encoding.ASCII.GetString(_RspBfr, aBeg, HTTP_HDR.Length);
                if (aTemp != HTTP_HDR)
                {                       // EMIT PROTOCOL ERROR
                    SocketErrorEventArgs aSocketError = new SocketErrorEventArgs();
                    aSocketError.Error = "Unknown Procotol";
                    SocketErrorEvent(this, aSocketError);
                    break;
                }
                aB = aBeg;
                // extract Set-Cookie and Content-Length loop
                do
                {                       // scan past next newline
                    while (aB < aEnd && ((char)_RspBfr[aB++]) != '\n')
                    {
                        ;
                    }

                    if (aB + SET_COOKIE.Length < aEnd &&
                        _RspBfr[aB] == 'S' &&
                        _RspBfr[aB + 1] == 'e' &&
                        _RspBfr[aB + 2] == 't' &&
                        _RspBfr[aB + 3] == '-' &&
                        _RspBfr[aB + 4] == 'C' &&
                        _RspBfr[aB + 5] == 'o' &&
                        _RspBfr[aB + 6] == 'o' &&
                        _RspBfr[aB + 7] == 'k' &&
                        _RspBfr[aB + 8] == 'i' &&
                        _RspBfr[aB + 9] == 'e')
                    {                           // scan past the colon (:)
                        while ((aB < aEnd) && (_RspBfr[aB++] != ':'))
                        {
                            ;
                        }

                        if (aB < aEnd)
                        {
                            Int32 aEol = 0;
                            if (_RspBfr[aB] == ' ')
                            {
                                aB++;
                            }

                            for (aEol = aB; (aEol < aEnd) && (_RspBfr[aEol] != '\r') &&
                                 (_RspBfr[aEol] != '\n'); aEol++)
                            {
                                ;
                            }

                            aCookie = new byte[aEol - aB];
                            Array.Copy(_RspBfr, aB, aCookie, 0, aEol - aB);
                        }
                    }
                    else if (aB + CONTENT_LENGTH.Length < aEnd &&
                             _RspBfr[aB] == 'C' &&
                             _RspBfr[aB + 1] == 'o' &&
                             _RspBfr[aB + 2] == 'n' &&
                             _RspBfr[aB + 3] == 't' &&
                             _RspBfr[aB + 4] == 'e' &&
                             _RspBfr[aB + 5] == 'n' &&
                             _RspBfr[aB + 6] == 't' &&
                             _RspBfr[aB + 7] == '-' &&
                             _RspBfr[aB + 8] == 'L' &&
                             _RspBfr[aB + 9] == 'e' &&
                             _RspBfr[aB + 10] == 'g' &&
                             _RspBfr[aB + 11] == 'n' &&
                             _RspBfr[aB + 12] == 't' &&
                             _RspBfr[aB + 13] == 'h')
                    {
                        while ((aB < aEnd) && _RspBfr[aB] < '0' || _RspBfr[aB] > '9')
                        {
                            aB++;
                        }

                        // get the content-length
                        if (aB < aEnd)
                        {
                            Int32 aEol = 0;
                            for (aEol = aB; (aEol < aEnd) && (_RspBfr[aEol] != '\r') &&
                                 (_RspBfr[aEol] != '\n'); aEol++)
                            {
                                ;
                            }
                            aTemp = Encoding.ASCII.GetString(_RspBfr, aB, (aEol - aB));
                            try
                            { aMsgLength = Int32.Parse(aTemp); }
                            catch (FormatException)
                            { Debug.WriteLine("Invalid Content-Length value."); }
                        }
                    }
                    else if (_RspBfr[aB] == '\r')
                    {
                        aB++;
                    }
                }                 // extract Set-Cookie and Content-Length loop
                while (aB < aEnd && (_RspBfr[aB++]) != '\n');

                // partial. save the partial request.
                // aBeg = Beginning of this message
                // aB = Beginning of the body of request
                if (aB + aMsgLength > aEnd)
                {                       // if aBeg has been moved past the beginning of the buffer
                                        // just keep the partial
                    if (aBeg > 0)
                    {                   // create new buffer
                        byte[] aNewBfr = new byte[aEnd - aBeg];
                        Array.Copy(_RspBfr, aBeg, aNewBfr, 0, aNewBfr.Length);
                        _RspBfr = aNewBfr;
                    }
                    aBeg = aB + aMsgLength;
                    // DO NOT CLEAR BUFFER
                    aClear = false;
                    // quit the main loop
                    break;
                }
                else
                {
                    ResponseEventArgs aHtmlResponse = new ResponseEventArgs();
                    aHtmlResponse.ResponseBuffer = new byte[aMsgLength];
                    aHtmlResponse.CookieBuffer   = aCookie;
                    Array.Copy(_RspBfr, aB, aHtmlResponse.ResponseBuffer, 0, aMsgLength);

                    // emit response signal
                    ResponseEvent(this, aHtmlResponse);

                    // move aBeg to end of body
                    aBeg += aMsgLength;
                }
            }
            if (aClear)
            {
                _RspLength = 0;
            }
            // call asynchronous read again
            _RemoteSocket.ReceiveAsync(iEvent);
        }         // end of process response buffer loop
Ejemplo n.º 2
0
        /// <summary>
        /// Handles the XML response.
        /// </summary>
        /// <param name="iEvent">Socket event arguments object.</param>
        private void ProcessXml(SocketAsyncEventArgs iEvent)
        {
            // resize response buffer if not enough
            if ((_RspLength + iEvent.BytesTransferred) < _RspBfr.Length)
            {
                Array.Resize(ref _RspBfr, _RspLength + iEvent.BytesTransferred);
            }
            // append new data to response buffer
            Array.Copy(iEvent.Buffer, 0, _RspBfr, _RspLength, iEvent.BytesTransferred);

            // update new response length
            _RspLength += iEvent.BytesTransferred;
            Int32  aBeg   = 0;
            Int32  aB     = 0;
            Int32  aEnd   = _RspLength;
            String aTemp  = String.Empty;
            bool   aClear = true;

            // process response buffer loop
            while (aBeg < aEnd)
            {                   // skip whitespaces
                while ((Char.IsWhiteSpace((char)_RspBfr[aBeg])) && (aBeg < aEnd))
                {
                    aBeg++;
                }
                // buffer overflow protection
                if (aBeg == aEnd)
                {
                    aClear = false;
                    break;                     // not enough bytes
                }
                // make sure we can read the protocol header
                if (aBeg + XML_HDR.Length > aEnd)
                {
                    aClear = false;
                    break;                     // not enough bytes
                }
                // read the protocol header
                aTemp = System.Text.Encoding.ASCII.GetString(_RspBfr, aBeg, XML_HDR.Length);
                if (aTemp != XML_HDR)
                {                       // EMIT PROTOCOL ERROR
                    SocketErrorEventArgs aSocketError = new SocketErrorEventArgs();
                    aSocketError.Error = "Unknown Protocol";
                    SocketErrorEvent(this, aSocketError);
                    break;
                }
                for (aB = aBeg; aB < aEnd && _RspBfr[aB] > MSG_TERM; aB++)
                {
                    ;
                }

                //  if read past the last character
                if (aB == aEnd)
                {                       // DO NOT CLEAR BUFFER
                    aClear = false;
                    break;
                }
                // partial. save partial request.
                // aBeg - Beginning of next response
                // aB - end of this response
                if (_RspBfr[aB] > MSG_TERM)
                {                       // if aBeg has been moved past the beginning of the buffer
                    if (aBeg > 0)
                    {
                        byte[] aNewBuffer = new byte[aEnd - aBeg];
                        Array.Copy(_RspBfr, aBeg, aNewBuffer, 0, aNewBuffer.Length);
                        _RspBfr = aNewBuffer;
                    }
                    // DO NOT CLEAR BUFFER
                    aClear = false;
                    break;
                }

                // NULL terminate the response
                _RspBfr[aB] = (byte)MSG_NULL;
                ResponseEventArgs aResponse = new ResponseEventArgs();
                aResponse.ResponseBuffer = new byte[aB + 1];
                Array.Copy(_RspBfr, aBeg, aResponse.ResponseBuffer, 0, aB + 1);

                // emit response signal
                ResponseEvent(this, aResponse);

                // move aBeg to
                aBeg = aB + 1;
            }
            if (aClear)
            {
                _RspLength = 0;
            }
            // call asynchronous read again
            _RemoteSocket.ReceiveAsync(iEvent);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Handles the APP response.
        /// </summary>
        /// <param name="iEvent">Async receive arguments object.</param>
        private void ProcessApp(SocketAsyncEventArgs iEvent)
        {
            byte[] aBuffer       = iEvent.Buffer; // buffer reference
            String aTemp         = String.Empty;  // temporary string
            String aErrorMessage = String.Empty;  // error message
            bool   aError        = false;         // error flag
            bool   aEmit         = false;         // emit signal flag

            switch (_AppReadState)
            {
            case AppReadState.ReadingResponseLength:
                // check if length field was read correctly
                // and message delimiter is present
                if (iEvent.BytesTransferred == LENGTH_SIZE &&
                    aBuffer[LENGTH_SIZE - 1] == MSG_DELIM)
                {                               // convert length field to integer
                    aTemp = Encoding.ASCII.GetString(aBuffer, 0, LENGTH_SIZE - 1);
                    try
                    {                                   // get the expected size of response
                        _ResponseSize = Int32.Parse(aTemp);
                    }
                    catch (FormatException)
                    {                                   // error in number conversion
                        aErrorMessage = "Invalid response message size format.";
                        aError        = true;
                    }
                    // response size is valid
                    if (_ResponseSize > 0)
                    {                                   // set state to reading data length
                        _AppReadState = AppReadState.ReadingDataLength;
                    }
                    else
                    {                                   // response size is invalid
                        aErrorMessage = "Invalid response message size.";
                        aError        = true;
                    }
                }
                else
                {                               // protocol error
                    aErrorMessage = "Unable to extract response message size.";
                    aError        = true;
                }
                break;

            case AppReadState.ReadingDataLength:
                // check if length field was read correctly
                if (iEvent.BytesTransferred == LENGTH_SIZE &&
                    aBuffer[LENGTH_SIZE - 1] == MSG_DELIM)
                {                               // convert binary data length field to integer
                    aTemp = Encoding.ASCII.GetString(aBuffer, 0, LENGTH_SIZE - 1);
                    try
                    {                                   // get the expected size of binary data
                        _DataSize = Int32.Parse(aTemp);
                    }
                    catch (FormatException)
                    {                                   // error in number conversion
                        aErrorMessage = "Invalid binary data size format.";
                        aError        = true;
                    }
                    if (_DataSize >= 0)
                    {                                   // check size of response buffer
                        if (_RspBfr.Length <= _ResponseSize)
                        {                               // increase buffer size
                            _RspBfr = new byte[_ResponseSize + 1];
                        }
                        // read the response message (including terminator)
                        _AppReadState = AppReadState.ReadingResponse;
                        iEvent.SetBuffer(_RspBfr, 0, _ResponseSize + 1);
                    }
                    else
                    {                                   // binary data size is invalid
                        aErrorMessage = "Invalid binary data size.";
                        aError        = true;
                    }
                }
                else
                {                               // protocol error
                    aErrorMessage = "Unable to extract binary data size";
                    aError        = true;
                }
                break;

            case AppReadState.ReadingResponse:
                // update the bytes received
                _RspLength += iEvent.BytesTransferred;

                // if read response is complete
                if (_RspLength == _ResponseSize + 1)
                {                               // check if terminator is present
                    if (_RspBfr[_ResponseSize] > MSG_TERM)
                    {                           // allow to continue
                        Debug.WriteLine("Encountered unterminated response in message.");
                    }
                    // put null terminator
                    _RspBfr[_ResponseSize] = (byte)MSG_NULL;

                    // if binary data is expected
                    if (_DataSize > 0)
                    {                                   // if data buffer not present or not enough
                        if (_DataBfr == null || _DataBfr.Length < _DataSize)
                        {
                            _DataBfr = new byte[_DataSize];
                        }
                        // read data
                        _AppReadState = AppReadState.ReadingData;
                        iEvent.SetBuffer(_DataBfr, 0, _DataSize);
                    }
                    else
                    {                                   // read complete, signal response event
                        aEmit = true;
                    }
                }
                else
                {                               // partial response received
                                                // continue reading the remaining bytes
                    iEvent.SetBuffer(_RspLength, _ResponseSize - _RspLength + 1);
                }
                break;

            case AppReadState.ReadingData:
                // update the bytes received
                _DataLength += iEvent.BytesTransferred;

                // if read binary data is complete
                if (_DataLength == _DataSize)
                {                               // read complete, signal response event
                    aEmit = true;
                }
                else
                {                               // partial binary data received
                                                // continue reading the remaining bytes
                    iEvent.SetBuffer(_DataLength, _DataSize - _DataLength);
                }
                break;
            }
            // on emit
            if (aEmit)
            {                   // Get ready to emit response to subscribers
                ResponseEventArgs aResEvtArgs = new ResponseEventArgs();
                aResEvtArgs.ResponseBuffer = new byte[_ResponseSize + 1];
                Array.Copy(_RspBfr, aResEvtArgs.ResponseBuffer, _ResponseSize + 1);

                // if binary data is available
                if (_DataLength > 0)
                {
                    aResEvtArgs.DataBuffer = new byte[_DataSize];
                    Array.Copy(_DataBfr, aResEvtArgs.DataBuffer, _DataSize);
                }
                // Signal response event
                ResponseEvent(this, aResEvtArgs);

                // Reset state variables
                _RspLength    = 0;
                _ResponseSize = 0;
                _DataLength   = 0;
                _DataSize     = 0;
                _AppReadState = AppReadState.ReadingResponseLength;
                iEvent.SetBuffer(_RspBfr, 0, LENGTH_SIZE);
            }
            // on error
            if (aError)
            {                   // Display error message
                Debug.WriteLine(aErrorMessage);

                // Clear socket buffer
                DumpSocketBuffer();

                // Reset read state
                _RspLength    = 0;
                _ResponseSize = 0;
                _DataLength   = 0;
                _DataSize     = 0;
                _AppReadState = AppReadState.ReadingResponseLength;
                iEvent.SetBuffer(_RspBfr, 0, LENGTH_SIZE);
            }
            // trigger next asynchronous read
            _RemoteSocket.ReceiveAsync(iEvent);
        }