The problem with your code is that a network TCP stream (and thus an SSL stream sitting on top of it) does not ever return 0 from Read() until the connection with the server is closed.
Because of this, you need to use other ways of figuring out if you've read all the data or not.
In your case, since you are trying to read a POP3 server greeting, what you want to do is to keep looping until you've read a "\r\n"
sequence (you could also simply check for '\n' as well).
When you go to implement the CAPA, UIDL, STAT, TOP, and RETR commands, you'll want to continue looping until you receive "\r\n.\r\n"
.
If you would like to see some advanced techniques on how to do this, feel free to browse my code at https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Pop3/Pop3Stream.cs#L394 (the line # may change, but look for the Read (byte[] buffer, int offset, int count, CancellationToken cancellationToken)
method).
What this method does is prevent the consumer of this stream from reading beyond the end of a response to a command such as RETR and TOP. While doing that, it also un-byte-stuffs the data being read from the network (the POP3 server will 'byte-stuff' by prepending a '.'
to every line that begins with a '.'
in the RETR and TOP responses) so that the consumer can simply read the stream as if it were reading the raw message from disk and not have to worry about handling any of that.
In order to do that, you'll notice that Pop3Stream buffers data. That's what the ReadAhead()
method is responsible for.
This is all designed so that I can parse the message more-or-less directly from the socket rather than reading all of the data into 1 big StringBuffer before parsing it: https://github.com/jstedfast/MailKit/blob/master/MailKit/Net/Pop3/Pop3Client.cs#L1275
Between this and the fact that my MIME parser parses the message incrementally (rather than reading the entire message into 1 big StringBuffer) is what makes my code so incredibly fast compared to all of the other .NET POP3 libraries.
Good luck!