-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
1,070 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
using System; | ||
using SuperSocket.Common; | ||
using SuperSocket.SocketBase.Protocol; | ||
|
||
namespace SuperSocket.SocketEngine.Protocol | ||
{ | ||
/// <summary> | ||
/// ReceiveFilter for the protocol that each request has bengin and end mark | ||
/// </summary> | ||
/// <typeparam name="TRequestInfo">The type of the request info.</typeparam> | ||
public abstract class BeginEndMarkReceiveFilter<TRequestInfo> : ReceiveFilterBase<TRequestInfo> | ||
where TRequestInfo : IRequestInfo | ||
{ | ||
private readonly SearchMarkState<byte> m_BeginSearchState; | ||
private readonly SearchMarkState<byte> m_EndSearchState; | ||
|
||
private bool m_FoundBegin = false; | ||
|
||
/// <summary> | ||
/// Null request info | ||
/// </summary> | ||
protected TRequestInfo NullRequestInfo = default(TRequestInfo); | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BeginEndMarkReceiveFilter<TRequestInfo>"/> class. | ||
/// </summary> | ||
/// <param name="beginMark">The begin mark.</param> | ||
/// <param name="endMark">The end mark.</param> | ||
protected BeginEndMarkReceiveFilter(byte[] beginMark, byte[] endMark) | ||
{ | ||
m_BeginSearchState = new SearchMarkState<byte>(beginMark); | ||
m_EndSearchState = new SearchMarkState<byte>(endMark); | ||
} | ||
|
||
/// <summary> | ||
/// Filters the specified session. | ||
/// </summary> | ||
/// <param name="readBuffer">The read buffer.</param> | ||
/// <param name="offset">The offset.</param> | ||
/// <param name="length">The length.</param> | ||
/// <param name="toBeCopied">if set to <c>true</c> [to be copied].</param> | ||
/// <param name="rest">The rest.</param> | ||
/// <returns></returns> | ||
public override TRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest) | ||
{ | ||
rest = 0; | ||
|
||
int searchEndMarkOffset; | ||
int searchEndMarkLength; | ||
|
||
//prev macthed begin mark length | ||
int prevMatched = 0; | ||
int totalParsed = 0; | ||
|
||
if (!m_FoundBegin) | ||
{ | ||
prevMatched = m_BeginSearchState.Matched; | ||
int pos = readBuffer.SearchMark(offset, length, m_BeginSearchState, out totalParsed); | ||
|
||
if (pos < 0) | ||
{ | ||
//Don't cache invalid data | ||
if (prevMatched > 0 || (m_BeginSearchState.Matched > 0 && length != m_BeginSearchState.Matched)) | ||
{ | ||
State = FilterState.Error; | ||
return NullRequestInfo; | ||
} | ||
|
||
return NullRequestInfo; | ||
} | ||
else //Found the matched begin mark | ||
{ | ||
//But not at the beginning | ||
if(pos != offset) | ||
{ | ||
State = FilterState.Error; | ||
return NullRequestInfo; | ||
} | ||
} | ||
|
||
//Found start mark | ||
m_FoundBegin = true; | ||
|
||
searchEndMarkOffset = pos + m_BeginSearchState.Mark.Length - prevMatched; | ||
|
||
//This block only contain (part of)begin mark | ||
if (offset + length <= searchEndMarkOffset) | ||
{ | ||
AddArraySegment(m_BeginSearchState.Mark, 0, m_BeginSearchState.Mark.Length, false); | ||
return NullRequestInfo; | ||
} | ||
|
||
searchEndMarkLength = offset + length - searchEndMarkOffset; | ||
} | ||
else//Already found begin mark | ||
{ | ||
searchEndMarkOffset = offset; | ||
searchEndMarkLength = length; | ||
} | ||
|
||
while (true) | ||
{ | ||
var prevEndMarkMatched = m_EndSearchState.Matched; | ||
var parsedLen = 0; | ||
var endPos = readBuffer.SearchMark(searchEndMarkOffset, searchEndMarkLength, m_EndSearchState, out parsedLen); | ||
|
||
//Haven't found end mark | ||
if (endPos < 0) | ||
{ | ||
rest = 0; | ||
if(prevMatched > 0)//Also cache the prev matched begin mark | ||
AddArraySegment(m_BeginSearchState.Mark, 0, prevMatched, false); | ||
AddArraySegment(readBuffer, offset, length, toBeCopied); | ||
return NullRequestInfo; | ||
} | ||
|
||
totalParsed += parsedLen; | ||
rest = length - totalParsed; | ||
|
||
byte[] commandData = new byte[BufferSegments.Count + prevMatched + totalParsed]; | ||
|
||
if (BufferSegments.Count > 0) | ||
BufferSegments.CopyTo(commandData, 0, 0, BufferSegments.Count); | ||
|
||
if(prevMatched > 0) | ||
Array.Copy(m_BeginSearchState.Mark, 0, commandData, BufferSegments.Count, prevMatched); | ||
|
||
Array.Copy(readBuffer, offset, commandData, BufferSegments.Count + prevMatched, totalParsed); | ||
|
||
var requestInfo = ProcessMatchedRequest(commandData, 0, commandData.Length); | ||
|
||
if (!ReferenceEquals(requestInfo, NullRequestInfo)) | ||
{ | ||
Reset(); | ||
return requestInfo; | ||
} | ||
|
||
if (rest > 0) | ||
{ | ||
searchEndMarkOffset = endPos + m_EndSearchState.Mark.Length; | ||
searchEndMarkLength = rest; | ||
continue; | ||
} | ||
|
||
//Not match | ||
if(prevMatched > 0)//Also cache the prev matched begin mark | ||
AddArraySegment(m_BeginSearchState.Mark, 0, prevMatched, false); | ||
AddArraySegment(readBuffer, offset, length, toBeCopied); | ||
return NullRequestInfo; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Processes the matched request. | ||
/// </summary> | ||
/// <param name="readBuffer">The read buffer.</param> | ||
/// <param name="offset">The offset.</param> | ||
/// <param name="length">The length.</param> | ||
/// <returns></returns> | ||
protected abstract TRequestInfo ProcessMatchedRequest(byte[] readBuffer, int offset, int length); | ||
|
||
/// <summary> | ||
/// Resets this instance. | ||
/// </summary> | ||
public override void Reset() | ||
{ | ||
m_BeginSearchState.Matched = 0; | ||
m_EndSearchState.Matched = 0; | ||
m_FoundBegin = false; | ||
base.Reset(); | ||
} | ||
} | ||
} |
Oops, something went wrong.