WL#12240: X Protocol server initiates conversation

Affects: Server-8.0   —   Status: Complete

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

  1. xproto clients are expected to not fail the connection if they receive a notice on connect
  2. xproto clients are expected to ignore the notice if they don't understand it
  3. 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