Skip to content

Commit 9be26bd

Browse files
authored
socket: only send client metadata once per socket (#105)
Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up.
1 parent 896bbb8 commit 9be26bd

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

cluster.go

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,38 @@ func (cluster *mongoCluster) isMaster(socket *mongoSocket, result *isMasterResul
148148
session := newSession(Monotonic, cluster, 10*time.Second)
149149
session.setSocket(socket)
150150

151-
// provide some meta infos on the client,
152-
// see https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake
153-
// for details
154-
metaInfo := bson.M{"driver": bson.M{"name": "mgo", "version": "globalsign"},
155-
"os": bson.M{"type": runtime.GOOS, "architecture": runtime.GOARCH}}
151+
var cmd = bson.D{{Name: "isMaster", Value: 1}}
152+
153+
// Send client metadata to the server to identify this socket if this is
154+
// the first isMaster call only.
155+
//
156+
// isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments
157+
// https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake
158+
//
159+
socket.sendMeta.Do(func() {
160+
var meta = bson.M{
161+
"driver": bson.M{
162+
"name": "mgo",
163+
"version": "globalsign",
164+
},
165+
"os": bson.M{
166+
"type": runtime.GOOS,
167+
"architecture": runtime.GOARCH,
168+
},
169+
}
156170

157-
if cluster.appName != "" {
158-
metaInfo["application"] = bson.M{"name": cluster.appName}
159-
}
160-
err := session.Run(bson.D{{Name: "isMaster", Value: 1}, {Name: "client", Value: metaInfo}}, result)
171+
// Include the application name if set
172+
if cluster.appName != "" {
173+
meta["application"] = bson.M{"name": cluster.appName}
174+
}
175+
176+
cmd = append(cmd, bson.DocElem{
177+
Name: "client",
178+
Value: meta,
179+
})
180+
})
181+
182+
err := session.Run(cmd, result)
161183
session.Close()
162184
return err
163185
}

socket.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type mongoSocket struct {
5454
dead error
5555
serverInfo *mongoServerInfo
5656
closeAfterIdle bool
57+
sendMeta sync.Once
5758
}
5859

5960
type queryOpFlags uint32

0 commit comments

Comments
 (0)