public StompConnection(Socket socket) { _socket = socket; _processor = new StompFrameProcessor(); _requestProcessingStatus = RequestProcessingStatus.RequestPending; _currentHeaders = new Dictionary <string, string>(); }
private async Task InitializeResponseAsync() { //fire on start. //call reponse starting call back. var startingTask = FireOnStarting(); await startingTask; _requestProcessStatus = RequestProcessingStatus.ResponseStarted; }
private void ProduceStart(bool appCompleted) { if (HasResponseStarted) { return; } _requestProcessingStatus = RequestProcessingStatus.ResponseStarted; var statusBytes = ReasonPhrases.ToStatusBytes(StatusCode, ReasonPhrase); CreateResponseHeader(statusBytes, appCompleted); }
private void ParseRequest(ReadOnlySequence <byte> buffer, out SequencePosition consumed, out SequencePosition examined) { consumed = buffer.Start; examined = buffer.End; switch (_requestProcessingStatus) { case RequestProcessingStatus.RequestPending: if (buffer.IsEmpty) { break; } _requestProcessingStatus = RequestProcessingStatus.ParsingCommand; goto case RequestProcessingStatus.ParsingCommand; case RequestProcessingStatus.ParsingCommand: if (_processor.ProcessCommandLine(new StompRequestHandler(this), buffer, out consumed, out examined)) { buffer = buffer.Slice(consumed, buffer.End); _requestProcessingStatus = RequestProcessingStatus.ParsingHeaders; goto case RequestProcessingStatus.ParsingHeaders; } break; case RequestProcessingStatus.ParsingHeaders: if (_processor.ProcessHeaders(new StompRequestHandler(this), buffer, out consumed, out examined)) { _requestProcessingStatus = RequestProcessingStatus.ParsingBody; goto case RequestProcessingStatus.ParsingBody; } break; case RequestProcessingStatus.ParsingBody: if (_processor.ProcessBody(new StompRequestHandler(this), buffer, out consumed, out examined)) { _requestProcessingStatus = RequestProcessingStatus.RequestPending; } break; } }
public void Reset() { FrameRequestHeaders?.Reset(); FrameResponseHeaders?.Reset(); _onStarting = null; _onCompleted = null; _requestProcessingStatus = RequestProcessingStatus.RequestPending; _keepAlive = false; _autoChunk = false; _applicationException = null; ResetFeatureCollection(); Scheme = null; Method = null; PathBase = null; Path = null; QueryString = null; _httpVersion = HttpVersionType.Unset; StatusCode = 200; ReasonPhrase = null; RemoteIpAddress = RemoteEndPoint?.Address; RemotePort = RemoteEndPoint?.Port ?? 0; LocalIpAddress = LocalEndPoint?.Address; LocalPort = LocalEndPoint?.Port ?? 0; ConnectionIdFeature = ConnectionId; PrepareRequest?.Invoke(this); _manuallySetRequestAbortToken = null; _abortedCts = null; }
protected RequestLineStatus TakeStartLine(SocketInput input) { var scan = input.ConsumingStart(); var consumed = scan; try { // We may hit this when the client has stopped sending data but // the connection hasn't closed yet, and therefore Frame.Stop() // hasn't been called yet. if (scan.Peek() == -1) { return(RequestLineStatus.Empty); } _requestProcessingStatus = RequestProcessingStatus.RequestStarted; string method; var begin = scan; if (!begin.GetKnownMethod(out method)) { if (scan.Seek(ref _vectorSpaces) == -1) { return(RequestLineStatus.MethodIncomplete); } method = begin.GetAsciiString(scan); if (method == null) { RejectRequest("Missing method."); } // Note: We're not in the fast path any more (GetKnownMethod should have handled any HTTP Method we're aware of) // So we can be a tiny bit slower and more careful here. for (int i = 0; i < method.Length; i++) { if (!IsValidTokenChar(method[i])) { RejectRequest("Invalid method."); } } } else { scan.Skip(method.Length); } scan.Take(); begin = scan; var needDecode = false; var chFound = scan.Seek(ref _vectorSpaces, ref _vectorQuestionMarks, ref _vectorPercentages); if (chFound == -1) { return(RequestLineStatus.TargetIncomplete); } else if (chFound == '%') { needDecode = true; chFound = scan.Seek(ref _vectorSpaces, ref _vectorQuestionMarks); if (chFound == -1) { return(RequestLineStatus.TargetIncomplete); } } var pathBegin = begin; var pathEnd = scan; var queryString = ""; if (chFound == '?') { begin = scan; if (scan.Seek(ref _vectorSpaces) == -1) { return(RequestLineStatus.TargetIncomplete); } queryString = begin.GetAsciiString(scan); } var queryEnd = scan; if (pathBegin.Peek() == ' ') { RejectRequest("Missing request target."); } scan.Take(); begin = scan; if (scan.Seek(ref _vectorCRs) == -1) { return(RequestLineStatus.VersionIncomplete); } string httpVersion; if (!begin.GetKnownVersion(out httpVersion)) { // A slower fallback is necessary since the iterator's PeekLong() method // used in GetKnownVersion() only examines two memory blocks at most. // Although unlikely, it is possible that the 8 bytes forming the version // could be spread out on more than two blocks, if the connection // happens to be unusually slow. httpVersion = begin.GetAsciiString(scan); if (httpVersion == null) { RejectRequest("Missing HTTP version."); } else if (httpVersion != "HTTP/1.0" && httpVersion != "HTTP/1.1") { RejectRequest("Unrecognized HTTP version."); } } scan.Take(); var next = scan.Take(); if (next == -1) { return(RequestLineStatus.Incomplete); } else if (next != '\n') { RejectRequest("Missing LF in request line."); } // URIs are always encoded/escaped to ASCII https://tools.ietf.org/html/rfc3986#page-11 // Multibyte Internationalized Resource Identifiers (IRIs) are first converted to utf8; // then encoded/escaped to ASCII https://www.ietf.org/rfc/rfc3987.txt "Mapping of IRIs to URIs" string requestUrlPath; string rawTarget; if (needDecode) { // Read raw target before mutating memory. rawTarget = pathBegin.GetAsciiString(queryEnd); // URI was encoded, unescape and then parse as utf8 pathEnd = UrlPathDecoder.Unescape(pathBegin, pathEnd); requestUrlPath = pathBegin.GetUtf8String(pathEnd); } else { // URI wasn't encoded, parse as ASCII requestUrlPath = pathBegin.GetAsciiString(pathEnd); if (queryString.Length == 0) { // No need to allocate an extra string if the path didn't need // decoding and there's no query string following it. rawTarget = requestUrlPath; } else { rawTarget = pathBegin.GetAsciiString(queryEnd); } } var normalizedTarget = PathNormalizer.RemoveDotSegments(requestUrlPath); consumed = scan; Method = method; QueryString = queryString; RawTarget = rawTarget; HttpVersion = httpVersion; bool caseMatches; if (RequestUrlStartsWithPathBase(normalizedTarget, out caseMatches)) { PathBase = caseMatches ? _pathBase : normalizedTarget.Substring(0, _pathBase.Length); Path = normalizedTarget.Substring(_pathBase.Length); } else if (rawTarget[0] == '/') // check rawTarget since normalizedTarget can be "" or "/" after dot segment removal { Path = normalizedTarget; } else { Path = string.Empty; PathBase = string.Empty; QueryString = string.Empty; } return(RequestLineStatus.Done); } finally { input.ConsumingComplete(consumed, scan); } }