SuperSocket icon indicating copy to clipboard operation
SuperSocket copied to clipboard

PipelineFilterBase - Filter(ref SequenceReader<byte> reader) - when method returns null something wierd is happening

Open panterlo opened this issue 1 year ago • 9 comments

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) };
	}
}

panterlo avatar Oct 31 '23 19:10 panterlo

Anyone have any ideas ?

panterlo avatar Nov 01 '23 14:11 panterlo

I will suggest you to use FixedHeaderPipelineFilter, which is more reasonable protocol than your current

chucklu avatar Nov 02 '23 07:11 chucklu

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

chucklu avatar Nov 02 '23 07:11 chucklu

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:

  1. The line starts with SUCCESS: or ERROR: which indicates there is a oneline response from the server ending with \r\n
  2. The line starts with > meaning it's an event like "greeting" or some data that the server sends periodically. Ending with \r\n
  3. 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.

panterlo avatar Nov 02 '23 08:11 panterlo

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.

panterlo avatar Nov 02 '23 09:11 panterlo

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

chucklu avatar Nov 02 '23 09:11 chucklu

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).

panterlo avatar Nov 02 '23 09:11 panterlo

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....

panterlo avatar Nov 02 '23 09:11 panterlo

It is a PipelineFilter implementation issue.

kerryjiang avatar Jan 09 '24 19:01 kerryjiang