-
Notifications
You must be signed in to change notification settings - Fork 232
Description
This can lead to situations where an attempt to connect via a NATS instance using await finishes waiting for the asynchronous connection to complete, yet the NATS instance is not formally connected via the is_connected property being set to True.
When the gnats server responds to a connect command with "OK", if we proceed to immediately write "PING", the server will respond with the expected "PONG".
But when the gnats server responds to a connect command with its own "PING", when we immediately write "PING", the next op from the io_reader buffer will be the server's own "PING" instead of the expected "PONG", which is what client.py is using to consider the client connected.
My proposed fix is to simply add an extra next_op = yield from self._io_reader.readline() after the main connect command is written, but before we send the client's "PING" to the server.
The value of next_op after the initial connection will still be either "OK" or sometimes "PING". In either case, after we write our own "PING" from the client and then drain the writer, the next op read from the io_reader buffer will consistenly be "OK" and then "PONG" (unless there was an actual problem with the client's PING from being recognized by the gnats server).
With the fix, example of when server responds with expected "OK" after initial connection:
client.py: writing connect_cmd [b'CONNECT {"auth_token": "xxxxxxx", "echo": true, "lang": "python3", "pedantic": true, "protocol": 1, "verbose": true, "version": "0.8.2"}\r\n']
client.py: next_op [b'+OK\r\n']
client.py: writing ping_proto [b'PING\r\n']
client.py: next_op [b'PONG\r\n']
client.py: client is_connected set to True!
client.py: process_connect_init() complete
With the fix, example of when server responds with unexpected "PING" after initial connection:
client.py: writing connect_cmd [b'CONNECT {"auth_token": "xxxxxxx", "echo": true, "lang": "python3", "pedantic": true, "protocol": 1, "verbose": true, "version": "0.8.2"}\r\n']
client.py: next_op [b'PING\r\n']
client.py: writing ping_proto [b'PING\r\n']
client.py: next_op [b'+OK\r\n']
client.py: next_op [b'PONG\r\n']
client.py: client is_connected set to True!
client.py: process_connect_init() complete
Note that in the above case, the "OK" is read from the io_reader because verbose is currently set to True.
Without the fix mentioned above, we can sometimes see:
client.py: writing connect_cmd [b'CONNECT {"auth_token": "xxxxxxx", "echo": true, "lang": "python3", "pedantic": true, "protocol": 1, "verbose": true, "version": "0.8.2"}\r\n']
client.py: writing ping_proto [b'PING\r\n']
client.py: next_op [b'PING\r\n']
client.py: client is_connected is NOT set to True!
client.py: process_connect_init() complete