diff --git a/CHANGELOG.md b/CHANGELOG.md index 19f353ad8..68166e39c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +#### 2.0.0 + +- Do not set beta protocol flag when using v5 (CASSGO-88) + #### 2.0.0-rc1 - Cassandra version unmarshal fix (CASSGO-49) diff --git a/conn.go b/conn.go index 6cfb6fe9a..877c2aaec 100644 --- a/conn.go +++ b/conn.go @@ -1317,7 +1317,21 @@ func (c *Conn) execInternal(ctx context.Context, req frameBuilder, tracer Tracer defer c.releaseStream(call) if v := resp.framer.header.version.version(); v != c.version { - return nil, NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version) + errProtocol := NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version) + responseFrame, err := resp.framer.parseFrame() + if err != nil { + c.logger.Warning("Framer error while attempting to parse potential protocol error.", + newLogFieldError("err", err)) + return nil, errProtocol + } + //goland:noinspection GoTypeAssertionOnErrors + errFrame, isErrFrame := responseFrame.(errorFrame) + if !isErrFrame || errFrame.Code() != ErrCodeProtocol { + return nil, errProtocol + } + return nil, NewErrProtocol("%w", &protocolError{ + errFrame, + }) } return resp.framer, nil diff --git a/control.go b/control.go index b521c41d8..e3c835b45 100644 --- a/control.go +++ b/control.go @@ -204,13 +204,34 @@ func shuffleHosts(hosts []*HostInfo) []*HostInfo { // this is going to be version dependant and a nightmare to maintain :( var protocolSupportRe = regexp.MustCompile(`the lowest supported version is \d+ and the greatest is (\d+)$`) +var betaProtocolRe = regexp.MustCompile(`Beta version of the protocol used \(.*\), but USE_BETA flag is unset`) func parseProtocolFromError(err error) int { + errStr := err.Error() + + var errProtocol ErrProtocol + if errors.As(err, &errProtocol) { + err = errProtocol.error + } + // I really wish this had the actual info in the error frame... - matches := protocolSupportRe.FindAllStringSubmatch(err.Error(), -1) + matches := betaProtocolRe.FindAllStringSubmatch(errStr, -1) + if len(matches) == 1 { + var protoErr *protocolError + if errors.As(err, &protoErr) { + version := protoErr.frame.Header().version.version() + if version > 0 { + return int(version - 1) + } + } + return 0 + } + + matches = protocolSupportRe.FindAllStringSubmatch(errStr, -1) if len(matches) != 1 || len(matches[0]) != 2 { - if verr, ok := err.(*protocolError); ok { - return int(verr.frame.Header().version.version()) + var protoErr *protocolError + if errors.As(err, &protoErr) { + return int(protoErr.frame.Header().version.version()) } return 0 } @@ -223,11 +244,13 @@ func parseProtocolFromError(err error) int { return max } +const highestProtocolVersionSupported = 5 + func (c *controlConn) discoverProtocol(hosts []*HostInfo) (int, error) { hosts = shuffleHosts(hosts) connCfg := *c.session.connCfg - connCfg.ProtoVersion = 5 // TODO: define maxProtocol + connCfg.ProtoVersion = highestProtocolVersionSupported handler := connErrorHandlerFn(func(c *Conn, err error, closed bool) { // we should never get here, but if we do it means we connected to a diff --git a/frame.go b/frame.go index 93af2c673..7e551c233 100644 --- a/frame.go +++ b/frame.go @@ -393,9 +393,6 @@ func newFramer(compressor Compressor, version byte, r *RegisteredTypes) *framer if compressor != nil { flags |= flagCompress } - if version == protoVersion5 { - flags |= flagBetaProtocol - } version &= protoVersionMask