public override BinaryCommandInfo FindCommandInfo(IAppSession session, byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int left) { left = 0; int lastSegmentOffset = BufferSegments.Count; int searchEndMarkLength = length; this.AddArraySegment(readBuffer, offset, length, isReusableBuffer); if (!m_FoundStart) { var pos = BufferSegments.SearchMark(lastSegmentOffset, length, m_StartMark); if (!pos.HasValue || pos.Value < 0) { return(null); } //Found start mark m_StartPos = pos.Value; m_FoundStart = true; lastSegmentOffset = pos.Value + 2; //The end mark could not exist in this round received data if (lastSegmentOffset + 2 > BufferSegments.Count) { return(null); } searchEndMarkLength = BufferSegments.Count - lastSegmentOffset; } var endPos = BufferSegments.SearchMark(lastSegmentOffset, searchEndMarkLength, m_EndMark); //Haven't found end mark if (!endPos.HasValue || endPos.Value < 0) { return(null); } //Found end mark left = BufferSegments.Count - endPos.Value - 2; var commandData = BufferSegments.ToArrayData(m_StartPos, endPos.Value - m_StartPos + 2); var commandInfo = new BinaryCommandInfo(BitConverter.ToString(commandData, 15, 1), commandData); //Reset state m_FoundStart = false; m_StartPos = -1; BufferSegments.ClearSegements(); return(commandInfo); }
public override WebSocketCommandInfo GetCommandInfo(byte[] readBuffer, int offset, int length, out int left) { left = 0; var prevMatched = m_HeadSeachState.Matched; var result = readBuffer.SearchMark(offset, length, m_HeadSeachState); if (result < 0) { AddArraySegment(readBuffer, offset, length); return(null); } int findLen = result - offset; string handshake = string.Empty; if (this.BufferSegments.Count > 0) { if (findLen > 0) { this.AddArraySegment(readBuffer, offset, findLen); handshake = this.BufferSegments.Decode(Encoding.UTF8); } else { handshake = this.BufferSegments.Decode(Encoding.UTF8, 0, this.BufferSegments.Count - prevMatched); } } else { handshake = Encoding.UTF8.GetString(readBuffer, offset, findLen); } left = length - findLen - (HeaderTerminator.Length - prevMatched); BufferSegments.ClearSegements(); if (!handshake.StartsWith(m_BadRequestPrefix, StringComparison.OrdinalIgnoreCase)) { return(new WebSocketCommandInfo { Key = OpCode.Handshake.ToString(), Text = handshake }); } else { return(new WebSocketCommandInfo { Key = OpCode.BadRequest.ToString(), Text = handshake }); } }
void Reset(bool clearBuffer) { m_Type = null; m_Length = null; m_TempLength = 0; if (clearBuffer) { BufferSegments.ClearSegements(); } }
/// <summary> /// Finds the command. /// "SEND 0008 xg^89W(v" /// Read 10 chars as command name and command data length /// </summary> /// <param name="session">The session.</param> /// <param name="readBuffer">The read buffer.</param> /// <param name="offset">The offset.</param> /// <param name="length">The length.</param> /// <param name="isReusableBuffer">if set to <c>true</c> [is reusable buffer].</param> /// <returns></returns> public override BinaryCommandInfo FindCommandInfo(IAppSession session, byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int left) { left = 0; int leftLength = 10 - this.BufferSegments.Count; if (length < leftLength) { AddArraySegment(readBuffer, offset, length, isReusableBuffer); NextCommandReader = this; return(null); } AddArraySegment(readBuffer, offset, leftLength, isReusableBuffer); string commandName = BufferSegments.Decode(Encoding.ASCII, 0, 4); int commandDataLength = Convert.ToInt32(BufferSegments.Decode(Encoding.ASCII, 5, 4).TrimStart('0')); if (length > leftLength) { int leftDataLength = length - leftLength; if (leftDataLength >= commandDataLength) { byte[] commandData = readBuffer.CloneRange(offset + leftLength, commandDataLength); BufferSegments.ClearSegements(); NextCommandReader = this; var commandInfo = new BinaryCommandInfo(commandName, commandData); //The next commandInfo is comming if (leftDataLength > commandDataLength) { left = leftDataLength - commandDataLength; } return(commandInfo); } else// if (leftDataLength < commandDataLength) { //Clear previous cached header data BufferSegments.ClearSegements(); //Save left data part AddArraySegment(readBuffer, offset + leftLength, length - leftLength, isReusableBuffer); NextCommandReader = GetMyCommandDataReader(commandName, commandDataLength); return(null); } } else//length == leftLength { BufferSegments.ClearSegements(); NextCommandReader = GetMyCommandDataReader(commandName, commandDataLength); return(null); } }
public override BinaryRequestInfo Filter(IAppSession <BinaryRequestInfo> session, byte[] readBuffer, int offset, int length, bool toBeCopied, out int left) { left = 0; int leftLength = 6 - this.BufferSegments.Count; if (length < leftLength) { AddArraySegment(readBuffer, offset, length, toBeCopied); NextRequestFilter = this; return(null); } AddArraySegment(readBuffer, offset, leftLength, toBeCopied); string commandName = BufferSegments.Decode(Encoding.ASCII, 0, 4); int commandDataLength = (int)BufferSegments[4] * 256 + (int)BufferSegments[5]; if (length > leftLength) { int leftDataLength = length - leftLength; if (leftDataLength >= commandDataLength) { byte[] commandData = readBuffer.CloneRange(offset + leftLength, commandDataLength); BufferSegments.ClearSegements(); NextRequestFilter = this; var requestInfo = new BinaryRequestInfo(commandName, commandData); //The next requestInfo is comming if (leftDataLength > commandDataLength) { left = leftDataLength - commandDataLength; } return(requestInfo); } else// if (leftDataLength < commandDataLength) { //Clear previous cached header data BufferSegments.ClearSegements(); //Save left data part AddArraySegment(readBuffer, offset + leftLength, length - leftLength, toBeCopied); NextRequestFilter = GetMyCommandDataReader(commandName, commandDataLength); return(null); } } else { NextRequestFilter = GetMyCommandDataReader(commandName, commandDataLength); return(null); } }
public override BinaryCommandInfo FindCommandInfo(IAppSession session, byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int left) { left = 0; this.AddArraySegment(readBuffer, offset, length, isReusableBuffer); if (length < 14) { BufferSegments.ClearSegements(); return(null); } var commandData = BufferSegments.ToArrayData(0, length); BufferSegments.ClearSegements(); return(new BinaryCommandInfo("WMDEVICE", commandData)); }
public override IWebSocketFragment Filter(byte[] readBuffer, int offset, int length, bool isReusableBuffer, out int rest) { var webSocketSession = Session; int total = BufferSegments.Count + length; if (total == SecKey3Len) { byte[] key = new byte[SecKey3Len]; BufferSegments.CopyTo(key); Array.Copy(readBuffer, offset, key, BufferSegments.Count, length); webSocketSession.Items[WebSocketConstant.SecWebSocketKey3] = key; BufferSegments.ClearSegements(); rest = 0; if (Handshake(webSocketSession.AppServer.WebSocketProtocolProcessor, webSocketSession)) { return(HandshakeRequestInfo); } } else if (total > SecKey3Len) { byte[] key = new byte[8]; BufferSegments.CopyTo(key); Array.Copy(readBuffer, offset, key, BufferSegments.Count, SecKey3Len - BufferSegments.Count); webSocketSession.Items[WebSocketConstant.SecWebSocketKey3] = key; BufferSegments.ClearSegements(); rest = total - SecKey3Len; if (Handshake(webSocketSession.AppServer.WebSocketProtocolProcessor, webSocketSession)) { return(HandshakeRequestInfo); } } else { AddArraySegment(readBuffer, offset, length, isReusableBuffer); rest = 0; NextReceiveFilter = this; return(null); } return(null); }
/// <summary> /// Clears the buffer segments. /// </summary> protected void ClearBufferSegments() { BufferSegments.ClearSegements(); }
public override WebSocketCommandInfo GetCommandInfo(byte[] readBuffer, int offset, int length, out int left) { left = 0; // prevMatched is needed because handshake may have come // in a number of segments, and the HeaderTerminator that // we're looking for might lie across previous segments // and `readBuffer`. // // More precisely, prevMatched > 0 if and only if the last // byte(s) at end of the previous segment **started like** // an incomplete HeaderTerminator that **may or may not** // be continued and completed in current `readBuffer`. -- // fidergo-stephane-gourichon var prevMatched = m_HeadSeachState.Matched; // At this point in code **we don't know yet** if the // `prevMatched` bytes that match the `HeaderTerminator` // at end of previous segment are part of a **full match** // (in this case the value of `prevMatched` is useful) or // just a **partial** (in that cas the value of // `prevMatched` is irrelevant). var result = readBuffer.SearchMark(offset, length, m_HeadSeachState); if (result < 0) { // We've not found the HeaderTerminator yet. We'll be // called again when more data arrives. -- // fidergo-stephane-gourichon AddArraySegment(readBuffer, offset, length); return(null); } // We've found the HeaderTerminator. All might be in // readBuffer, or handshake might be cut across the last // segment, or just the HeaderTerminator might be in // readBuffer or even cut across. We must handle all // those cases. -- fidergo-stephane-gourichon int findLen = result - offset; string handshake = string.Empty; if (this.BufferSegments.Count > 0) { if (findLen > 0) { // In this code path we know that the handshake // was cut across at least previous segments and // `readBuffer`. In other words, // `readBuffer[offset]` starts with at least one // byte that belongs to the handshake proper // (excluding `HeaderTerminator`). So, we add // those bytes and extract the handshake. this.AddArraySegment(readBuffer, offset, findLen); handshake = this.BufferSegments.Decode(Encoding.UTF8); // Now, we need to correct `prevMatched`. Indeed, // in this code path, any byte(s) matched at end // of previous segment were not part of an actual // HeaderTerminator cut across. If // `prevMatched`>0, such byte(s) was / were a // partial match that `readBuffer` content // disproved. // // So, basically, there were actually zero bytes // of the actual `HeaderTerminator` match in // previous segment. We reflect that by setting // prevMatched = 0. -- fidergo-stephane-gourichon prevMatched = 0; // If we did not set prevMatched to zero, `left` // would be too big and our read pointer would not // advance enough, causing desynchronization in WS // protocol decoding, failure to recognize further // messages, server closing connection for lack of // reply to ping. -- fidergo-stephane-gourichon } else { // The handshake was actually fully inside the // previous segment. That segment possibly ended // with `prevMatch` bytes of the // `HeaderTerminator` that we have to shave // off. -- fidergo-stephane-gourichon handshake = this.BufferSegments.Decode(Encoding.UTF8, 0, this.BufferSegments.Count - prevMatched); } } else { // In this code path, there was no previous segment. // Everything is in `readBuffer`. handshake = Encoding.UTF8.GetString(readBuffer, offset, findLen); // I'm nearly sure prevMatched is always zero already, // if reset between invocations (see below // `m_HeadSeachState.Matched = 0`). I'm definitely // sure it should be zero here. An assert would be // good. As a fallback set it. -- // fidergo-stephane-gourichon prevMatched = 0; } // We must tell caller how many bytes are left, with a // formula that works in all cases. // It works if prevMatched reflects actual match, not // partial match, as set to zero above. -- // fidergo-stephane-gourichon left = length - findLen - (HeaderTerminator.Length - prevMatched); // Rationale: left bytes are all bytes minus bytes // consumed. We consume the part of the handshake that's // in `readBuffer`, which is `findLen` bytes. We also // consume the part of the `HeaderTerminator` that is in // `readBuffer`, which is `(HeaderTerminator.Length - // prevMatched)` bytes. BufferSegments.ClearSegements(); // In case the object is reused, reset search state. I'm // nearly sure this is always zero already. An assert // would be good. As a fallback set it. -- // fidergo-stephane-gourichon m_HeadSeachState.Matched = 0; if (!handshake.StartsWith(m_BadRequestPrefix, StringComparison.OrdinalIgnoreCase)) { return(new WebSocketCommandInfo { Key = OpCode.Handshake.ToString(), Text = handshake }); } else { return(new WebSocketCommandInfo { Key = OpCode.BadRequest.ToString(), Text = handshake }); } }