WL#12240: X Protocol server initiates conversation
Motivation
In (the not so uncommon) case a classic-protocol client connects to xproto server port, the client will return
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial
communication packet', system error: 0
to the application:
- socket connection was successful
- but timeout was reached, waiting for the server's handshake message
This error is triggered as classic proto and xproto have different expectations on who sends the first packet:
- in classic, server initiates the conversation
- in X, client initiates the conversation
Thus when classic client connect to X Server then client waits for data from the server and server waits for data from the client.
The displayed error message isn't helpful for the users, and a classic client has no way to know it connected to a xproto port.
Goal
Give the classic-protocol client a way to report a useful error if it connected to a xproto port.
Notes
Until 8.0.15, only C++ Connector (X Protocol) supported global notice other connectors failed with following errors:
- C/Net 8.0 GA - "Expected message id: 2. Received message id: 11"
- C/Python 8.0 GA - "AttributeError"
- C/Node.JS 8.0 GA - "Invalid type for Mysqlx.Notice.Frame"
All connectors must:
- ignore unknown notice
- allow global notices at any moment of the X Protocol flow
Protocol Functional requirements
P1. Connecting mysql client and X Protocol port, must return with an error immediately
P2. Connecting mysql client and X Protocol port, must return with an error that may have an valuable information for the user. Like "invalid protocol"
Configuration functional requirement
C1. User with admin privileges must be able to disable the feature, to reduce overhead in X Protocol only environments
Design
classic clients expectation
The classic client expects to receive:
xx xx xx 00 0a ...
^^^^^^^^ length
^^ sequence id
^^ protocol version
from the server.
xproto possibilities
A xprotocol message looked like:
xx xx xx xx yy
^^^^^^^^^^^ length
^^ message-type
While the xproto server waits for the client to send the first message, the protocol allows the server to send Notices message at any time and the xproto clients needs to ignore them if they are not known.
If
Notice message is less than 16Mbyte (classic proto length limit)
- payload length is encoded the same way
- sequence id is 0x00 as needed
Notice message doesn't start with "0x0a"
the classic client will report:
- unknown protocol
immediately.
Implementation
xproto server sends a global Mysqlx.Notice.Frame after establishing the connection.
Payload of the Notice
For now there aren't any useful information that server can forward to client, still the protocol must be open for future changes. To do so, the notice must be of a new type/submessage to which we can add those "future" information. The type is going to be "HELLO":
message Frame {
...
enum Type {
WARNING = 1;
SESSION_VARIABLE_CHANGED = 2;
SESSION_STATE_CHANGED = 3;
GROUP_REPLICATION_STATE_CHANGED = 4;
SERVER_HELLO = 5;
};
required uint32 type = 1;
...
option (server_message_id) = NOTICE; // comment_out_if PROTOBUF_LITE
}
The new session setup flow is going to be following:
client <-> server: TCP connection establishment
client <- server: Mysqlx.Notice.Frame(type=SERVER_HELLO, scope=GLOBAL)
alt Connection configuration
client -> server: Mysqlx.Capability.CapabilitySet(...)
client <- server: Mysqlx.Ok()
end
client -> server: Mysqlx.Connection.AuthenticationStart(...)
... authentication flow ...
client <- server: Mysqlx.Connection.AuthenticationOk()
Assumption on Client side behaviour
- xproto clients are expected to not fail the connection if they receive a notice on connect
- xproto clients are expected to ignore the notice if they don't understand it
- xproto clients should not expect the Notice to be always sent
Configuration
Following system/plugin variables must be introduced:
- mysqlx_enable_hello_notice
Enables/disables sending of "Mysqlx.Notice.Frame(type=SERVER_HELLO). User can set this variable to "false" to give possibility to "buggy" clients to connect to X Plugin.
Property | Value |
---|---|
Variable Name | mysqlx_enable_hello_notice |
Type | BOOL |
Scope | GLOBAL |
Default | TRUE |