private async void SendKeepAliveAsync()
{
// Check concurrent writes, pings & pongs, or closes
if (!_writeLock.Wait(0))
{
// Sending real data is better than a ping, discard it.
return;
}
try
{
if (State == WebSocketState.CloseSent || State >= WebSocketState.Closed)
{
_keepAliveTimer.Dispose();
return;
}
int mask = GetNextMask();
FrameHeader frameHeader = new FrameHeader(true, Constants.OpCodes.PingFrame, _maskOutput, mask, PingBuffer.Length);
ArraySegment<byte> headerSegment = frameHeader.Buffer;
// TODO: CancelationToken / timeout?
if (_maskOutput && mask != 0)
{
byte[] maskedFrame = Utilities.MergeAndMask(mask, headerSegment, new ArraySegment<byte>(PingBuffer));
await _stream.WriteAsync(maskedFrame, 0, maskedFrame.Length);
}
else
{
await _stream.WriteAsync(headerSegment.Array, headerSegment.Offset, headerSegment.Count);
await _stream.WriteAsync(PingBuffer, 0, PingBuffer.Length);
}
}
catch (Exception)
{
// TODO: Log exception, this is a background thread.
// Shut down, we must be in a faulted state;
Abort();
}
finally
{
_writeLock.Release();
}
}