SuperSocket
SuperSocket copied to clipboard
PipelineFilterBase - Filter(ref SequenceReader<byte> reader) - when method returns null something wierd is happening
Try this code with 2.0.0-beta.18 and when returning null it will fail after a few "line returns". Removing the return null and returning non null it will read of the data correctly. The sever is a simple RAW socket with CRLF termination. I am trying to deal with the scenario that commands sent to the server could be responded in "one line" responses or a longer response that ends with the word "END".
public class CustomFilter : PipelineFilterBase<TextPackageInfo>
{
private StringBuilder _result = new StringBuilder();
public CustomFilter()
{
}
public override TextPackageInfo Filter(ref SequenceReader<byte> reader)
{
var terminator = new ReadOnlyMemory<byte>(new[] { (byte)'\r', (byte)'\n' });
var terminatorSpan = terminator.Span;
if (!reader.TryReadTo(out ReadOnlySequence<byte> pack, terminatorSpan, advancePastDelimiter: false))
return null; // Not reached line end
try
{
var text = pack.GetString(Encoding.ASCII);
if (text.StartsWith(">") == false &&
text.StartsWith("SUCCESS:") == false &&
text.StartsWith("ERROR:") == false)
_result.AppendLine(text);
Console.WriteLine(_result.ToString());
return null; // Will work for a few line returns then nothing happens....
return new TextPackageInfo() { Text = text }; // Works all the way
}
finally
{
reader.Advance(terminator.Length);
}
}
protected override TextPackageInfo DecodePackage(ref ReadOnlySequence<byte> buffer)
{
return new TextPackageInfo { Text = buffer.GetString(Encoding.ASCII) };
}
}
Anyone have any ideas ?
I will suggest you to use FixedHeaderPipelineFilter, which is more reasonable protocol than your current
When you return null package, the subsequent code logic is here https://github.com/kerryjiang/SuperSocket/blob/07d5a6f86601cbb7c76b2f18503103b3b232aede/src/SuperSocket.Channel/PipeChannel.cs#L496
if (packageInfo == null)
{
// the current pipeline filter needs more data to process
if (!filterSwitched)
{
// set consumed position and then continue to receive...
consumed = buffer.GetPosition(bytesConsumedTotal);
return true;
}
// we should reset the previous pipeline filter after switch
currentPipelineFilter.Reset();
}
else
{
// reset the pipeline filter after we parse one full package
currentPipelineFilter.Reset();
_packagePipe.Write(packageInfo);
}
If you think you encounter an bug, try to reproduce it and provide a sample repository with both client and server code for me to troubleshooting
Hmm, I am noticing if the server sends only a carriage return \r\n and nothing else it for some reason locks up further calling on the pipeline filter.
I am using OpenVPN Management socket which essentially loooks like this:
Description: [FROM SERVER WHEN CLIENT CONNECTS]
>INFO:OpenVPN Management Interface Version 5 -- type 'help' for more info
Description: [FROM CLIENT TO SERVER]
status
Description: [SERVER RESPONDS WITH]
OpenVPN STATISTICS
Updated,2023-11-02 09:18:54
TUN/TAP read bytes,780
TUN/TAP write bytes,5363
TCP/UDP read bytes,8151
TCP/UDP write bytes,6208
Auth read bytes,0
END
The socket server have these variations:
- The line starts with SUCCESS: or ERROR: which indicates there is a oneline response from the server ending with \r\n
- The line starts with > meaning it's an event like "greeting" or some data that the server sends periodically. Ending with \r\n
- The line doesnt start with 1) or 2) but ends with the word END and \r\n
I will put the short code for testing on a repo now.
I have added a repo here https://github.com/panterlo/OpenVPNManagementClient and the client connects to a forwarded port on my firewall so you don't have to setup OpenVPN. So you should just be able to run the code.
So, you are using the EasyClient with pipelineFilter? working as a socket client instead of socket server?
_client = new EasyClient<OpenVPNManagementPackage>(new LinePipelineFilterOpenVPN(), new SuperSocket.Channel.ChannelOptions()).AsClient();
Please refer to the sample code https://github.com/kerryjiang/SuperSocket/blob/07d5a6f86601cbb7c76b2f18503103b3b232aede/test/SuperSocket.Tests/ClientTest.cs#L211, and write a server according the sample
Correct, it's a client I am trying to build against an already existing server, OpenVPN Mangement Socket Server. I have added a test server in the code with the external IP so there is no need to mock a separate server (that ideally wouldn't be the same).
You can just use Putty or whatever socket client there is with RAW sockets and connect to the IP and port and run the commands to see how it should behave....
It is a PipelineFilter implementation issue.