private bool ProcessResponseMessage(uint messageType, ArraySegment<byte> messageChunk)
{
//Utils.Trace("Channel {0}: ProcessResponseMessage()", ChannelId);
// validate security on the message.
TcpChannelToken token = null;
uint requestId = 0;
uint sequenceNumber = 0;
ArraySegment<byte> messageBody;
try
{
messageBody = ReadSymmetricMessage(messageChunk, false, out token, out requestId, out sequenceNumber);
}
catch (Exception e)
{
ForceReconnect(ServiceResult.Create(e, StatusCodes.BadSecurityChecksFailed, "Could not verify security on response."));
return false;
}
// check if operation is still available.
WriteOperation operation = null;
if (!m_requests.TryGetValue(requestId, out operation))
{
return false;
}
BufferCollection chunksToProcess = null;
// check for replay attacks.
if (!VerifySequenceNumber(sequenceNumber, "ProcessResponseMessage"))
{
throw new ServiceResultException(StatusCodes.BadSequenceNumberInvalid);
}
try
{
// check for an abort.
if (TcpMessageType.IsAbort(messageType))
{
// get the chunks to process.
chunksToProcess = GetSavedChunks(requestId, messageBody);
// decoder reason.
MemoryStream istrm = new MemoryStream(messageBody.Array, messageBody.Offset, messageBody.Count, false);
BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext);
ServiceResult error = ReadErrorMessageBody(decoder);
decoder.Close();
// report a fault.
operation.Fault(true, error);
return true;
}
// check if it is necessary to wait for more chunks.
if (!TcpMessageType.IsFinal(messageType))
{
SaveIntermediateChunk(requestId, messageBody);
return true;
}
// get the chunks to process.
chunksToProcess = GetSavedChunks(requestId, messageBody);
// get response.
operation.MessageBody = ParseResponse(chunksToProcess);
if (operation.MessageBody == null)
{
operation.Fault(true, StatusCodes.BadStructureMissing, "Could not parse response body.");
return true;
}
// is complete.
operation.Complete(true, 0);
return true;
}
catch (Exception e)
{
operation.Fault(true, e, StatusCodes.BadUnknownResponse, "Unexpected error processing response.");
return true;
}
finally
{
if (chunksToProcess != null)
{
chunksToProcess.Release(BufferManager, "ProcessResponseMessage");
}
}
}
#endregion