private ManagedWebSocket(Stream stream, bool isServer, string subprotocol, TimeSpan keepAliveInterval, int receiveBufferSize, ArraySegment<byte>? receiveBuffer)
{
Debug.Assert(StateUpdateLock != null, $"Expected {nameof(StateUpdateLock)} to be non-null");
Debug.Assert(ReceiveAsyncLock != null, $"Expected {nameof(ReceiveAsyncLock)} to be non-null");
Debug.Assert(StateUpdateLock != ReceiveAsyncLock, "Locks should be different objects");
Debug.Assert(stream != null, $"Expected non-null stream");
Debug.Assert(stream.CanRead, $"Expected readable stream");
Debug.Assert(stream.CanWrite, $"Expected writeable stream");
Debug.Assert(keepAliveInterval == Timeout.InfiniteTimeSpan || keepAliveInterval >= TimeSpan.Zero, $"Invalid keepalive interval: {keepAliveInterval}");
Debug.Assert(receiveBufferSize >= MaxMessageHeaderLength, $"Receive buffer size {receiveBufferSize} is too small");
_stream = stream;
_isServer = isServer;
_subprotocol = subprotocol;
// If we were provided with a buffer to use, use it, as long as it's big enough for our needs, and for simplicity
// as long as we're not supposed to use only a portion of it. If it doesn't meet our criteria, just create a new one.
if (receiveBuffer.HasValue &&
receiveBuffer.Value.Offset == 0 && receiveBuffer.Value.Count == receiveBuffer.Value.Array.Length &&
receiveBuffer.Value.Count >= MaxMessageHeaderLength)
{
_receiveBuffer = receiveBuffer.Value.Array;
}
else
{
_receiveBuffer = new byte[Math.Max(receiveBufferSize, MaxMessageHeaderLength)];
}
// Set up the abort source so that if it's triggered, we transition the instance appropriately.
_abortSource.Token.Register(s =>
{
var thisRef = (ManagedWebSocket)s;
lock (thisRef.StateUpdateLock)
{
WebSocketState state = thisRef._state;
if (state != WebSocketState.Closed && state != WebSocketState.Aborted)
{
thisRef._state = state != WebSocketState.None && state != WebSocketState.Connecting ?
WebSocketState.Aborted :
WebSocketState.Closed;
}
}
}, this);
// Now that we're opened, initiate the keep alive timer to send periodic pings
if (keepAliveInterval > TimeSpan.Zero)
{
_keepAliveTimer = new Timer(s => ((ManagedWebSocket)s).SendKeepAliveFrameAsync(), this, keepAliveInterval, keepAliveInterval);
}
}