in src/Microsoft.Azure.Relay/HybridHttpConnection.cs [423:465]
public override async Task WriteAsync(byte[] array, int offset, int count, CancellationToken cancelToken)
{
RelayEventSource.Log.HybridHttpResponseStreamWrite(this.TrackingContext, count);
this.context.Response.SetReadOnly();
using (var timeoutCancelSource = new CancellationTokenSource(this.WriteTimeout))
using (var linkedCancelSource = CancellationTokenSource.CreateLinkedTokenSource(cancelToken, timeoutCancelSource.Token))
using (await this.asyncLock.LockAsync(linkedCancelSource.Token).ConfigureAwait(false))
{
if (!this.responseCommandSent)
{
FlushReason flushReason;
if (this.connection.rendezvousWebSocket != null)
{
flushReason = FlushReason.RendezvousExists;
}
else
{
int bufferedCount = this.writeBufferStream != null ? (int)this.writeBufferStream.Length : 0;
if (count + bufferedCount <= MaxControlConnectionBodySize)
{
// There's still a chance we might be able to respond over the control connection, accumulate bytes
if (this.writeBufferStream == null)
{
int initialStreamSize = Math.Min(count * 2, MaxControlConnectionBodySize);
this.writeBufferStream = new MemoryStream(initialStreamSize);
this.writeBufferFlushTimer = new Timer((s) => ((ResponseStream)s).OnWriteBufferFlushTimer(), this, WriteBufferFlushTimeout, Timeout.InfiniteTimeSpan);
}
this.writeBufferStream.Write(array, offset, count);
return;
}
flushReason = FlushReason.BufferFull;
}
// FlushCoreAsync will rendezvous, send the responseCommand, and any writeBufferStream bytes
await this.FlushCoreAsync(flushReason, linkedCancelSource.Token).ConfigureAwait(false);
}
var buffer = new ArraySegment<byte>(array, offset, count);
await this.connection.SendBytesOverRendezvousAsync(buffer, WebSocketMessageType.Binary, false, linkedCancelSource.Token).ConfigureAwait(false);
}
}