in Unix/wsman/wsman.c [2589:2932]
static void _SendEnumPullResponse(
_In_ WSMAN_EnumerateContext* selfEC,
MI_Boolean fromRequest )
{
WSBuf outBufHeader;
WSBuf outBufTrailer;
Page* responsePageCombined = 0;
Page* responsePageHeader = 0;
Page* responsePageTrailer = 0;
MI_Uint32 totalSize, messagesSize = 0;
WSMAN_ConnectionData* selfCD = selfEC->activeConnection;
PostInstanceMsg* subsetEnd = 0;
MI_Boolean endOfSequence = selfEC->enumerationCompleted;
MI_Result result;
MI_ConstString bookmarkToSend = NULL;
DEBUG_ASSERT( NULL != selfCD );
#ifndef DISABLE_INDICATION
/* SubscribeResponse messages should NOT contain any indications if they
* have arrived before the SubscribeResponse message. */
if (selfCD->wsheader.rqtAction != WSMANTAG_ACTION_SUBSCRIBE)
#endif
{
/* Get message subset based on envelope size/ maxElements */
_EC_GetMessageSubset(selfEC, selfCD, &subsetEnd, &messagesSize, &bookmarkToSend);
}
/* validate if all mesages can be sent */
if (endOfSequence && subsetEnd)
{
endOfSequence = MI_FALSE;
}
/* check if we can put at least one message in response */
if (NULL != selfEC->head && subsetEnd == selfEC->head)
{
trace_Wsman_MaxEnvelopeIsTooSmall((int)subsetEnd->packedInstanceSize);
_CD_SendFaultResponse(selfCD, fromRequest ? NULL : selfEC , WSBUF_FAULT_ENCODING_LIMIT, ZT("insufficient envelope size for instance transferring"));
/* Note: leaving context 'as is' so advanced client can increase packet size and re-try */
_EC_CloseLeft( selfEC, MI_FALSE );
/* This also releases the context on WSMAN
* The response should not be sent while a timer is running.
* The timer must be stopped first */
_EC_CheckCloseRight( selfEC );
return;
}
/* Create EnumResponse */
if (WSBuf_Init(&outBufHeader, APPROX_ENUM_RESP_ENVELOPE_SIZE) != MI_RESULT_OK)
{
outBufTrailer.page = 0;
GOTO_FAILED;
}
if (WSBuf_Init(&outBufTrailer, 256) != MI_RESULT_OK)
GOTO_FAILED;
/* prepare response header */
if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
{
if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBufHeader,
LIT(ZT("http://schemas.xmlsoap.org/ws/2004/09/enumeration/EnumerateResponse")), selfCD->wsheader.rqtMessageID))
GOTO_FAILED;
}
#ifndef DISABLE_INDICATION
else if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_SUBSCRIBE)
{
if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBufHeader,
LIT(ZT("http://schemas.xmlsoap.org/ws/2004/08/eventing/SubscribeResponse")), selfCD->wsheader.rqtMessageID))
goto failed;
}
#endif /* ifndef DISABLE_INDICATION */
else
{
if (MI_RESULT_OK != WSBuf_CreateSoapResponseHeader(&outBufHeader,
LIT(ZT("http://schemas.xmlsoap.org/ws/2004/09/enumeration/PullResponse")), selfCD->wsheader.rqtMessageID))
GOTO_FAILED;
#ifndef DISABLE_INDICATION
if (selfEC->sendBookmarks)
{
if (NULL == bookmarkToSend)
{
/* A bookmark was requested by the client, but not supplied
* by the provider. Pass along the default value. */
bookmarkToSend = ZT("http://schemas.dmtf.org/wbem/wsman/1/wsman/bookmark/earliest"); // TODO: Appropriate to do?
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("<wsman:Bookmark>"))))
GOTO_FAILED;
if (MI_RESULT_OK != WSBuf_AddString(&outBufHeader,
bookmarkToSend))
GOTO_FAILED;
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("</wsman:Bookmark>"))))
GOTO_FAILED;
}
#endif
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("</SOAP-ENV:Header>")
ZT("<SOAP-ENV:Body>"))))
GOTO_FAILED;
if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("<wsen:EnumerateResponse>"))))
GOTO_FAILED;
}
#ifndef DISABLE_INDICATION
else if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_SUBSCRIBE)
{
if (MI_RESULT_OK != _WSMAN_AddSubscribeResponse(&outBufHeader, selfEC))
GOTO_FAILED;
}
#endif /* ifndef DISABLE_INDICATION */
else
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("<wsen:PullResponse>"))))
GOTO_FAILED;
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("<wsen:EnumerationContext>"))))
GOTO_FAILED;
if (MI_RESULT_OK != WSBuf_AddUint32(&outBufHeader,selfEC->enumerationContextID))
GOTO_FAILED;
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("</wsen:EnumerationContext>"))))
GOTO_FAILED;
if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("<wsman:Items>"))))
GOTO_FAILED;
}
#ifndef DISABLE_INDICATION
else if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_SUBSCRIBE)
{
}
#endif /* ifndef DISABLE_INDICATION */
else
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufHeader,
LIT(ZT("<wsen:Items>"))))
GOTO_FAILED;
}
/* trailer */
if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("</wsman:Items>"))))
GOTO_FAILED;
}
#ifndef DISABLE_INDICATION
else if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_SUBSCRIBE)
{
}
#endif /* ifndef DISABLE_INDICATION */
else
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("</wsen:Items>"))))
GOTO_FAILED;
}
if (endOfSequence)
{
if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("<wsman:EndOfSequence/>"))))
GOTO_FAILED;
}
else
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("<wsen:EndOfSequence/>"))))
GOTO_FAILED;
}
}
if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_ENUMERATE)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("</wsen:EnumerateResponse>"))))
GOTO_FAILED;
}
#ifndef DISABLE_INDICATION
else if (selfCD->wsheader.rqtAction == WSMANTAG_ACTION_SUBSCRIBE)
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(MI_T("</e:SubscribeResponse>"))))
goto failed;
}
#endif /* ifndef DISABLE_INDICATION */
else
{
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("</wsen:PullResponse>"))))
GOTO_FAILED;
}
if (MI_RESULT_OK != WSBuf_AddLit(&outBufTrailer,
LIT(ZT("</SOAP-ENV:Body>")
ZT("</SOAP-ENV:Envelope>"))))
GOTO_FAILED;
/* all together */
responsePageHeader = WSBuf_StealPage(&outBufHeader);
responsePageTrailer = WSBuf_StealPage(&outBufTrailer);
if (!responsePageTrailer || !responsePageHeader)
GOTO_FAILED;
/* calculate size */
totalSize = (MI_Uint32)(responsePageHeader->u.s.size + responsePageTrailer->u.s.size) + messagesSize;
if (sizeof(Page) + totalSize + 1 > WSMAN_ALLOCATION_LIMIT)
{
trace_Wsman_Malloc_Error(sizeof(Page) + totalSize + 1);
GOTO_FAILED;
}
responsePageCombined = (Page*)PAL_Malloc(sizeof(Page) + totalSize + 1);
if (!responsePageCombined)
GOTO_FAILED;
{
char* data = (char*) (responsePageCombined + 1);
data[totalSize] = 0;
memcpy(data, responsePageHeader+1, responsePageHeader->u.s.size);
data += responsePageHeader->u.s.size;
#ifndef DISABLE_INDICATION
/* SubscribeResponse messages should NOT contain any indications if they
* have arrived before the SubscribeResponse message. */
if (selfCD->wsheader.rqtAction != WSMANTAG_ACTION_SUBSCRIBE)
#endif
{
PostInstanceMsg* msg = selfEC->head;
while (msg != subsetEnd)
{
PostInstanceMsg* next = (PostInstanceMsg*)msg->base.next;
memcpy(data, msg->packedInstancePtr, msg->packedInstanceSize);
data += msg->packedInstanceSize;
/* remove message from the list */
selfEC->totalResponses--;
selfEC->totalResponseSize -= msg->packedInstanceSize;
List_Remove(
(ListElem**)&selfEC->head,
(ListElem**)&selfEC->tail,
(ListElem*)msg);
PostInstanceMsg_Release(msg);
msg = next;
}
}
memcpy(data, responsePageTrailer+1, responsePageTrailer->u.s.size);
data += responsePageTrailer->u.s.size;
responsePageCombined->u.s.size = totalSize;
responsePageCombined->u.s.next = 0;
}
PAL_Free(responsePageHeader); responsePageHeader = 0;
PAL_Free(responsePageTrailer); responsePageTrailer = 0;
if( fromRequest )
{
STRAND_ASSERTONSTRAND(&selfCD->strand.base);
result = _CD_SendResponse(
selfCD,
HTTP_ERROR_CODE_OK,
responsePageCombined);
}
else
{
STRAND_ASSERTONSTRAND(&selfEC->strand.base);
result = _EC_SendResponse(
selfEC,
HTTP_ERROR_CODE_OK,
responsePageCombined);
}
_EC_StartHeartbeatTimer( selfEC );
goto Done;
failed:
WSBuf_Destroy(&outBufHeader);
WSBuf_Destroy(&outBufTrailer);
if (responsePageCombined) PAL_Free(responsePageCombined);
if (responsePageHeader) PAL_Free(responsePageHeader);
if (responsePageTrailer) PAL_Free(responsePageTrailer);
if( fromRequest )
{
STRAND_ASSERTONSTRAND(&selfCD->strand.base);
// There should be no responses at this point
DEBUG_ASSERT( NULL == selfEC->head );
result = _CD_SendFailedResponse(selfCD);
}
else
{
STRAND_ASSERTONSTRAND(&selfEC->strand.base);
_EC_ReleaseAllMessages(selfEC);
result = _EC_SendResponse(
selfEC,
HTTP_ERROR_CODE_INTERNAL_SERVER_ERROR,
NULL);
}
Done:
if (result != MI_RESULT_OK)
{
DEBUG_ASSERT( MI_RESULT_OK == result );
}
_EC_CloseLeft( selfEC, fromRequest );
_EC_ProcessPendingMessage( selfEC );
}