Skip to content

Commit 9a6d631

Browse files
committed
Fix protocol version negotiation issues with v5
Driver was automatically setting beta flag when using v5 protocol which causes issues when trying to connect to Cassandra versions that supported beta v5 like 3.11. Also, this patch makes the protocol version discovery process more resilient. Still not a long term solution since long term we should make the protocol version negotiation work like in the java driver. Patch by João Reis; reviewed by TBD for CASSGO-88
1 parent a6e8291 commit 9a6d631

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

conn.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,24 @@ func (c *Conn) execInternal(ctx context.Context, req frameBuilder, tracer Tracer
13171317
defer c.releaseStream(call)
13181318

13191319
if v := resp.framer.header.version.version(); v != c.version {
1320-
return nil, NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version)
1320+
errProtocol := NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version)
1321+
responseFrame, err := resp.framer.parseFrame()
1322+
if err != nil {
1323+
c.logger.Warning("Framer error while attempting to parse potential protocol error.",
1324+
newLogFieldError("err", err))
1325+
return nil, errProtocol
1326+
}
1327+
//goland:noinspection GoTypeAssertionOnErrors
1328+
errFrame, isErrFrame := responseFrame.(errorFrame)
1329+
if !isErrFrame {
1330+
return nil, errProtocol
1331+
}
1332+
if errFrame.Code() != ErrCodeProtocol {
1333+
return nil, errProtocol
1334+
}
1335+
return nil, NewErrProtocol("%w", &protocolError{
1336+
errFrame,
1337+
})
13211338
}
13221339

13231340
return resp.framer, nil

control.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,13 +204,34 @@ func shuffleHosts(hosts []*HostInfo) []*HostInfo {
204204

205205
// this is going to be version dependant and a nightmare to maintain :(
206206
var protocolSupportRe = regexp.MustCompile(`the lowest supported version is \d+ and the greatest is (\d+)$`)
207+
var betaProtocolRe = regexp.MustCompile(`Beta version of the protocol used \(.*\), but USE_BETA flag is unset`)
207208

208209
func parseProtocolFromError(err error) int {
210+
errStr := err.Error()
211+
212+
var errProtocol ErrProtocol
213+
if errors.As(err, &errProtocol) {
214+
err = errProtocol.error
215+
}
216+
209217
// I really wish this had the actual info in the error frame...
210-
matches := protocolSupportRe.FindAllStringSubmatch(err.Error(), -1)
218+
matches := betaProtocolRe.FindAllStringSubmatch(errStr, -1)
219+
if len(matches) == 1 {
220+
var protoErr *protocolError
221+
if errors.As(err, &protoErr) {
222+
version := protoErr.frame.Header().version.version()
223+
if version > 0 {
224+
return int(version - 1)
225+
}
226+
}
227+
return 0
228+
}
229+
230+
matches = protocolSupportRe.FindAllStringSubmatch(errStr, -1)
211231
if len(matches) != 1 || len(matches[0]) != 2 {
212-
if verr, ok := err.(*protocolError); ok {
213-
return int(verr.frame.Header().version.version())
232+
var protoErr *protocolError
233+
if errors.As(err, &protoErr) {
234+
return int(protoErr.frame.Header().version.version())
214235
}
215236
return 0
216237
}
@@ -223,11 +244,13 @@ func parseProtocolFromError(err error) int {
223244
return max
224245
}
225246

247+
const highestProtocolVersionSupported = 5
248+
226249
func (c *controlConn) discoverProtocol(hosts []*HostInfo) (int, error) {
227250
hosts = shuffleHosts(hosts)
228251

229252
connCfg := *c.session.connCfg
230-
connCfg.ProtoVersion = 5 // TODO: define maxProtocol
253+
connCfg.ProtoVersion = highestProtocolVersionSupported
231254

232255
handler := connErrorHandlerFn(func(c *Conn, err error, closed bool) {
233256
// we should never get here, but if we do it means we connected to a

frame.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,9 +393,6 @@ func newFramer(compressor Compressor, version byte, r *RegisteredTypes) *framer
393393
if compressor != nil {
394394
flags |= flagCompress
395395
}
396-
if version == protoVersion5 {
397-
flags |= flagBetaProtocol
398-
}
399396

400397
version &= protoVersionMask
401398

0 commit comments

Comments
 (0)