public Write ( ArraySegment |
||
buffer | ArraySegment |
|
callback | Action |
|
state | object | |
immediate | bool | |
socketShutdownSend | bool | |
socketDisconnect | bool | |
return | void |
public void ProduceStart() { if (_resultStarted) { return; } _resultStarted = true; FireOnSendingHeaders(); _headersSent = true; var status = ReasonPhrases.ToStatus(StatusCode, ReasonPhrase); var responseHeader = CreateResponseHeader(status, ResponseHeaders); SocketOutput.Write( responseHeader.Item1, (error, x) => { if (error != null) { Trace.WriteLine("ProduceStart " + error.ToString()); } ((IDisposable)x).Dispose(); }, responseHeader.Item2); }
public void ProduceContinue() { if (_responseStarted) { return; } StringValues expect; if (_httpVersion == HttpVersionType.Http1_1 && RequestHeaders.TryGetValue("Expect", out expect) && (expect.FirstOrDefault() ?? "").Equals("100-continue", StringComparison.OrdinalIgnoreCase)) { SocketOutput.Write(_continueBytes); } }
public void Write(ArraySegment <byte> data) { ProduceStartAndFireOnStarting(immediate: false).GetAwaiter().GetResult(); if (_autoChunk) { if (data.Count == 0) { return; } WriteChunked(data); } else { SocketOutput.Write(data, immediate: true); } }
public void ProduceStart(bool immediate = true, bool appCompleted = false) { // ProduceStart shouldn't no-op in the future just b/c FireOnStarting throws. if (_responseStarted) { return; } FireOnStarting(); _responseStarted = true; var status = ReasonPhrases.ToStatus(StatusCode, ReasonPhrase); var responseHeader = CreateResponseHeader(status, appCompleted); SocketOutput.Write(responseHeader.Item1, immediate: immediate); responseHeader.Item2.Dispose(); }
public void Write(ArraySegment <byte> data) { ProduceStart(immediate: false); if (_autoChunk) { if (data.Count == 0) { return; } WriteChunked(data); } else { SocketOutput.Write(data, immediate: true); } }
public void CanWrite1MB() { // This test was added because when initially implementing write-behind buffering in // SocketOutput, the write callback would never be invoked for writes larger than // _maxBytesPreCompleted even after the write actually completed. // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { triggerCompleted(0); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new KestrelTrace(new TestKestrelTrace())); var trace = new KestrelTrace(new TestKestrelTrace()); var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace); // I doubt _maxBytesPreCompleted will ever be over a MB. If it is, we should change this test. var bufferSize = 1048576; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); Action<Exception, object, bool> onCompleted = (ex, state, calledInline) => { Assert.Null(ex); Assert.Null(state); completedWh.Set(); }; // Act socketOutput.Write(buffer, onCompleted, null); // Assert Assert.True(completedWh.Wait(1000)); } }
public void ProduceContinue() { if (_resultStarted) { return; } string[] expect; if (HttpVersion.Equals("HTTP/1.1") && RequestHeaders.TryGetValue("Expect", out expect) && (expect.FirstOrDefault() ?? "").Equals("100-continue", StringComparison.OrdinalIgnoreCase)) { SocketOutput.Write( new ArraySegment <byte>(_continueBytes, 0, _continueBytes.Length), (error, _) => { if (error != null) { Trace.WriteLine("ProduceContinue " + error.ToString()); } }, null); } }
private void WriteChunkedResponseSuffix() { SocketOutput.Write(_endChunkedResponseBytes, immediate: true); }
private void WriteChunked(ArraySegment <byte> data) { SocketOutput.Write(BeginChunkBytes(data.Count), immediate: false); SocketOutput.Write(data, immediate: false); SocketOutput.Write(_endChunkBytes, immediate: true); }
public void Flush() { ProduceStartAndFireOnStarting(immediate: false).GetAwaiter().GetResult(); SocketOutput.Write(_emptyData, immediate: true); }
public void WritesDontCompleteImmediatelyWhenTooManyBytesAreAlreadyPreCompleted() { // This should match _maxBytesPreCompleted in SocketOutput var maxBytesPreCompleted = 65536; var completeQueue = new Queue<Action<int>>(); // Arrange var mockLibuv = new MockLibuv { OnWrite = (socket, buffers, triggerCompleted) => { completeQueue.Enqueue(triggerCompleted); return 0; } }; using (var kestrelEngine = new KestrelEngine(mockLibuv, new TestServiceContext())) { kestrelEngine.Start(count: 1); var kestrelThread = kestrelEngine.Threads[0]; var socket = new MockSocket(kestrelThread.Loop.ThreadId, new KestrelTrace(new TestKestrelTrace())); var trace = new KestrelTrace(new TestKestrelTrace()); var socketOutput = new SocketOutput(kestrelThread, socket, 0, trace); var bufferSize = maxBytesPreCompleted; var buffer = new ArraySegment<byte>(new byte[bufferSize], 0, bufferSize); var completedWh = new ManualResetEventSlim(); Action<Exception, object, bool> onCompleted = (ex, state, calledInline) => { Assert.Null(ex); Assert.Null(state); completedWh.Set(); }; // Act socketOutput.Write(buffer, onCompleted, null); // Assert // The first write should pre-complete since it is <= _maxBytesPreCompleted. Assert.True(completedWh.Wait(1000)); // Arrange completedWh.Reset(); // Act socketOutput.Write(buffer, onCompleted, null); // Assert // Too many bytes are already pre-completed for the second write to pre-complete. Assert.False(completedWh.Wait(1000)); // Act completeQueue.Dequeue()(0); // Assert // Finishing the first write should allow the second write to pre-complete. Assert.True(completedWh.Wait(1000)); } }
public void Flush() { ProduceStart(immediate: false); SocketOutput.Write(_emptyData, immediate: true); }
public void Write(ArraySegment <byte> data, Action <Exception, object> callback, object state) { ProduceStart(); SocketOutput.Write(data, callback, state); }