private bool ProcessHelloMessage(uint messageType, ArraySegment<byte> messageChunk)
{
// validate the channel state.
if (State != TcpChannelState.Connecting)
{
ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "Client sent an unexpected Hello message.");
return false;
}
try
{
MemoryStream istrm = new MemoryStream(messageChunk.Array, messageChunk.Offset, messageChunk.Count, false);
BinaryDecoder decoder = new BinaryDecoder(istrm, Quotas.MessageContext);
istrm.Seek(TcpMessageLimits.MessageTypeAndSize, SeekOrigin.Current);
// read requested buffer sizes.
uint protocolVersion = decoder.ReadUInt32(null);
uint receiveBufferSize = decoder.ReadUInt32(null);
uint sendBufferSize = decoder.ReadUInt32(null);
uint maxMessageSize = decoder.ReadUInt32(null);
uint maxChunkCount = decoder.ReadUInt32(null);
// read the endpoint url.
int length = decoder.ReadInt32(null);
if (length > 0)
{
if (length > TcpMessageLimits.MaxEndpointUrlLength)
{
ForceChannelFault(StatusCodes.BadTcpEndpointUrlInvalid);
return false;
}
byte[] endpointUrl = new byte[length];
for (int ii = 0; ii < endpointUrl.Length; ii++)
{
endpointUrl[ii] = decoder.ReadByte(null);
}
if (!SetEndpointUrl(new UTF8Encoding().GetString(endpointUrl)))
{
ForceChannelFault(StatusCodes.BadTcpEndpointUrlInvalid);
return false;
}
}
decoder.Close();
// update receive buffer size.
if (receiveBufferSize < ReceiveBufferSize)
{
ReceiveBufferSize = (int)receiveBufferSize;
}
if (ReceiveBufferSize < TcpMessageLimits.MinBufferSize)
{
ReceiveBufferSize = TcpMessageLimits.MinBufferSize;
}
// update send buffer size.
if (sendBufferSize < SendBufferSize)
{
SendBufferSize = (int)sendBufferSize;
}
if (SendBufferSize < TcpMessageLimits.MinBufferSize)
{
SendBufferSize = TcpMessageLimits.MinBufferSize;
}
// update the max message size.
if (maxMessageSize > 0 && maxMessageSize < MaxResponseMessageSize)
{
MaxResponseMessageSize = (int)maxMessageSize;
}
if (MaxResponseMessageSize < SendBufferSize)
{
MaxResponseMessageSize = SendBufferSize;
}
// update the max chunk count.
if (maxChunkCount > 0 && maxChunkCount < MaxResponseChunkCount)
{
MaxResponseChunkCount = (int)maxChunkCount;
}
// send acknowledge.
byte[] buffer = BufferManager.TakeBuffer(SendBufferSize, "ProcessHelloMessage");
try
{
MemoryStream ostrm = new MemoryStream(buffer, 0, SendBufferSize);
BinaryEncoder encoder = new BinaryEncoder(ostrm, Quotas.MessageContext);
encoder.WriteUInt32(null, TcpMessageType.Acknowledge);
encoder.WriteUInt32(null, 0);
encoder.WriteUInt32(null, 0); // ProtocolVersion
encoder.WriteUInt32(null, (uint)ReceiveBufferSize);
encoder.WriteUInt32(null, (uint)SendBufferSize);
encoder.WriteUInt32(null, (uint)MaxRequestMessageSize);
encoder.WriteUInt32(null, (uint)MaxRequestChunkCount);
int size = encoder.Close();
UpdateMessageSize(buffer, 0, size);
// now ready for the open or bind request.
State = TcpChannelState.Opening;
BeginWriteMessage(new ArraySegment<byte>(buffer, 0, size), Int32.MaxValue, null);
buffer = null;
}
finally
{
if (buffer != null)
{
BufferManager.ReturnBuffer(buffer, "ProcessHelloMessage");
}
}
}
catch (Exception e)
{
ForceChannelFault(e, StatusCodes.BadTcpInternalError, "Unexpected error while processing a Hello message.");
}
return false;
}