⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpconnection.cpp

📁 Pegasus is an open-source implementationof the DMTF CIM and WBEM standards. It is designed to be por
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 * sending them. If not, the message must be queued up until a complete flag * has arrived. */Boolean HTTPConnection::_handleWriteEvent(Message &message){    static const char func[] = "HTTPConnection::_handleWriteEvent";    String httpStatus;    HTTPMessage& httpMessage = *(HTTPMessage*)&message;    Buffer& buffer = httpMessage.message;    Boolean isFirst = message.isFirst();    Boolean isLast = message.isComplete();    Sint32 totalBytesWritten = 0;    Uint32 messageLength = buffer.size();    try    {        // delivery behavior:        // 1 handler.processing() : header + optional body?        // 2 handler.deliver()    : 1+ fully XML encoded object(s)        // 3 handler.complete()   : deliver() + isLast = true        Uint32 bytesRemaining = messageLength;        char *messageStart = (char *) buffer.getData();        Uint32 bytesToWrite = httpTcpBufferSize;        Uint32 messageIndex = message.getIndex();        Boolean isChunkResponse = false;        Boolean isChunkRequest = false;        Boolean isFirstException = false;        if (_isClient() == false)        {            // for null termination            buffer.reserveCapacity(messageLength + 1);            messageStart = (char *) buffer.getData();            messageStart[messageLength] = 0;            Tracer::trace(                TRC_XML_IO,                Tracer::LEVEL2, "<!-- Response: queue id: %u -->\n%s",                getQueueId(),                buffer.getData());            if (isFirst == true)            {                _incomingBuffer.clear();                // tracks the message coming from above                _transferEncodingChunkOffset = 0;                _mpostPrefix.clear();                cimException = CIMException();                _responsePending = true;            }            else            {                // this is coming from our own internal code, therefore it is an                // internal error. somehow the chunks came out of order.                if (_transferEncodingChunkOffset+1 != messageIndex)                    _throwEventFailure(                        httpStatusInternal, "chunk sequence mismatch");                _transferEncodingChunkOffset++;            }            // save the first error            if (httpMessage.cimException.getCode() != CIM_ERR_SUCCESS)            {                httpStatus = httpMessage.cimException.getMessage();                if (cimException.getCode() == CIM_ERR_SUCCESS)                {                    cimException = httpMessage.cimException;                    // set language to first error language (overriding                    // anything there)                    contentLanguages = cimException.getContentLanguages();                    isFirstException = true;                }            }            else if (cimException.getCode() == CIM_ERR_SUCCESS)            {                if (isFirst == true)                    contentLanguages = httpMessage.contentLanguages;                else if (httpMessage.contentLanguages != contentLanguages)                    contentLanguages.clear();                else contentLanguages = httpMessage.contentLanguages;            }            // check to see if the client requested chunking OR trailers.            // trailers are tightly integrated with chunking, so it can also            // be used.            if (isChunkRequested() == true)            {                isChunkRequest = true;            }            else            {                // we are not sending chunks because the client did not                // request it                // save the entire FIRST error response for non-chunked error                // responses this will be used as the error message                if (isFirstException == true)                {                    // this shouldnt happen, but this is defensive ...                    if (messageLength == 0)                    {                        CIMStatusCode code = httpMessage.cimException.getCode();                        String httpDetail(cimStatusCodeToString(code));                        char s[21];                        sprintf(s, "%u", code);                        String httpStatus(s);                        Buffer message = XmlWriter::formatHttpErrorRspMessage                            (httpStatus, String(), httpDetail);                        messageLength = message.size();                        message.reserveCapacity(messageLength+1);                        messageStart = (char *) message.getData();                        messageStart[messageLength] = 0;                    }                    cimException = CIMException(cimException.getCode(),                        String(messageStart, messageLength));                }                if (isFirst == false)                {                    // subsequent chunks from the server, just append                    messageLength += _incomingBuffer.size();                    _incomingBuffer.reserveCapacity(messageLength+1);                    _incomingBuffer.append(buffer.getData(), buffer.size());                    buffer.clear();                    // null terminate                    messageStart = (char *) _incomingBuffer.getData();                    messageStart[messageLength] = 0;                    // put back in buffer, so the httpMessage parser can work                    // below                    _incomingBuffer.swap(buffer);                }                if (isLast == false)                {                    // this tells the send loop below to do nothing until we                    // are at the last response                    bytesRemaining = 0;                }                else                {                    if (cimException.getCode() != CIM_ERR_SUCCESS)                    {                        buffer.clear();                        // discard all data collected to this point                        _incomingBuffer.clear();                        String messageS = cimException.getMessage();                        CString messageC = messageS.getCString();                        messageStart = (char *) (const char *) messageC;                        messageLength = strlen(messageStart);                        buffer.reserveCapacity(messageLength+1);                        buffer.append(messageStart, messageLength);                        // null terminate                        messageStart = (char *) buffer.getData();                        messageStart[messageLength] = 0;                    }                    bytesRemaining = messageLength;                }            } // if not sending chunks            // We now need to adjust the contentLength line.            // If chunking was requested and this is the first chunk, then            // we need to enter this block so we can adjust the header and            // send to the client the first set of bytes right away.            // If chunking was NOT requested, we have to wait for the last            // chunk of the message to get (and set) the size of the content            // because we are going to send it the traditional (i.e            // non-chunked) way            if (isChunkRequest == true && isFirst == true ||                    isChunkRequest == false && isLast == true)            {                // need to find the end of the header                String startLine;                Array<HTTPHeader> headers;                Uint32 contentLength = 0;                // Note: this gets the content length from subtracting the                // header length from the messageLength, not by parsing the                // content length header field                httpMessage.parse(startLine, headers, contentLength);                Uint32 httpStatusCode = 0;                String httpVersion;                String reasonPhrase;                Boolean isValid = httpMessage.parseStatusLine(                    startLine, httpVersion, httpStatusCode, reasonPhrase);                Uint32 headerLength = messageLength - contentLength;                char save = messageStart[headerLength];                messageStart[headerLength] = 0;                char *contentLengthStart =                    strstr(messageStart, headerNameContentLength);                char* contentLengthEnd = contentLengthStart ?                    strstr(contentLengthStart, headerLineTerminator) : 0;                messageStart[headerLength] = save;                // the message may or may not have the content length specified                // depending on the type of request it is                if (contentLengthStart)                {                    // the message has the content length specified.                    // If we are NOT sending a chunked response, then we need                    // to overlay the contentLength number to reflect the                    // actual byte count of the content (i.e message body).                    // If we ARE sending a chunked response, then we will                    // overlay the transferEncoding keyword name and value                    // on top of the contentLength keyword and value.                    // Important note:                    // for performance reasons, the contentLength and/or                    // transferEncoding strings are being overlayed                    // DIRECTLY inside the message buffer WITHOUT changing                    // the actual length in bytes of the message.                    // The XmlWriter has been modified to pad out the                    // maximum number in zeros to accomodate any number.                    // The maximum contentLength name and value is identical                    // to the transferEncoding name and value and can                    // be easily interchanged. By doing this, we do not have                    // to piece together the header (and more importantly,                    // the lengthy body) all over again!                    // This is why the http line lengths are validated below                    Uint32 transferEncodingLineLengthExpected =                        headerNameTransferEncodingLength +                        headerNameTerminatorLength +                        headerValueTransferEncodingChunkedLength;                    Uint32 contentLengthLineLengthExpected =                        headerNameContentLengthLength +                        headerNameTerminatorLength + numberAsStringLength;                    Uint32 contentLengthLineLengthFound =                        contentLengthEnd - contentLengthStart;                    if (isValid == false || ! contentLengthEnd ||                            contentLengthLineLengthFound !=                            transferEncodingLineLengthExpected ||                            transferEncodingLineLengthExpected !=                            contentLengthLineLengthExpected)                    {                        // these should match up since this is coming                        // directly from our code in XmlWriter! If not,                        // some code changes have got out of sync                        _throwEventFailure(httpStatusInternal,                            "content length was incorrectly formatted");                    }                    // we will be sending a chunk response if:                    // 1. chunking has been requested AND                    // 2. contentLength has been set                    //    (meaning a non-bodyless message has come in) OR                    // 3. this is not the last message                    //    (meaning the data is coming in pieces and we should                    //    send chunked)                    if (isChunkRequest == true &&                        (contentLength > 0 || isLast == false))                    {                        isChunkResponse = true;                    }                    save = contentLengthStart[contentLengthLineLengthExpected];                    contentLengthStart[contentLengthLineLengthExpected] = 0;                    // overlay the contentLength value                    if (isChunkResponse == false)                    {                        // overwrite the content length number with the actual                        // byte count                        char *contentLengthNumberStart = contentLengthStart +                            headerNameContentLengthLength +                            headerNameTerminatorLength;                        char format[6];                        sprintf (format, "%%.%uu", numberAsStringLength);                        // overwrite the bytes in buffer with the content                        //encoding length                        sprintf(contentLengthNumberStart,                            format, contentLength);                        contentLengthStart[contentLengthLineLengthExpected] =                            save;                    }                    else                    {                        // overlay the contentLength name and value with the                        // transferEncoding name and value                        sprintf(contentLengthStart, "%s%s%s",                            headerNameTransferEncoding,                            headerNameTerminator,                            headerValueTransferEncodingChunked);                        bytesToWrite = messageLength - contentLength;                        contentLengthStart[contentLengthLineLengthExpected] =                            save;                        String operationName = headerNameOperation;                        // look for 2-digit prefix (if mpost was use)                        HTTPMessage::lookupHeaderPrefix(headers, operationName,                            _mpostPrefix);                    } // else chunk response is true                } // if content length was found                if (isChunkRequest == false)                {                    if (isLast == true)                    {                        if (contentLanguages.size() != 0)                        {                            // we must insert the content-language into the                            // header                            Buffer contentLanguagesString;                            // this is the keyword:value(s) + header line                            // terminator                            contentLanguagesString <<                                headerNameContentLanguage <<                                headerNameTerminator <<                                LanguageParser::buildContentLanguageHeader(                                    contentLanguages).getCString() <<                                headerLineTerminator;                            Uint32 insertOffset =                                headerLength - headerLineTerminatorLength;                            messageLength =                                contentLanguagesString.size() + buffer.size();                            buffer.reserveCapacity(messageLength+1);                            messageLength = contentLanguagesString.size();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -