コード例 #1
0
ファイル: StreamSocket.cs プロジェクト: menghuan341/ice
        private int Write(ByteBuffer buf)
        {
            Debug.Assert(_fd != null);
            if (AssemblyUtil.IsMono)
            {
                //
                // Mono on Android and iOS don't support the use of synchronous socket
                // operations on a non-blocking socket. Returning 0 here forces the caller to schedule
                // an asynchronous operation.
                //
                return(0);
            }
            int packetSize = buf.Remaining();

            if (AssemblyUtil.IsWindows)
            {
                //
                // On Windows, limiting the buffer size is important to prevent
                // poor throughput performances when transfering large amount of
                // data. See Microsoft KB article KB823764.
                //
                if (_maxSendPacketSize > 0 && packetSize > _maxSendPacketSize / 2)
                {
                    packetSize = _maxSendPacketSize / 2;
                }
            }

            int sent = 0;

            while (buf.HasRemaining())
            {
                try
                {
                    int ret = _fd.Send(buf.RawBytes(), buf.Position(), packetSize, SocketFlags.None);
                    Debug.Assert(ret > 0);

                    sent += ret;
                    buf.Position(buf.Position() + ret);
                    if (packetSize > buf.Remaining())
                    {
                        packetSize = buf.Remaining();
                    }
                }
                catch (SocketException ex)
                {
                    if (Network.WouldBlock(ex))
                    {
                        return(sent);
                    }
                    else if (Network.ConnectionLost(ex))
                    {
                        throw new Ice.ConnectionLostException(ex);
                    }
                    throw new Ice.SocketException(ex);
                }
            }
            return(sent);
        }
コード例 #2
0
ファイル: StreamSocket.cs プロジェクト: menghuan341/ice
        private int Read(ByteBuffer buf)
        {
            Debug.Assert(_fd != null);
            if (AssemblyUtil.IsMono)
            {
                //
                // Mono on Android and iOS don't support the use of synchronous socket
                // operations on a non-blocking socket. Returning 0 here forces the caller to schedule
                // an asynchronous operation.
                //
                return(0);
            }
            int read = 0;

            while (buf.HasRemaining())
            {
                try
                {
                    int ret = _fd.Receive(buf.RawBytes(), buf.Position(), buf.Remaining(), SocketFlags.None);
                    if (ret == 0)
                    {
                        throw new Ice.ConnectionLostException();
                    }
                    read += ret;
                    buf.Position(buf.Position() + ret);
                }
                catch (SocketException ex)
                {
                    if (Network.WouldBlock(ex))
                    {
                        return(read);
                    }
                    else if (Network.Interrupted(ex))
                    {
                        continue;
                    }
                    else if (Network.ConnectionLost(ex))
                    {
                        throw new Ice.ConnectionLostException(ex);
                    }

                    throw new Ice.SocketException(ex);
                }
            }
            return(read);
        }
コード例 #3
0
ファイル: HttpParser.cs プロジェクト: yzun/ice
        internal int IsCompleteMessage(ByteBuffer buf, int begin, int end)
        {
            byte[] raw = buf.RawBytes();
            int    p   = begin;

            //
            // Skip any leading CR-LF characters.
            //
            while (p < end)
            {
                byte ch = raw[p];
                if (ch != (byte)'\r' && ch != (byte)'\n')
                {
                    break;
                }
                ++p;
            }

            //
            // Look for adjacent CR-LF/CR-LF or LF/LF.
            //
            bool seenFirst = false;

            while (p < end)
            {
                byte ch = raw[p++];
                if (ch == (byte)'\n')
                {
                    if (seenFirst)
                    {
                        return(p);
                    }
                    else
                    {
                        seenFirst = true;
                    }
                }
                else if (ch != (byte)'\r')
                {
                    seenFirst = false;
                }
            }

            return(-1);
        }
コード例 #4
0
ファイル: HttpParser.cs プロジェクト: yzun/ice
        internal bool Parse(ByteBuffer buf, int begin, int end)
        {
            byte[]     raw   = buf.RawBytes();
            int        p     = begin;
            int        start = 0;
            const char CR    = '\r';
            const char LF    = '\n';

            if (_state == State.Complete)
            {
                _state = State.Init;
            }

            while (p != end && _state != State.Complete)
            {
                char c = (char)raw[p];

                switch (_state)
                {
                case State.Init:
                {
                    _method       = new StringBuilder();
                    _uri          = new StringBuilder();
                    _versionMajor = -1;
                    _versionMinor = -1;
                    _status       = -1;
                    _reason       = "";
                    _headers.Clear();
                    _state = State.Type;
                    continue;
                }

                case State.Type:
                {
                    if (c == CR || c == LF)
                    {
                        break;
                    }
                    else if (c == 'H')
                    {
                        //
                        // Could be the start of "HTTP/1.1" or "HEAD".
                        //
                        _state = State.TypeCheck;
                        break;
                    }
                    else
                    {
                        _state = State.Request;
                        continue;
                    }
                }

                case State.TypeCheck:
                {
                    if (c == 'T')         // Continuing "H_T_TP/1.1"
                    {
                        _state = State.Response;
                    }
                    else if (c == 'E')         // Expecting "HEAD"
                    {
                        _state = State.Request;
                        _method.Append('H');
                        _method.Append('E');
                    }
                    else
                    {
                        throw new WebSocketException("malformed request or response");
                    }
                    break;
                }

                case State.Request:
                {
                    _type  = Type.Request;
                    _state = State.RequestMethod;
                    continue;
                }

                case State.RequestMethod:
                {
                    if (c == ' ' || c == CR || c == LF)
                    {
                        _state = State.RequestMethodSP;
                        continue;
                    }
                    _method.Append(c);
                    break;
                }

                case State.RequestMethodSP:
                {
                    if (c == ' ')
                    {
                        break;
                    }
                    else if (c == CR || c == LF)
                    {
                        throw new WebSocketException("malformed request");
                    }
                    _state = State.RequestURI;
                    continue;
                }

                case State.RequestURI:
                {
                    if (c == ' ' || c == CR || c == LF)
                    {
                        _state = State.RequestURISP;
                        continue;
                    }
                    _uri.Append(c);
                    break;
                }

                case State.RequestURISP:
                {
                    if (c == ' ')
                    {
                        break;
                    }
                    else if (c == CR || c == LF)
                    {
                        throw new WebSocketException("malformed request");
                    }
                    _state = State.Version;
                    continue;
                }

                case State.RequestLF:
                {
                    if (c != LF)
                    {
                        throw new WebSocketException("malformed request");
                    }
                    _state = State.HeaderFieldStart;
                    break;
                }

                case State.HeaderFieldStart:
                {
                    //
                    // We've already seen a LF to reach this state.
                    //
                    // Another CR or LF indicates the end of the header fields.
                    //
                    if (c == CR)
                    {
                        _state = State.HeaderFieldEndLF;
                        break;
                    }
                    else if (c == LF)
                    {
                        _state = State.Complete;
                        break;
                    }
                    else if (c == ' ')
                    {
                        //
                        // Could be a continuation line.
                        //
                        _state = State.HeaderFieldContStart;
                        break;
                    }

                    _state = State.HeaderFieldNameStart;
                    continue;
                }

                case State.HeaderFieldContStart:
                {
                    if (c == ' ')
                    {
                        break;
                    }

                    _state = State.HeaderFieldCont;
                    start  = p;
                    continue;
                }

                case State.HeaderFieldCont:
                {
                    if (c == CR || c == LF)
                    {
                        if (p > start)
                        {
                            if (_headerName.Length == 0)
                            {
                                throw new WebSocketException("malformed header");
                            }
                            Debug.Assert(_headers.ContainsKey(_headerName));
                            string s        = _headers[_headerName];
                            var    newValue = new StringBuilder(s);
                            newValue.Append(' ');
                            for (int i = start; i < p; ++i)
                            {
                                newValue.Append((char)raw[i]);
                            }
                            _headers[_headerName] = newValue.ToString();
                            _state = c == CR ? State.HeaderFieldLF : State.HeaderFieldStart;
                        }
                        else
                        {
                            //
                            // Could mark the end of the header fields.
                            //
                            _state = c == CR ? State.HeaderFieldEndLF : State.Complete;
                        }
                    }

                    break;
                }

                case State.HeaderFieldNameStart:
                {
                    Debug.Assert(c != ' ');
                    start       = p;
                    _headerName = "";
                    _state      = State.HeaderFieldName;
                    continue;
                }

                case State.HeaderFieldName:
                {
                    if (c == ' ' || c == ':')
                    {
                        _state = State.HeaderFieldNameEnd;
                        continue;
                    }
                    else if (c == CR || c == LF)
                    {
                        throw new WebSocketException("malformed header");
                    }
                    break;
                }

                case State.HeaderFieldNameEnd:
                {
                    if (_headerName.Length == 0)
                    {
                        var str = new StringBuilder();
                        for (int i = start; i < p; ++i)
                        {
                            str.Append((char)raw[i]);
                        }
                        _headerName = str.ToString().ToLower();
                        //
                        // Add a placeholder entry if necessary.
                        //
                        if (!_headers.ContainsKey(_headerName))
                        {
                            _headers[_headerName]     = "";
                            _headerNames[_headerName] = str.ToString();
                        }
                    }

                    if (c == ' ')
                    {
                        break;
                    }
                    else if (c != ':' || p == start)
                    {
                        throw new WebSocketException("malformed header");
                    }

                    _state = State.HeaderFieldValueStart;
                    break;
                }

                case State.HeaderFieldValueStart:
                {
                    if (c == ' ')
                    {
                        break;
                    }

                    //
                    // Check for "Name:\r\n"
                    //
                    if (c == CR)
                    {
                        _state = State.HeaderFieldLF;
                        break;
                    }
                    else if (c == LF)
                    {
                        _state = State.HeaderFieldStart;
                        break;
                    }

                    start  = p;
                    _state = State.HeaderFieldValue;
                    continue;
                }

                case State.HeaderFieldValue:
                {
                    if (c == CR || c == LF)
                    {
                        _state = State.HeaderFieldValueEnd;
                        continue;
                    }
                    break;
                }

                case State.HeaderFieldValueEnd:
                {
                    Debug.Assert(c == CR || c == LF);
                    if (p > start)
                    {
                        var str = new StringBuilder();
                        for (int i = start; i < p; ++i)
                        {
                            str.Append((char)raw[i]);
                        }

                        if (!_headers.TryGetValue(_headerName, out string s) || s.Length == 0)
                        {
                            _headers[_headerName] = str.ToString();
                        }
                        else
                        {
                            _headers[_headerName] = s + ", " + str.ToString();
                        }
                    }

                    if (c == CR)
                    {
                        _state = State.HeaderFieldLF;
                    }
                    else
                    {
                        _state = State.HeaderFieldStart;
                    }
                    break;
                }

                case State.HeaderFieldLF:
                {
                    if (c != LF)
                    {
                        throw new WebSocketException("malformed header");
                    }
                    _state = State.HeaderFieldStart;
                    break;
                }

                case State.HeaderFieldEndLF:
                {
                    if (c != LF)
                    {
                        throw new WebSocketException("malformed header");
                    }
                    _state = State.Complete;
                    break;
                }

                case State.Version:
                {
                    if (c != 'H')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    _state = State.VersionH;
                    break;
                }

                case State.VersionH:
                {
                    if (c != 'T')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    _state = State.VersionHT;
                    break;
                }

                case State.VersionHT:
                {
                    if (c != 'T')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    _state = State.VersionHTT;
                    break;
                }

                case State.VersionHTT:
                {
                    if (c != 'P')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    _state = State.VersionHTTP;
                    break;
                }

                case State.VersionHTTP:
                {
                    if (c != '/')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    _state = State.VersionMajor;
                    break;
                }

                case State.VersionMajor:
                {
                    if (c == '.')
                    {
                        if (_versionMajor == -1)
                        {
                            throw new WebSocketException("malformed version");
                        }
                        _state = State.VersionMinor;
                        break;
                    }
                    else if (c < '0' || c > '9')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    if (_versionMajor == -1)
                    {
                        _versionMajor = 0;
                    }
                    _versionMajor *= 10;
                    _versionMajor += (int)(c - '0');
                    break;
                }

                case State.VersionMinor:
                {
                    if (c == CR)
                    {
                        if (_versionMinor == -1 || _type != Type.Request)
                        {
                            throw new WebSocketException("malformed version");
                        }
                        _state = State.RequestLF;
                        break;
                    }
                    else if (c == LF)
                    {
                        if (_versionMinor == -1 || _type != Type.Request)
                        {
                            throw new WebSocketException("malformed version");
                        }
                        _state = State.HeaderFieldStart;
                        break;
                    }
                    else if (c == ' ')
                    {
                        if (_versionMinor == -1 || _type != Type.Response)
                        {
                            throw new WebSocketException("malformed version");
                        }
                        _state = State.ResponseVersionSP;
                        break;
                    }
                    else if (c < '0' || c > '9')
                    {
                        throw new WebSocketException("malformed version");
                    }
                    if (_versionMinor == -1)
                    {
                        _versionMinor = 0;
                    }
                    _versionMinor *= 10;
                    _versionMinor += c - '0';
                    break;
                }

                case State.Response:
                {
                    _type  = Type.Response;
                    _state = State.VersionHT;
                    continue;
                }

                case State.ResponseVersionSP:
                {
                    if (c == ' ')
                    {
                        break;
                    }

                    _state = State.ResponseStatus;
                    continue;
                }

                case State.ResponseStatus:
                {
                    // TODO: Is reason string optional?
                    if (c == CR)
                    {
                        if (_status == -1)
                        {
                            throw new WebSocketException("malformed response status");
                        }
                        _state = State.ResponseLF;
                        break;
                    }
                    else if (c == LF)
                    {
                        if (_status == -1)
                        {
                            throw new WebSocketException("malformed response status");
                        }
                        _state = State.HeaderFieldStart;
                        break;
                    }
                    else if (c == ' ')
                    {
                        if (_status == -1)
                        {
                            throw new WebSocketException("malformed response status");
                        }
                        _state = State.ResponseReasonStart;
                        break;
                    }
                    else if (c < '0' || c > '9')
                    {
                        throw new WebSocketException("malformed response status");
                    }
                    if (_status == -1)
                    {
                        _status = 0;
                    }
                    _status *= 10;
                    _status += c - '0';
                    break;
                }

                case State.ResponseReasonStart:
                {
                    //
                    // Skip leading spaces.
                    //
                    if (c == ' ')
                    {
                        break;
                    }

                    _state = State.ResponseReason;
                    start  = p;
                    continue;
                }

                case State.ResponseReason:
                {
                    if (c == CR || c == LF)
                    {
                        if (p > start)
                        {
                            var str = new StringBuilder();
                            for (int i = start; i < p; ++i)
                            {
                                str.Append((char)raw[i]);
                            }
                            _reason = str.ToString();
                        }
                        _state = c == CR ? State.ResponseLF : State.HeaderFieldStart;
                    }

                    break;
                }

                case State.ResponseLF:
                {
                    if (c != LF)
                    {
                        throw new WebSocketException("malformed status line");
                    }
                    _state = State.HeaderFieldStart;
                    break;
                }

                case State.Complete:
                {
                    Debug.Assert(false);         // Shouldn't reach
                    break;
                }
                }

                ++p;
            }

            return(_state == State.Complete);
        }