static const String httpDetailDelimiter = headerValueSeparator;
static const String httpStatusInternal = HTTP_STATUS_INTERNALSERVERERROR;
+static const char INTERNAL_SERVER_ERROR_CONNECTION_CLOSED_KEY[] =
+ "Common.HTTPConnection.INTERNAL_SERVER_ERROR_CONNECTION_CLOSED";
+static const char INTERNAL_SERVER_ERROR_CONNECTION_CLOSED[] =
+ "Internal server error. Connection with IP address $0 closed.";
+
/*
* throw given http code with detail, file, line
* This is shared client/server code. The caller will decide what to do
_contentLength(-1),
_connectionClosePending(false),
_acceptPending(false),
- _firstRead(true)
+ _firstRead(true),
+ _internalError(false)
{
PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnection::HTTPConnection");
handleEnqueue(message);
}
+void HTTPConnection::handleInternalServerError(
+ Uint32 respMsgIndex,
+ Boolean isComplete)
+{
+ PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnection::handleInternalServerError");
+
+ PEG_TRACE((TRC_HTTP, Tracer::LEVEL1,
+ "Internal server error. Connection queue id : %u, IP address :%s, "
+ "Response Index :%u, Response is Complete :%u.",
+ getQueueId(),
+ (const char*)_ipAddress.getCString(),
+ respMsgIndex,
+ isComplete));
+
+ _internalError = true;
+ Buffer buffer;
+ HTTPMessage message(buffer);
+ message.setIndex(respMsgIndex);
+ message.setComplete(isComplete);
+ AutoMutex connectionLock(_connection_mut);
+ _handleWriteEvent(message);
+ PEG_METHOD_EXIT();
+}
+
void HTTPConnection::handleEnqueue(Message *message)
{
PEG_METHOD_ENTER(TRC_HTTP, "HTTPConnection::handleEnqueue");
_transferEncodingChunkOffset++;
}
+ // If there is an internal error on this connection, just return
+ // from here if the current message is not the last message becasue
+ // this connection will be closed once all messages are received.
+ if (_internalError)
+ {
+ if (isLast)
+ {
+ _responsePending = false;
+ _closeConnection();
+ Logger::put_l(
+ Logger::ERROR_LOG,
+ System::CIMSERVER,
+ Logger::SEVERE,
+ MessageLoaderParms(
+ INTERNAL_SERVER_ERROR_CONNECTION_CLOSED_KEY,
+ INTERNAL_SERVER_ERROR_CONNECTION_CLOSED,
+ _ipAddress));
+ }
+ return true;
+ }
+
// save the first error
if (httpMessage.cimException.getCode() != CIM_ERR_SUCCESS)
{
catch (Exception &e)
{
httpStatusString = e.getMessage();
+ _internalError = true;
+ }
+ catch (PEGASUS_STD(bad_alloc)&)
+ {
+ httpStatusString = "Out of memory";
+ _internalError = true;
}
catch (...)
{
- httpStatusString = HTTP_STATUS_INTERNALSERVERERROR;
- PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL1, "Unknown internal error");
+ httpStatusString = "Unknown error";
+ _internalError = true;
+ }
+
+ if (httpStatusString.size())
+ {
+ PEG_TRACE((TRC_HTTP, Tracer::LEVEL1,
+ "Internal error: %s, connection queue id: %u",
+ (const char*)httpStatusString.getCString(),
+ getQueueId()));
}
if (isLast == true)
//
if (_isClient() == false)
{
+ if (_internalError)
+ {
+ _closeConnection();
+ Logger::put_l(
+ Logger::ERROR_LOG,
+ System::CIMSERVER,
+ Logger::SEVERE,
+ MessageLoaderParms(
+ INTERNAL_SERVER_ERROR_CONNECTION_CLOSED_KEY,
+ INTERNAL_SERVER_ERROR_CONNECTION_CLOSED,
+ _ipAddress));
+ }
// Check for message to close
- if (httpMessage.getCloseConnect())
+ else if (httpMessage.getCloseConnect())
{
PEG_TRACE((TRC_HTTP, Tracer::LEVEL3,
"HTTPConnection::_handleWriteEvent: \"Connection: Close\" "
Boolean closeConnectionOnTimeout(struct timeval* timeNow);
+ // This method is called in Server code when response encoders or
+ // HTTPAuthenticatorDelegator runs out-of-memory. This method calls
+ // _handleWriteEvent() with a dummy HTTPMessage to maintain response
+ // chunk sequence properly. Once all responses are arrived, connection
+ // is closed. Param "respMsgIndex" indicates the response index and
+ // isComplete indicates whether the response is complete or not.
+ void handleInternalServerError(
+ Uint32 respMsgIndex,
+ Boolean isComplete);
+
// ATTN-RK-P1-20020521: This is a major hack, required to get the CIM
// server and tests to run successfully. The problem is that the
// HTTPAcceptor is deleting an HTTPConnection before all the threads
#ifndef PEGASUS_INTEGERS_BOUNDARY_ALIGNED
static Mutex _idleConnectionTimeoutSecondsMutex;
#endif
+ // When this flag is set to true, it indicates that internal error on this
+ // connection occured. Currently this flag is used by the Server code when
+ // out-of-memory error is occurs and connection is closed by the server
+ // once all responses are arrived.
+ Boolean _internalError;
friend class Monitor;
friend class HTTPAcceptor;
}
Uint32 queueId = response->queueIds.top();
- response->queueIds.pop();
Boolean closeConnect = response->getCloseConnect();
PEG_TRACE((
}
else
{
- // else non-error condition
- try
- {
- message = formatResponse(
- cimName,
- messageId,
- httpMethod,
- contentLanguage,
- body,
- serverTime,
- isFirst,
- isLast);
- }
- catch (PEGASUS_STD(bad_alloc)&)
- {
- MessageLoaderParms parms(
- "Server.CIMOperationResponseEncoder.OUT_OF_MEMORY",
- "A System error has occurred. Please retry the CIM Operation "
- "at a later time.");
-
- Logger::put_l(
- Logger::ERROR_LOG, System::CIMSERVER, Logger::WARNING,
- parms);
-
- cimException = PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, parms);
-
- // try again with new error and no body
- body.clear();
- sendResponse(response, name, isImplicit);
- PEG_METHOD_EXIT();
- return;
- }
+ message = formatResponse(
+ cimName,
+ messageId,
+ httpMethod,
+ contentLanguage,
+ body,
+ serverTime,
+ isFirst,
+ isLast);
STAT_BYTESSENT
}
void CIMOperationResponseEncoder::enqueue(Message* message)
{
- handleEnqueue(message);
+ try
+ {
+ handleEnqueue(message);
+ }
+ catch(PEGASUS_STD(bad_alloc)&)
+ {
+ MessageLoaderParms parms(
+ "Server.CIMOperationResponseEncoder.OUT_OF_MEMORY",
+ "A System error has occurred. Please retry the CIM Operation "
+ "at a later time.");
+
+ Logger::put_l(
+ Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, parms);
+
+ CIMResponseMessage* response =
+ dynamic_cast<CIMResponseMessage*>(message);
+ Uint32 queueId = response->queueIds.top();
+ MessageQueue* queue = MessageQueue::lookup(queueId);
+ HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue);
+ PEGASUS_ASSERT(httpQueue);
+
+ // Handle internal error on this connection.
+ httpQueue->handleInternalServerError(
+ response->getIndex(), response->isComplete());
+
+ delete message;
+ }
}
void CIMOperationResponseEncoder::handleEnqueue(Message* message)
catch (const bad_alloc&)
{
delete httpMessage;
- _sendHttpError(
- queueId,
- HTTP_STATUS_REQUEST_TOO_LARGE,
- String::EMPTY,
- String::EMPTY,
- closeConnect);
+ HTTPConnection *httpQueue =
+ dynamic_cast<HTTPConnection*>(
+ MessageQueue::lookup(queueId));
+ if (httpQueue)
+ {
+ httpQueue->handleInternalServerError(0, true);
+ }
PEG_METHOD_EXIT();
deleteMessage = false;
return;
catch (const bad_alloc&)
{
delete httpMessage;
- _sendHttpError(
- queueId,
- HTTP_STATUS_REQUEST_TOO_LARGE,
- String::EMPTY,
- String::EMPTY,
- closeConnect);
+ HTTPConnection *httpQueue =
+ dynamic_cast<HTTPConnection*>(
+ MessageQueue::lookup(queueId));
+ if (httpQueue)
+ {
+ httpQueue->handleInternalServerError(0, true);
+ }
PEG_METHOD_EXIT();
deleteMessage = false;
return;
}
catch (PEGASUS_STD(bad_alloc)&)
{
- WsmFault fault(WsmFault::wsman_InternalError,
- MessageLoaderParms(
- "WsmServer.WsmResponseEncoder.OUT_OF_MEMORY",
- "A System error has occurred. Please retry the "
- "WS-Management operation at a later time."));
- WsmFaultResponse outofmem(
- response->getRelatesTo(),
- response->getQueueId(),
- response->getHttpMethod(),
- response->getHttpCloseConnect(),
- fault);
- _encodeWsmFaultResponse(&outofmem);
+ MessageLoaderParms parms(
+ "WsmServer.WsmResponseEncoder.OUT_OF_MEMORY",
+ "A System error has occurred. Please retry the "
+ "WS-Management operation at a later time.");
+
+ Logger::put_l(
+ Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, parms);
+
+ MessageQueue* queue = MessageQueue::lookup(response->getQueueId());
+ HTTPConnection* httpQueue = dynamic_cast<HTTPConnection*>(queue);
+ PEGASUS_ASSERT(httpQueue);
+
+ // Handle the internal server error on this connection.
+ httpQueue->handleInternalServerError(0, true);
}
PEG_METHOD_EXIT();
Common.HTTPConnection.UNKNOWN_EXCEPTION:string {"PGS08100: Unknown exception caught while parsing HTTP message."}
+ /**
+ * @note PGS08101:
+ * Substitution {0} is a string containing the host of the CIMClient connection
+ */
+ Common.HTTPConnection.INTERNAL_SERVER_ERROR_CONNECTION_CLOSED:string {"PGS08101: Internal server error. Connection with IP address {0} closed."}
// ==========================================================
// Messages for LanguageParser