Tokio TcpStream Peek Method?


#1

Hello,

I’m trying to implement the PROXY protocol for an HTTP server I’m writing. Since PROXY is a variable width header for each connection, I need some way of not reading past its delimiter and clobbering the beginning of the first request.

My first idea was to just wrap the tokio_core::net::TcpStream in a BufRead implementation, but Hyper already buffers internally and I’d like to avoid double buffering.

I would like to be able to use peek() from std::net::TcpStream; however, tokio_core::net::TcpStream does not have peek(), nor is there any way I could find to extract the std::net::TcpStream.

Does anyone have any ideas of how to go about this? Unfortunately there doesn’t seem to be much example code for this kind of stuff that I could find.

Thank you in advance.

P. S. Another option I thought about was just reading two bytes at a time, but that seems horrifically wasteful.


#2

Does read_until basically do what you want? https://docs.rs/tokio-io/0.1.2/tokio_io/io/struct.ReadUntil.html

I’m not sure that you can get around allocating a buffer, you could use a shared space like an arena to save on allocations and reuse Vecs.


#3

Have a look at https://github.com/tokio-rs/tokio-socks5/blob/master/src/main.rs, which is a Tokio socks5 proxy impl.

It uses read_exact to read and interpret header info before determining how to proceed with future bytes. Perhaps you can use read_until? https://docs.rs/tokio-io/0.1.2/tokio_io/io/fn.read_until.html


#4

Thanks for the quick replies.

I’m not as concerned with allocating a buffer for the header (since it’s only 107 bytes at most I wouldn’t even mind just throwing it on the stack) as I am with copying all incoming data unnecessarily before Hyper consumes it into its own buffer.

The implementation I have right now drains the buffer after parsing the header then just forwards future calls directly to the underlying TcpStream. I suppose that will do for now, but I was really hoping that I was just missing something obvious to get at the peek() method.

Thank you again. :slight_smile: