cimoperationresponsedecoder.cpp

来自「Pegasus is an open-source implementation」· C++ 代码 · 共 1,785 行 · 第 1/4 页

CPP
1,785
字号
//%2006//////////////////////////////////////////////////////////////////////////// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;// IBM Corp.; EMC Corporation, The Open Group.// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;// EMC Corporation; VERITAS Software Corporation; The Open Group.// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;// EMC Corporation; Symantec Corporation; The Open Group.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions:// // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.////==============================================================================////%/////////////////////////////////////////////////////////////////////////////#include <Pegasus/Common/Config.h>#include <iostream>#include <Pegasus/Common/Constants.h>#include <Pegasus/Common/XmlParser.h>#include <Pegasus/Common/XmlReader.h>#include <Pegasus/Common/System.h>#include <Pegasus/Common/XmlWriter.h>#include <Pegasus/Common/HTTPMessage.h>#include <Pegasus/Common/CIMMessage.h>#include <Pegasus/Common/Exception.h>#include "CIMOperationResponseDecoder.h"#include <Pegasus/Common/MessageLoader.h>PEGASUS_USING_STD;PEGASUS_NAMESPACE_BEGINCIMOperationResponseDecoder::CIMOperationResponseDecoder(    MessageQueue* outputQueue,    MessageQueue* encoderQueue,    ClientAuthenticator* authenticator,    Uint32 showInput)    :    MessageQueue(PEGASUS_QUEUENAME_OPRESPDECODER),    _outputQueue(outputQueue),    _encoderQueue(encoderQueue),    _authenticator(authenticator),    _showInput(showInput){}CIMOperationResponseDecoder::~CIMOperationResponseDecoder(){}void  CIMOperationResponseDecoder::setEncoderQueue(MessageQueue* encoderQueue){    _encoderQueue = encoderQueue;}void CIMOperationResponseDecoder::handleEnqueue(){    Message* message = dequeue();    if (!message)        return;    switch (message->getType())    {        case HTTP_MESSAGE:        {            HTTPMessage* httpMessage = (HTTPMessage*)message;            _handleHTTPMessage(httpMessage);            break;        }        default:            PEGASUS_ASSERT(0);            break;    }    delete message;}void CIMOperationResponseDecoder::setDataStorePointer(    ClientPerfDataStore* perfDataStore_ptr){   dataStore = perfDataStore_ptr;}void CIMOperationResponseDecoder::_handleHTTPMessage(HTTPMessage* httpMessage){    //    // Parse the HTTP message:    //    TimeValue networkEndTime = TimeValue::getCurrentTime();    String  connectClose;    String  startLine;    Array<HTTPHeader> headers;    char*   content;    Uint32  contentLength;    Boolean cimReconnect=false;    if (httpMessage->message.size() == 0)    {        MessageLoaderParms mlParms(            "Client.CIMOperationResponseDecoder.EMPTY_RESPONSE",            "Empty HTTP response message.");        String mlString(MessageLoader::getMessage(mlParms));        CIMClientMalformedHTTPException* malformedHTTPException =            new CIMClientMalformedHTTPException(mlString);        ClientExceptionMessage * response =            new ClientExceptionMessage(malformedHTTPException);        _outputQueue->enqueue(response);        return;    }    httpMessage->parse(startLine, headers, contentLength);    //    // Check for Connection: Close    //    if (HTTPMessage::lookupHeader(headers, "Connection", connectClose, false))    {        if (String::equalNoCase(connectClose, "Close"))        {            //reconnect and then resend next request.            cimReconnect=true;        }    }    //    // Get the status line info    //    String httpVersion;    Uint32 statusCode;    String reasonPhrase;    Boolean parsableMessage = HTTPMessage::parseStatusLine(        startLine, httpVersion, statusCode, reasonPhrase);    if (!parsableMessage)    {        MessageLoaderParms mlParms(            "Client.CIMOperationResponseDecoder.MALFORMED_RESPONSE",            "Malformed HTTP response message.");        String mlString(MessageLoader::getMessage(mlParms));        CIMClientMalformedHTTPException* malformedHTTPException =            new CIMClientMalformedHTTPException(mlString);        ClientExceptionMessage * response =            new ClientExceptionMessage(malformedHTTPException);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }#ifdef PEGASUS_CLIENT_TRACE_ENABLE    if (_showInput & 1)    {        cout << "CIMOperatonResponseDecoder";        httpMessage->printAll(cout);    }    if (_showInput & 2)    {        Uint32 size = httpMessage->message.size();        char* tmpBuf = new char[size+1];        strncpy( tmpBuf, httpMessage->message.getData(), size );        tmpBuf[size] = '\0';        Logger::put(Logger::STANDARD_LOG,            System::CIMSERVER,            Logger::TRACE,            "CIMOperationRequestDecoder::Response, XML content: $1",            tmpBuf);        delete []tmpBuf;    }#endif    try    {        if (_authenticator->checkResponseHeaderForChallenge(headers))        {            //            // Get the original request, put that in the encoder's queue for            // re-sending with authentication challenge response.            //            Message* reqMessage = _authenticator->releaseRequestMessage();            if (cimReconnect == true)            {                reqMessage->setCloseConnect(cimReconnect);                _outputQueue->enqueue(reqMessage);            }            else            {                _encoderQueue->enqueue(reqMessage);            }            return;        }        else        {            //            // Received a valid/error response from the server.            // We do not need the original request message anymore, hence            // delete the request message by getting the handle from the            // ClientAuthenticator.            //            Message* reqMessage = _authenticator->releaseRequestMessage();            delete reqMessage;        }    }    catch (InvalidAuthHeader& e)    {        CIMClientMalformedHTTPException* malformedHTTPException =            new CIMClientMalformedHTTPException(e.getMessage());        ClientExceptionMessage * response =            new ClientExceptionMessage(malformedHTTPException);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }    // We have the response.  If authentication failed, we will generate a    // CIMClientHTTPErrorException below with the "401 Unauthorized" status    // in the (re-challenge) response.    //    // Check for a success (200 OK) response    //    if (statusCode != HTTP_STATUSCODE_OK)    {        String cimError;        String pegasusError;        HTTPMessage::lookupHeader(headers, "CIMError", cimError, true);        HTTPMessage::lookupHeader(            headers, PEGASUS_HTTPHEADERTAG_ERRORDETAIL, pegasusError);        try        {            pegasusError = XmlReader::decodeURICharacters(pegasusError);        }        catch (ParseError&)        {            // Ignore this exception.  We're more interested in having the            // message in encoded form than knowing that the format is invalid.        }        CIMClientHTTPErrorException* httpError =            new CIMClientHTTPErrorException(statusCode, reasonPhrase,                                            cimError, pegasusError);        ClientExceptionMessage * response =            new ClientExceptionMessage(httpError);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }    //    // Search for "CIMOperation" header:    //    String cimOperation;    if (!HTTPMessage::lookupHeader(        headers, "CIMOperation", cimOperation, true))    {        MessageLoaderParms mlParms(            "Client.CIMOperationResponseDecoder.MISSING_CIMOP_HEADER",            "Missing CIMOperation HTTP header");        String mlString(MessageLoader::getMessage(mlParms));        CIMClientMalformedHTTPException* malformedHTTPException =            new CIMClientMalformedHTTPException(mlString);        ClientExceptionMessage * response =            new ClientExceptionMessage(malformedHTTPException);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }    //    // Search for "Content-Type" header:    //    // BUG 572, Use of Content-Type header and change error msg.    // If header exists, test type.  If not, ignore. We will find    // content type errors in text analysis.    // content-type header  value format:    //              type "/" subtype *( ";" parameter )    // ex. text/xml;Charset="utf8"    String cimContentType;    if (HTTPMessage::lookupHeader(            headers, "Content-Type", cimContentType, true))    {        Uint32 len;        String contentTypeValue;        if ((len = cimContentType.find(';')) != PEG_NOT_FOUND)            contentTypeValue = cimContentType.subString(0,len);        else            contentTypeValue = cimContentType;        if (!String::equalNoCase(contentTypeValue, "text/xml") &&            !String::equalNoCase(contentTypeValue, "application/xml"))        {            CIMClientMalformedHTTPException* malformedHTTPException = new                CIMClientMalformedHTTPException                    ("Bad Content-Type HTTP header; " + contentTypeValue);            ClientExceptionMessage * response =                new ClientExceptionMessage(malformedHTTPException);            response->setCloseConnect(cimReconnect);            _outputQueue->enqueue(response);            return;        }    }    // comment out the error rejection code if the content-type header does    //    not exist#ifdef PEGASUS_REJECT_ON_MISSING_CONTENTTYPE_HEADER    else    {        CIMClientMalformedHTTPException* malformedHTTPException = new            CIMClientMalformedHTTPException                ("Missing Content-Type HTTP header; ");        ClientExceptionMessage * response =            new ClientExceptionMessage(malformedHTTPException);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }#endif    // look for any cim status codes. The HTTPConnection level would have    // added them here.    String cimStatusCodeValue;    Boolean found = HTTPMessage::lookupHeader(headers, "CIMStatusCode",        cimStatusCodeValue, true);    CIMStatusCode cimStatusCodeNumber = CIM_ERR_SUCCESS;    if (found == true &&        (cimStatusCodeNumber = (CIMStatusCode)         atoi(cimStatusCodeValue.getCString())) != CIM_ERR_SUCCESS)    {        String cimStatusCodeDescription;        found = HTTPMessage::lookupHeader(headers, "CIMStatusCodeDescription",            cimStatusCodeDescription, true);        if (found == true && cimStatusCodeDescription.size() > 0)        {            try            {                cimStatusCodeDescription =                    XmlReader::decodeURICharacters(cimStatusCodeDescription);            }            catch (ParseError&)            {            }        } // if there is a description with the code        CIMException* cimStatusException =            new CIMException(cimStatusCodeNumber,cimStatusCodeDescription);        cimStatusException->setContentLanguages(httpMessage->contentLanguages);        ClientExceptionMessage * response =            new ClientExceptionMessage(cimStatusException);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }    String serverTime;    if (HTTPMessage::lookupHeader(            headers, "WBEMServerResponseTime", serverTime, true))    {        Uint32 sTime = (Uint32) atol(serverTime.getCString());        dataStore->setServerTime(sTime);    }    //    // Zero-terminate the message:    //    httpMessage->message.append('\0');    // Calculate the beginning of the content from the message size and    // the content length.  Subtract 1 to take into account the null    // character we just added to the end of the message.    content = (char *) httpMessage->message.getData() +        httpMessage->message.size() - contentLength - 1;    //    // If it is a method response, then dispatch it to be handled:    //    if (!String::equalNoCase(cimOperation, "MethodResponse"))    {        MessageLoaderParms mlParms(            "Client.CIMOperationResponseDecoder.EXPECTED_METHODRESPONSE",            "Received CIMOperation HTTP header value \"$1\", expected "                "\"MethodResponse\"",            cimOperation);        String mlString(MessageLoader::getMessage(mlParms));        CIMClientMalformedHTTPException* malformedHTTPException =            new CIMClientMalformedHTTPException(mlString);        ClientExceptionMessage * response =            new ClientExceptionMessage(malformedHTTPException);        response->setCloseConnect(cimReconnect);        _outputQueue->enqueue(response);        return;    }    dataStore->setResponseSize(contentLength);    dataStore->setEndNetworkTime(networkEndTime);    _handleMethodResponse(content, httpMessage->contentLanguages,cimReconnect);

⌨️ 快捷键说明

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