public void ReadLineTest() { WriteTestData("abcd\r\nefgh\nijkl\r\n"); RewindStream(); var f = Reader.ReadLine(); f.GetCompletionEvent().Wait(); Assert.AreEqual("abcd", f.Result); f = Reader.ReadLine(); f.GetCompletionEvent().Wait(); Assert.AreEqual("efgh", f.Result); f = Reader.ReadLine(); f.GetCompletionEvent().Wait(); Assert.AreEqual("ijkl", f.Result); f = Reader.ReadLine(); f.GetCompletionEvent().Wait(); Assert.AreEqual("", f.Result); f = Reader.ReadLine(); f.GetCompletionEvent().Wait(); Assert.AreEqual(null, f.Result); }
static IEnumerator<object> ReceiveTask (SocketDataAdapter adapter) { var input = new AsyncTextReader(adapter, Encoding.ASCII); int i = 0; string message = null; Reader = input; while (true) { var f = input.ReadLine(); yield return f; if (!f.GetResult(out message)) throw new DisconnectedException(); if (message == null) throw new DisconnectedException(); else i += 1; if ((i % 1000) == 0) Console.WriteLine("Recieved: {0}", i); } }
public void TestReadingAllLines() { string[] expectedLines = System.IO.File.ReadAllLines(Stream.Name); var lines = new List <string>(); IFuture f; while (true) { f = Reader.ReadLine(); f.GetCompletionEvent().Wait(); var line = f.Result as string; if (line == null) { break; } lines.Add(line); } Assert.AreEqual(expectedLines, lines.ToArray()); }
private IEnumerator<object> RequestTask(ListenerContext context, SocketDataAdapter adapter) { var startedWhen = DateTime.UtcNow; bool successful = false; try { const int headerBufferSize = 1024 * 32; const int bodyBufferSize = 1024 * 128; const double requestLineTimeout = 5; // RFC2616: // Words of *TEXT MAY contain characters from character sets other than ISO-8859-1 [22] // only when encoded according to the rules of RFC 2047 [14]. Encoding headerEncoding; try { headerEncoding = Encoding.GetEncoding("ISO-8859-1"); } catch { headerEncoding = Encoding.ASCII; } Request request; RequestBody body; HeaderCollection headers; long bodyBytesRead = 0; long? expectedBodyLength = null; var reader = new AsyncTextReader(adapter, headerEncoding, headerBufferSize, false); string requestLineText; while (true) { var fRequestLine = reader.ReadLine(); var fRequestOrTimeout = Scheduler.Start(new WaitWithTimeout(fRequestLine, requestLineTimeout)); yield return fRequestOrTimeout; if (fRequestOrTimeout.Failed) { if (!(fRequestOrTimeout.Error is TimeoutException)) OnRequestError(fRequestOrTimeout.Error); yield break; } if (fRequestLine.Failed) { if (!(fRequestLine.Error is SocketDisconnectedException)) OnRequestError(fRequestLine.Error); yield break; } requestLineText = fRequestLine.Result; // RFC2616: // In the interest of robustness, servers SHOULD ignore any empty line(s) received where a // Request-Line is expected. In other words, if the server is reading the protocol stream // at the beginning of a message and receives a CRLF first, it should ignore the CRLF. if ((requestLineText != null) && (requestLineText.Trim().Length == 0)) continue; break; } var requestLineParsed = DateTime.UtcNow; headers = new HeaderCollection(); while (true) { var fHeaderLine = reader.ReadLine(); yield return fHeaderLine; if (String.IsNullOrWhiteSpace(fHeaderLine.Result)) break; headers.Add(new Header(fHeaderLine.Result)); } var headersParsed = DateTime.UtcNow; var expectHeader = (headers.GetValue("Expect") ?? "").ToLowerInvariant(); var expectsContinue = expectHeader.Contains("100-continue"); string hostName; if (headers.Contains("Host")) { hostName = String.Format("http://{0}", headers["Host"].Value); } else { var lep = (IPEndPoint)adapter.Socket.LocalEndPoint; hostName = String.Format("http://{0}:{1}", lep.Address, lep.Port); } var requestLine = new RequestLine(hostName, requestLineText); var remainingBytes = reader.DisposeAndGetRemainingBytes(); bodyBytesRead += remainingBytes.Count; var connectionHeader = (headers.GetValue("Connection") ?? "").ToLowerInvariant(); var shouldKeepAlive = ((requestLine.Version == "1.1") || connectionHeader.Contains("keep-alive")) && !connectionHeader.Contains("close"); if (headers.Contains("Content-Length")) expectedBodyLength = long.Parse(headers["Content-Length"].Value); body = new RequestBody(remainingBytes, expectedBodyLength); if (expectsContinue) yield return adapter.Write(Continue100, 0, Continue100.Length); request = new Request( this, adapter, shouldKeepAlive, requestLine, headers, body ); IncomingRequests.Enqueue(request); var requestEnqueued = DateTime.UtcNow; DateTime? requestBodyRead = null; // FIXME: I think it's technically accepted to send a body without a content-length, but // it seems to be impossible to make that work right. if (expectedBodyLength.HasValue) { using (var bodyBuffer = BufferPool<byte>.Allocate(bodyBufferSize)) while (bodyBytesRead < expectedBodyLength.Value) { long bytesToRead = Math.Min(expectedBodyLength.Value - bodyBytesRead, bodyBufferSize); if (bytesToRead <= 0) break; var fBytesRead = adapter.Read(bodyBuffer.Data, 0, (int)bytesToRead); yield return fBytesRead; if (fBytesRead.Failed) { if (fBytesRead.Error is SocketDisconnectedException) break; body.Failed(fBytesRead.Error); OnRequestError(fBytesRead.Error); yield break; } var bytesRead = fBytesRead.Result; bodyBytesRead += bytesRead; body.Append(bodyBuffer.Data, 0, bytesRead); } requestBodyRead = DateTime.UtcNow; } body.Finish(); successful = true; request.Timing = new Request.TimingData { Line = (requestLineParsed - startedWhen), Headers = (headersParsed - requestLineParsed), Queue = (requestEnqueued - headersParsed), Body = (requestBodyRead - requestEnqueued) }; } finally { if (!successful) adapter.Dispose(); } }
static IEnumerator<object> PeerTask (TcpClient client, Peer peer) { var adapter = new SocketDataAdapter(client.Client, true); var input = new AsyncTextReader(adapter, Encoding.ASCII); var output = new AsyncTextWriter(adapter, Encoding.ASCII); adapter.ThrowOnDisconnect = false; adapter.ThrowOnFullSendBuffer = false; output.AutoFlush = true; peer.Input = input; peer.Output = output; yield return output.WriteLine("Welcome! Please enter your name."); string name = null; yield return input.ReadLine().Bind(() => name); if (name == null) { PeerDisconnected(peer); yield break; } peer.Name = name; PeerConnected(peer); yield return output.Write(VT100.EraseScreen); string nextLine = null; while (peer.Connected) { var f = input.ReadLine(); yield return f; if (!f.GetResult(out nextLine) || nextLine == null) { PeerDisconnected(peer); yield break; } if (nextLine.Length > 0) DispatchNewMessage(peer, nextLine); } }
IEnumerator<object> SearchInFiles(SearchQuery search, BlockingQueue<string> filenames, IFuture completionFuture) { var searchedFiles = new List<string>(); var buffer = new List<SearchResult>(); var sb = new StringBuilder(); int numFiles = 0; using (Finally.Do(() => { SetSearchResults(buffer); lblStatus.Text = String.Format("{0} result(s) found.", buffer.Count); pbProgress.Style = ProgressBarStyle.Continuous; pbProgress.Value = 0; })) while (filenames.Count > 0 || !completionFuture.Completed) { var f = filenames.Dequeue(); yield return f; var filename = f.Result as string; if (filename == null) continue; if (searchedFiles.Contains(filename)) continue; if (PendingSearchQuery != null) break; searchedFiles.Add(filename); int lineNumber = 0; var lineBuffer = new LineEntry[3]; var insertResult = (Action)(() => { var item = new SearchResult(); item.Filename = filename; item.LineNumber = lineBuffer[1].LineNumber; sb.Remove(0, sb.Length); for (int i = 0; i < 3; i++) { if (lineBuffer[i].Text != null) { var line = lineBuffer[i].Text; if (line.Length > 512) line = line.Substring(0, 512); sb.Append(line); } if (i < 2) sb.Append("\r\n"); } item.Context = sb.ToString(); buffer.Add(item); if ((buffer.Count % 250 == 0) || ((buffer.Count < 50) && (buffer.Count % 5 == 1))) SetSearchResults(buffer); }); var stepSearch = (Action)(() => { string currentLine = lineBuffer[1].Text; if ((currentLine != null) && search.Regex.IsMatch(currentLine)) insertResult(); }); var insertLine = (Action<LineEntry>)((line) => { lineBuffer[0] = lineBuffer[1]; lineBuffer[1] = lineBuffer[2]; lineBuffer[2] = line; stepSearch(); }); numFiles += 1; if (numFiles % 50 == 0) { lblStatus.Text = String.Format("Scanning '{0}'...", filename); if (completionFuture.Completed) { int totalNumFiles = numFiles + filenames.Count; int progress = (numFiles * 1000 / totalNumFiles); if (pbProgress.Value != progress) pbProgress.Value = progress; if (pbProgress.Style != ProgressBarStyle.Continuous) pbProgress.Style = ProgressBarStyle.Continuous; } } FileDataAdapter adapter = null; try { adapter = new FileDataAdapter(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read); } catch { if (adapter != null) adapter.Dispose(); continue; } using (adapter) { var fEncoding = Future.RunInThread( () => DetectEncoding(adapter.BaseStream) ); yield return fEncoding; Future<string> thisLine = null, nextLine = null; using (var reader = new AsyncTextReader(adapter, fEncoding.Result, SearchBufferSize)) while (true) { thisLine = nextLine; if (thisLine != null) yield return thisLine; nextLine = reader.ReadLine(); if (thisLine == null) continue; lineNumber += 1; string line = thisLine.Result; insertLine(new LineEntry { Text = line, LineNumber = lineNumber }); if (line == null) break; if (PendingSearchQuery != null) break; if (lineNumber % 10000 == 5000) { var newStatus = String.Format("Scanning '{0}'... (line {1})", filename, lineNumber); if (lblStatus.Text != newStatus) lblStatus.Text = newStatus; } } } } }