version 1.56, 2005/07/08 14:51:15
|
version 1.57, 2005/07/26 21:42:21
|
|
|
// Seema Gupta (gseema@in.ibm.com for PEP135) | // Seema Gupta (gseema@in.ibm.com for PEP135) |
// David Dillard, VERITAS Software Corp. | // David Dillard, VERITAS Software Corp. |
// (david.dillard@veritas.com) | // (david.dillard@veritas.com) |
|
// John Alex, IBM (johnalex@us.ibm.com) - Bug#2290 |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
| |
void CIMExportRequestDecoder::sendResponse( | void CIMExportRequestDecoder::sendResponse( |
Uint32 queueId, | Uint32 queueId, |
Array<char>& message) |
Array<char>& message, |
|
Boolean closeConnect) |
{ | { |
MessageQueue* queue = MessageQueue::lookup(queueId); | MessageQueue* queue = MessageQueue::lookup(queueId); |
| |
if (queue) | if (queue) |
{ | { |
HTTPMessage* httpMessage = new HTTPMessage(message); | HTTPMessage* httpMessage = new HTTPMessage(message); |
|
httpMessage->setCloseConnect(closeConnect); |
queue->enqueue(httpMessage); | queue->enqueue(httpMessage); |
} | } |
} | } |
|
|
HttpMethod httpMethod, | HttpMethod httpMethod, |
const String& messageId, | const String& messageId, |
const String& eMethodName, | const String& eMethodName, |
const CIMException& cimException) |
const CIMException& cimException, |
|
Boolean closeConnect) |
{ | { |
Array<char> message; | Array<char> message; |
message = XmlWriter::formatSimpleEMethodErrorRspMessage( | message = XmlWriter::formatSimpleEMethodErrorRspMessage( |
|
|
httpMethod, | httpMethod, |
cimException); | cimException); |
| |
sendResponse(queueId, message); |
sendResponse(queueId, message,closeConnect); |
} | } |
| |
void CIMExportRequestDecoder::sendHttpError( | void CIMExportRequestDecoder::sendHttpError( |
Uint32 queueId, | Uint32 queueId, |
const String& status, | const String& status, |
const String& cimError, | const String& cimError, |
const String& messageBody) |
const String& messageBody, |
|
Boolean closeConnect) |
{ | { |
Array<char> message; | Array<char> message; |
message = XmlWriter::formatHttpErrorRspMessage( | message = XmlWriter::formatHttpErrorRspMessage( |
|
|
cimError, | cimError, |
messageBody); | messageBody); |
| |
sendResponse(queueId, message); |
sendResponse(queueId, message,closeConnect); |
} | } |
| |
void CIMExportRequestDecoder::handleEnqueue(Message *message) | void CIMExportRequestDecoder::handleEnqueue(Message *message) |
|
|
userName = httpMessage->authInfo->getAuthenticatedUser(); | userName = httpMessage->authInfo->getAuthenticatedUser(); |
} | } |
| |
|
Boolean closeConnect = httpMessage->getCloseConnect(); |
|
Tracer::trace( |
|
TRC_HTTP, |
|
Tracer::LEVEL3, |
|
"CIMOperationRequestDecoder::handleHTTPMessage()- httpMessage->getCloseConnect() returned %d",httpMessage->getCloseConnect()); |
|
|
// Parse the HTTP message: | // Parse the HTTP message: |
| |
String startLine; | String startLine; |
|
|
sendHttpError( | sendHttpError( |
queueId, | queueId, |
HTTP_STATUS_NOTIMPLEMENTED, | HTTP_STATUS_NOTIMPLEMENTED, |
"Only POST and M-POST are implemented" ); |
"Only POST and M-POST are implemented", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
//</bug> | //</bug> |
|
|
if( (httpMethod == HTTP_METHOD_M_POST) && | if( (httpMethod == HTTP_METHOD_M_POST) && |
(httpVersion == "HTTP/1.0") ) | (httpVersion == "HTTP/1.0") ) |
{ | { |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_BADREQUEST, | HTTP_STATUS_BADREQUEST, |
"M-POST method is not valid with version 1.0" ); |
"M-POST method is not valid with version 1.0", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
//</bug> | //</bug> |
|
|
"ExportServer.CIMExportRequestDecoder.MISSING_HOST_HEADER", | "ExportServer.CIMExportRequestDecoder.MISSING_HOST_HEADER", |
"HTTP request message lacks a Host header field."); | "HTTP request message lacks a Host header field."); |
String msg(MessageLoader::getMessage(parms)); | String msg(MessageLoader::getMessage(parms)); |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "", msg); |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"", |
|
msg, |
|
closeConnect); |
return; | return; |
} | } |
} | } |
|
|
// PEGASUS_ASSERT(exportHeaderFound); | // PEGASUS_ASSERT(exportHeaderFound); |
if (!exportHeaderFound) | if (!exportHeaderFound) |
{ | { |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_BADREQUEST, | HTTP_STATUS_BADREQUEST, |
"Export header not found"); |
"Export header not found", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
// </bug> | // </bug> |
|
|
// status "400 Bad Request". The CIM Server MUST include a | // status "400 Bad Request". The CIM Server MUST include a |
// CIMError header in the response with a value of | // CIMError header in the response with a value of |
// unsupported-operation. | // unsupported-operation. |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_BADREQUEST, | HTTP_STATUS_BADREQUEST, |
"unsupported-operation"); |
"unsupported-operation", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
// CIMExportBatch header is present, but the Listener does not | // CIMExportBatch header is present, but the Listener does not |
// support Multiple Exports, then it MUST fail the request and | // support Multiple Exports, then it MUST fail the request and |
// return a status of "501 Not Implemented". | // return a status of "501 Not Implemented". |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_NOTIMPLEMENTED, | HTTP_STATUS_NOTIMPLEMENTED, |
"multiple-requests-unsupported"); |
"multiple-requests-unsupported", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
if (cimExportMethod == String::EMPTY) | if (cimExportMethod == String::EMPTY) |
{ | { |
// This is not a valid value, and we use EMPTY to mean "absent" | // This is not a valid value, and we use EMPTY to mean "absent" |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "header-mismatch"); |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"header-mismatch", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
} | } |
|
|
Thread::clearLanguages(); | Thread::clearLanguages(); |
MessageLoaderParms msgParms("ExportServer.CIMExportRequestDecoder.REQUEST_NOT_VALID","request-not-valid"); | MessageLoaderParms msgParms("ExportServer.CIMExportRequestDecoder.REQUEST_NOT_VALID","request-not-valid"); |
String msg(MessageLoader::getMessage(msgParms)); | String msg(MessageLoader::getMessage(msgParms)); |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_BADREQUEST, |
msg, | msg, |
e.getMessage()); |
e.getMessage(), |
|
closeConnect); |
return; | return; |
} | } |
// l10n end | // l10n end |
|
|
String::equalNoCase(cimContentType, "text/xml; charset=\"utf-8\"") || | String::equalNoCase(cimContentType, "text/xml; charset=\"utf-8\"") || |
contentTypeHeaderFound)) | contentTypeHeaderFound)) |
{ | { |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "header-mismatch", |
sendHttpError( |
"CIMContentType value syntax error."); |
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"header-mismatch", |
|
"CIMContentType value syntax error.", |
|
closeConnect); |
return; | return; |
} | } |
// Validating content falls within UTF8 | // Validating content falls within UTF8 |
|
|
{ | { |
if (!(isUTF8((char *)&content[count]))) | if (!(isUTF8((char *)&content[count]))) |
{ | { |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "request-not-valid", |
sendHttpError( |
"Invalid UTF-8 character detected."); |
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"request-not-valid", |
|
"Invalid UTF-8 character detected.", |
|
closeConnect); |
return; | return; |
} | } |
UTF8_NEXT(content,count); | UTF8_NEXT(content,count); |
|
|
// If it is a method call, then dispatch it to be handled: | // If it is a method call, then dispatch it to be handled: |
| |
// l10n | // l10n |
handleMethodRequest(queueId, httpMethod, content, requestUri, |
handleMethodRequest( |
cimProtocolVersion, cimExportMethod, userName, |
queueId, |
acceptLanguages, contentLanguages); |
httpMethod, |
|
content, |
|
requestUri, |
|
cimProtocolVersion, |
|
cimExportMethod, |
|
userName, |
|
acceptLanguages, |
|
contentLanguages, |
|
closeConnect); |
} | } |
| |
| |
|
|
const String& cimExportMethodInHeader, | const String& cimExportMethodInHeader, |
const String& userName, | const String& userName, |
const AcceptLanguages& httpAcceptLanguages, // l10n | const AcceptLanguages& httpAcceptLanguages, // l10n |
const ContentLanguages& httpContentLanguages) |
const ContentLanguages& httpContentLanguages, |
|
Boolean closeConnect) |
{ | { |
// l10n | // l10n |
// Set the Accept-Language into the thread for this service. | // Set the Accept-Language into the thread for this service. |
|
|
// | // |
if (_serverTerminating) | if (_serverTerminating) |
{ | { |
sendHttpError(queueId, HTTP_STATUS_SERVICEUNAVAILABLE, |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_SERVICEUNAVAILABLE, |
String::EMPTY, | String::EMPTY, |
"CIM Listener is shutting down."); |
"CIM Listener is shutting down.", |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
| |
if (strcmp(cimVersion, "2.0") != 0) | if (strcmp(cimVersion, "2.0") != 0) |
{ | { |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_NOTIMPLEMENTED, | HTTP_STATUS_NOTIMPLEMENTED, |
"unsupported-cim-version"); |
"unsupported-cim-version", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
| |
if (!dtdVersionAccepted) | if (!dtdVersionAccepted) |
{ | { |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_NOTIMPLEMENTED, | HTTP_STATUS_NOTIMPLEMENTED, |
"unsupported-dtd-version"); |
"unsupported-dtd-version", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
| |
if (!String::equalNoCase(protocolVersion, cimProtocolVersionInHeader)) | if (!String::equalNoCase(protocolVersion, cimProtocolVersionInHeader)) |
{ | { |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_BADREQUEST, | HTTP_STATUS_BADREQUEST, |
"header-mismatch"); |
"header-mismatch", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
if (!protocolVersionAccepted) | if (!protocolVersionAccepted) |
{ | { |
// See Specification for CIM Operations over HTTP section 4.3 | // See Specification for CIM Operations over HTTP section 4.3 |
sendHttpError(queueId, |
sendHttpError( |
|
queueId, |
HTTP_STATUS_NOTIMPLEMENTED, | HTTP_STATUS_NOTIMPLEMENTED, |
"unsupported-protocol-version"); |
"unsupported-protocol-version", |
|
String::EMPTY, |
|
closeConnect); |
|
|
return; | return; |
} | } |
| |
|
|
{ | { |
// We wouldn't have gotten here if CIMExportBatch header was | // We wouldn't have gotten here if CIMExportBatch header was |
// specified, so this must be indicative of a header mismatch | // specified, so this must be indicative of a header mismatch |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "header-mismatch"); |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"header-mismatch", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
// Future: When MULTIEXPREQ is supported, must ensure CIMExportMethod | // Future: When MULTIEXPREQ is supported, must ensure CIMExportMethod |
// header is absent, and CIMExportBatch header is present. | // header is absent, and CIMExportBatch header is present. |
|
|
if (!String::equalNoCase(cimExportMethodName, cimExportMethodInHeader)) | if (!String::equalNoCase(cimExportMethodName, cimExportMethodInHeader)) |
{ | { |
// ATTN-RK-P3-20020404: How to decode cimExportMethodInHeader? | // ATTN-RK-P3-20020404: How to decode cimExportMethodInHeader? |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "header-mismatch"); |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"header-mismatch", |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
httpMethod, | httpMethod, |
messageId, | messageId, |
cimExportMethodName, | cimExportMethodName, |
e); |
e, |
|
closeConnect); |
| |
return; | return; |
} | } |
|
|
Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE, | Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE, |
"CIMExportRequestDecoder::handleMethodRequest - XmlValidationError exception has occurred. Message: $0",e.getMessage()); | "CIMExportRequestDecoder::handleMethodRequest - XmlValidationError exception has occurred. Message: $0",e.getMessage()); |
| |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "request-not-valid", |
sendHttpError( |
e.getMessage()); |
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"request-not-valid", |
|
e.getMessage(), |
|
closeConnect); |
return; | return; |
} | } |
catch (XmlSemanticError& e) | catch (XmlSemanticError& e) |
|
|
Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE, | Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE, |
"CIMExportRequestDecoder::handleMethodRequest - XmlSemanticError exception has occurred. Message: $0",e.getMessage()); | "CIMExportRequestDecoder::handleMethodRequest - XmlSemanticError exception has occurred. Message: $0",e.getMessage()); |
// ATTN-RK-P2-20020404: Is this the correct response for these errors? | // ATTN-RK-P2-20020404: Is this the correct response for these errors? |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "request-not-valid", |
sendHttpError( |
e.getMessage()); |
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"request-not-valid", |
|
e.getMessage(), |
|
closeConnect); |
return; | return; |
} | } |
catch (XmlException& e) | catch (XmlException& e) |
|
|
Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE, | Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE, |
"CIMExportRequestDecoder::handleMethodRequest - XmlException has occurred. Message: $0",e.getMessage()); | "CIMExportRequestDecoder::handleMethodRequest - XmlException has occurred. Message: $0",e.getMessage()); |
| |
sendHttpError(queueId, HTTP_STATUS_BADREQUEST, "request-not-well-formed", |
sendHttpError( |
e.getMessage()); |
queueId, |
|
HTTP_STATUS_BADREQUEST, |
|
"request-not-well-formed", |
|
e.getMessage(), |
|
closeConnect); |
return; | return; |
} | } |
catch (Exception& e) | catch (Exception& e) |
|
|
// Don't know why I got this exception. Seems like a bad thing. | // Don't know why I got this exception. Seems like a bad thing. |
// Any exceptions we're expecting should be caught separately and | // Any exceptions we're expecting should be caught separately and |
// dealt with appropriately. This is a last resort. | // dealt with appropriately. This is a last resort. |
sendHttpError(queueId, HTTP_STATUS_INTERNALSERVERERROR, String::EMPTY, |
sendHttpError( |
e.getMessage()); |
queueId, |
|
HTTP_STATUS_INTERNALSERVERERROR, |
|
String::EMPTY, |
|
e.getMessage(), |
|
closeConnect); |
return; | return; |
} | } |
catch (...) | catch (...) |
|
|
// Don't know why I got whatever this is. Seems like a bad thing. | // Don't know why I got whatever this is. Seems like a bad thing. |
// Any exceptions we're expecting should be caught separately and | // Any exceptions we're expecting should be caught separately and |
// dealt with appropriately. This is a last resort. | // dealt with appropriately. This is a last resort. |
sendHttpError(queueId, HTTP_STATUS_INTERNALSERVERERROR); |
sendHttpError( |
|
queueId, |
|
HTTP_STATUS_INTERNALSERVERERROR, |
|
String::EMPTY, |
|
String::EMPTY, |
|
closeConnect); |
return; | return; |
} | } |
| |
|
|
} | } |
// l10n end | // l10n end |
| |
|
request->setCloseConnect(closeConnect); |
|
|
_outputQueue->enqueue(request.release()); | _outputQueue->enqueue(request.release()); |
} | } |
| |