-
Notifications
You must be signed in to change notification settings - Fork 700
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
[FIXED] Protocols received right after first PONG may not be processed #348
Conversation
This manifested with the recent changes where server may send an async INFO protocol right after sending the initial PONG to the client. After the client sends the CONNECT protocol, it expects to receive a PONG. The reading of the protocol is done in place (in the sendConnect() function) but a buffer reader was used. This is wrong since any data/protocol sent right after by the server may be consumed when trying to read the PONG instead of leaving that to the readLoop. Since we are just looking for the PONG (or OK and PONG) here, perform a byte-by-byte read there. Alternatively, if doing a buffered read, the buffer will have to be passed to the readLoop so that whatever is in the buffer is read prior to resuming reading from socket.
This is the result of flapping tests in go-nats that were caused by a defect (see PR https://github.com/nats-io/go-nats/pull/348). However, during debugging, I realize that there were also things that were not quite right in the server side. This change should make it the notification of cluster topology changes to clients more robust.
This is the result of flapping tests in go-nats that were caused by a defect (see PR https://github.com/nats-io/go-nats/pull/348). However, during debugging, I realize that there were also things that were not quite right in the server side. This change should make it the notification of cluster topology changes to clients more robust.
nats.go
Outdated
@@ -1283,6 +1285,24 @@ func (nc *Conn) sendConnect() error { | |||
return nil | |||
} | |||
|
|||
// read byte-by-byte from the connection until the given 'c' character is found. | |||
func (nc *Conn) readStringUpTo(c byte) (string, error) { |
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.
I think their is a func in the stdlib that does this no?
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.
I could not find. We cannot use a buffered reader because it does fill up the buffer in the background, thing that we don't want to happen. I looked at a buffered reader with io.LimitedReader
, but then you need to know the number of bytes you want to read.
I did rename the function to readProto
and don't pass the delimiter anymore. This function is not meant to be an all purpose function.
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.
ok
In some cases the server may send an authorization violation and closes the connection right away. With the original change, the test in server would fail. Handling the EOF here solves the issue. From tests it looks like the last `\n` is often missing but it is fine since the client library when not getting a PONG assumes it is an error and strips away the `-ERR` prefix and the new line suffix anyway. Updated a test since we changed the server DefaultTestOptions port to be -1 instead of 4222.
This manifested with the recent changes where server may send
an async INFO protocol right after sending the initial PONG to
the client.
After the client sends the CONNECT protocol, it expects to receive
a PONG. The reading of the protocol is done in place (in the
sendConnect() function) but a buffer reader was used. This is wrong
since any data/protocol sent right after by the server may be
consumed when trying to read the PONG instead of leaving that to
the readLoop.
Since we are just looking for the PONG (or OK and PONG) here, perform
a byte-by-byte read there. Alternatively, if doing a buffered read,
the buffer will have to be passed to the readLoop so that whatever
is in the buffer is read prior to resuming reading from socket.