Skip to content

Commit c7e3862

Browse files
skoefReinier Schoof
authored and
Reinier Schoof
committed
support client connection attributes on the client side
1 parent d166653 commit c7e3862

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

client/auth.go

+26
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,20 @@ func (c *Conn) genAuthResponse(authData []byte) ([]byte, bool, error) {
139139
}
140140
}
141141

142+
// generate connection attributes data
143+
func (c *Conn) genAttributes() []byte {
144+
if len(c.attributes) == 0 {
145+
return nil
146+
}
147+
148+
attrData := make([]byte, 0)
149+
for k, v := range c.attributes {
150+
attrData = append(attrData, PutLengthEncodedString([]byte(k))...)
151+
attrData = append(attrData, PutLengthEncodedString([]byte(v))...)
152+
}
153+
return append(PutLengthEncodedInt(uint64(len(attrData))), attrData...)
154+
}
155+
142156
// See: http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
143157
func (c *Conn) writeAuthHandshake() error {
144158
if !authPluginAllowed(c.authPluginName) {
@@ -195,6 +209,12 @@ func (c *Conn) writeAuthHandshake() error {
195209
capability |= CLIENT_CONNECT_WITH_DB
196210
length += len(c.db) + 1
197211
}
212+
// connection attributes
213+
attrData := c.genAttributes()
214+
if len(attrData) > 0 {
215+
capability |= CLIENT_CONNECT_ATTRS
216+
length += len(attrData)
217+
}
198218

199219
data := make([]byte, length+4)
200220

@@ -264,6 +284,12 @@ func (c *Conn) writeAuthHandshake() error {
264284
// Assume native client during response
265285
pos += copy(data[pos:], c.authPluginName)
266286
data[pos] = 0x00
287+
pos++
288+
289+
// connection attributes
290+
if len(attrData) > 0 {
291+
pos += copy(data[pos:], attrData)
292+
}
267293

268294
return c.WritePacket(data)
269295
}

client/auth_test.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package client
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
)
7+
8+
func TestConnGenAttributes(t *testing.T) {
9+
c := &Conn{
10+
// example data from
11+
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse41
12+
attributes: map[string]string{
13+
"_os": "debian6.0",
14+
"_client_name": "libmysql",
15+
"_pid": "22344",
16+
"_client_version": "5.6.6-m9",
17+
"_platform": "x86_64",
18+
"foo": "bar",
19+
},
20+
}
21+
22+
data := c.genAttributes()
23+
fixture := []byte{
24+
0x61, 0x03, 0x5f, 0x6f, 0x73, 0x09, 0x64, 0x65, 0x62, 0x69,
25+
0x61, 0x6e, 0x36, 0x2e, 0x30, 0x0c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e,
26+
0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x08, 0x6c, 0x69, 0x62, 0x6d, 0x79,
27+
0x73, 0x71, 0x6c, 0x04, 0x5f, 0x70, 0x69, 0x64, 0x05, 0x32, 0x32, 0x33,
28+
0x34, 0x34, 0x0f, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x76,
29+
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x08, 0x35, 0x2e, 0x36, 0x2e, 0x36,
30+
0x2d, 0x6d, 0x39, 0x09, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
31+
0x6d, 0x06, 0x78, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x03, 0x66, 0x6f, 0x6f,
32+
0x03, 0x62, 0x61, 0x72,
33+
}
34+
35+
if !bytes.Equal(fixture, data) {
36+
t.Fatalf("unexpected attribute data\nexpected: %v\ngot: %v\n", fixture, data)
37+
}
38+
}

client/conn.go

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ type Conn struct {
2828
// client-set capabilities only
2929
ccaps uint32
3030

31+
attributes map[string]string
32+
3133
status uint16
3234

3335
charset string
@@ -302,6 +304,10 @@ func (c *Conn) Rollback() error {
302304
return errors.Trace(err)
303305
}
304306

307+
func (c *Conn) SetAttributes(attributes map[string]string) {
308+
c.attributes = attributes
309+
}
310+
305311
func (c *Conn) SetCharset(charset string) error {
306312
if c.charset == charset {
307313
return nil

0 commit comments

Comments
 (0)