private bool ProcessRequestMessage(uint messageType, ArraySegment<byte> messageChunk)
{
// validate the channel state.
if (State != TcpChannelState.Open)
{
ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "Client sent an unexpected request message.");
return false;
}
// validate security on the message.
TcpChannelToken token = null;
uint requestId = 0;
uint sequenceNumber = 0;
ArraySegment<byte> messageBody;
try
{
messageBody = ReadSymmetricMessage(messageChunk, true, out token, out requestId, out sequenceNumber);
// check for replay attacks.
if (!VerifySequenceNumber(sequenceNumber, "ProcessRequestMessage"))
{
throw new ServiceResultException(StatusCodes.BadSequenceNumberInvalid);
}
if (token == CurrentToken && PreviousToken != null && !PreviousToken.Expired)
{
Utils.Trace("Server Revoked Token. ChannelId={1}, TokenId={0}", PreviousToken.TokenId, PreviousToken.ChannelId, DateTime.UtcNow);
PreviousToken.Lifetime = 0;
}
}
catch (Exception e)
{
Utils.Trace("Could not verify security on incoming request.");
ForceChannelFault(e, StatusCodes.BadSecurityChecksFailed, "Could not verify security on incoming request.");
return false;
}
BufferCollection chunksToProcess = null;
try
{
// check for an abort.
if (TcpMessageType.IsAbort(messageType))
{
Utils.Trace("Request was aborted.");
chunksToProcess = GetSavedChunks(requestId, messageBody);
return true;
}
// check if it is necessary to wait for more chunks.
if (!TcpMessageType.IsFinal(messageType))
{
SaveIntermediateChunk(requestId, messageBody);
return true;
}
// Utils.Trace("Channel {0}: ProcessRequestMessage {1}", ChannelId, requestId);
// get the chunks to process.
chunksToProcess = GetSavedChunks(requestId, messageBody);
// decode the request.
IServiceRequest request = BinaryDecoder.DecodeMessage(new ArraySegmentStream(chunksToProcess), null, Quotas.MessageContext) as IServiceRequest;
if (request == null)
{
SendServiceFault(token, requestId, ServiceResult.Create(StatusCodes.BadStructureMissing, "Could not parse request body."));
return true;
}
// ensure that only discovery requests come through unsecured.
if (DiscoveryOnly)
{
if (!(request is GetEndpointsRequest || request is FindServersRequest))
{
SendServiceFault(token, requestId, ServiceResult.Create(StatusCodes.BadSecurityPolicyRejected, "Channel can only be used for discovery."));
return true;
}
}
// hand the request to the server.
if (m_RequestReceived != null)
{
m_RequestReceived(this, requestId, request);
}
return true;
}
catch (Exception e)
{
Utils.Trace(e, "Unexpected error processing request.");
SendServiceFault(token, requestId, ServiceResult.Create(e, StatusCodes.BadTcpInternalError, "Unexpected error processing request."));
return false;
}
finally
{
if (chunksToProcess != null)
{
chunksToProcess.Release(BufferManager, "ProcessRequestMessage");
}
}
}
#endregion