-
-
Notifications
You must be signed in to change notification settings - Fork 104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose Conn.BufReader #54
Conversation
To prevent data loss from internal buffer when unwrapping Conn back to the underlying connection, the private buffered reader was made external.
Also, off-topic. #51 mentioned a generic |
Hmm, still not clear to me why it's not possible to just read from |
Feel free to submit a PR for it. I don't need that yet, so haven't bothered sending a patch. |
Reading larger data than whats buffered in bufio.Reader will cause it to read its underlying reader. To drain just the internal buffer, you need to know exactly how much you can read without triggering a refill. That amount you can read is exposed via Reader.Buffered(), which is what I just exposed. |
OK, but why do you need to drain the internal bufio reader? |
Ah. easy. When you detach the underlying connection from the proxy struct (which is now done using #51), you're going to want that extra data when you repurpose that connection. In my use case, I'm writing a connection forwarder (open new connection to remote, pipe data between existing (proxy) connection and the new connection). To do that properly, I need to call the underlying TCPConn's CloseRead and CloseWrite Because those methods are unaware to the fact that some of the data read from the connection is actually buffered somewhere, I'm going to need to:
If I don't drain the buffer, some application data will be forgotten in that buffer. |
By the way, another approach could be setting Conn's net.Conn as the embedded struct. That way you could e.g. pass a Conn to my forwarding routine (I would need to do the casts over there, but that's OK i guess) |
Thanks for taking the time to explain everything!
So in two separate goroutines you want to:
to properly support half-opened connections?
Maybe you can call |
Hm, I don't quite understand this one. What is the "embedded struct"? |
yea! that's why I offered
so I could just cast proxyproto.Conn like I would've done with any net.Conn anyway. I guess that will do fine for my use-case :) |
well, in our case we have an embedded interface, but we could pull it off like this type Conn struct {
- conn net.Conn
+ net.Conn
bufReader *bufio.Reader
header *Header
once sync.Once
ProxyHeaderPolicy Policy
Validate Validator
readErr error
} that way proxyproto.Conn "inherits" all of conn's methods (but can override them with implemention of its own for e.g. Read.) |
I see, that makes sense. I believe there are other use-cases that would benefit of exposing the underlying var conn *proxyproto.Conn
tr := textproto.NewReader(bufio.NewReader(conn)) Then the pipeline will contain two buffered readers, one internal to var conn *proxyproto.Conn
tr := textproto.NewReader(conn.BufReader) |
well, buffered reader actually checks if the internal reader is a buffered reader too and reuses it if so, but I see where you're going with that. |
Yeah, but that won't work here, because |
Well, i've been thinking about it, and at least for my end goal turning net.Conn into the embedded interface will make my code better than draining the however-long bufio.Reader chain I might be facing. May I add that too to the PR for further discussion? |
My bad. Excuse me. What I just outlined won't work because i'll need to type-assert to net.Conn before calling my routine, so i'm losing the internal buffer again. I guess I'll have to pass both the buffered reader and the conn to the routine. |
OK. After doing some offline evaluation, this PR is irrelevant for my needs, as I could just type-assert to proxyproto.Conn, unwrap to tcpconn with proxyproto.TCPConn() and call the needed CloseRead/Write methods. I would, however prefer to have that Raw() method we talked about earlier. I'll open another PR for that. Because we did outline some useful use-cases for this PR's change, feel free to merge it (or close it) |
Have you read #54 (comment)? |
I re-read it now, thanks for calling it out. |
@@ -21,7 +21,7 @@ type Listener struct { | |||
// may be speaking the Proxy Protocol. If it is, the RemoteAddr() will | |||
// return the address of the client instead of the proxy address. | |||
type Conn struct { | |||
bufReader *bufio.Reader | |||
BufReader *bufio.Reader |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is exported, please add a descriptive comment with an example of a use-case. Also, please add a test or two.
Gentle ping in case this got lost in doom of github notifications. |
Actually, I was reading this for the nth time and I want to go back to my initial assessment: this will be closed until it really becomes needed. Right now, it seems like it would be doing something for future users that may never show up and I'd rather not do it, particularly as exposing the buffer this way may also result in dangerous behavior. |
To prevent data loss from internal buffer when unwrapping Conn back to the underlying connection, the private buffered reader was made external. Follows-up #51.