Ejemplo n.º 1
0
func newConnection(node, keyspace string, timeout int, authentication map[string]string) (*connection, error) {

	addr, err := net.ResolveTCPAddr("tcp", node)
	if err != nil {
		return nil, err
	}

	c := &connection{node: node}

	c.socket, err = thrift.NewTNonblockingSocketAddr(addr)
	if err != nil {
		return nil, err
	}

	// socket not open yet, so no error expected. it expects nanos, we have milis, so it's 1e6
	c.socket.SetTimeout(int64(timeout) * 1e6)

	c.transport = thrift.NewTFramedTransport(c.socket)
	protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
	c.client = cassandra.NewCassandraClientFactory(c.transport, protocolFactory)

	// simulate timeout support for the underlying Dial() in .Open(). needless to say this sucks
	// restore sanity to this for Go v1 with the new DialTimeout() func
	ch := make(chan bool, 1)
	go func() {
		err = c.transport.Open()
		ch <- true
	}()
	timedOut := false
	select {
	case <-time.After(time.Duration(timeout) * time.Millisecond):
		timedOut = true
	case <-ch:
	}
	if timedOut {
		return nil, ErrorConnectionTimeout
	}
	if err != nil {
		return nil, err
	}

	version, err := c.client.DescribeVersion()
	if err != nil {
		c.close()
		return nil, err
	}
	versionComponents := strings.Split(version, ".")
	if len(versionComponents) < 1 {
		return nil, ErrorInvalidThriftVersion
	}
	majorVersion, err := strconv.Atoi(versionComponents[0])
	if err != nil {
		return nil, ErrorInvalidThriftVersion
	}
	if majorVersion < LOWEST_COMPATIBLE_VERSION {
		return nil, ErrorWrongThriftVersion
	}

	if len(authentication) > 0 {
		ar := cassandra.NewAuthenticationRequest()
		ar.Credentials = thrift.NewTMap(thrift.STRING, thrift.STRING, 1)
		for k, v := range authentication {
			ar.Credentials.Set(k, v)
		}
		autE, auzE, err := c.client.Login(ar)
		if autE != nil {
			return nil, ErrorAuthenticationFailed
		}
		if auzE != nil {
			return nil, ErrorAuthorizationFailed
		}
		if err != nil {
			return nil, err
		}
	}

	ire, err := c.client.SetKeyspace(keyspace)
	if err != nil {
		c.close()
		return nil, err
	}
	if ire != nil {
		c.close()
		return nil, ErrorSetKeyspace
	}

	c.keyspace = keyspace

	return c, nil
}
Ejemplo n.º 2
0
func newConnection(n *node, keyspace string, timeout time.Duration, authentication map[string]string, tlsConfig *tls.Config) (*connection, error) {

	addr, err := net.ResolveTCPAddr("tcp", n.node)
	if err != nil {
		return nil, err
	}

	c := &connection{node: n}
	if tlsConfig == nil {
		socket := thrift.NewTSocketFromAddrTimeout(addr, timeout)
		c.transport = thrift.NewTFramedTransport(socket)
	} else {
		sslSocket := thrift.NewTSSLSocketFromAddrTimeout(addr, tlsConfig, timeout)
		c.transport = thrift.NewTFramedTransport(sslSocket)
	}

	protocol := thrift.NewTBinaryProtocolTransport(c.transport)
	c.client = cassandra.NewCassandraClientProtocol(c.transport, protocol, protocol)

	if err = c.transport.Open(); err != nil {
		return nil, err
	}

	version, err := c.client.DescribeVersion()
	if err != nil {
		c.close()
		return nil, err
	}
	versionComponents := strings.Split(version, ".")
	if len(versionComponents) < 1 {
		return nil, errors.New(fmt.Sprint("Cannot parse the Thrift API version number: ", version))
	}
	majorVersion, err := strconv.Atoi(versionComponents[0])
	if err != nil {
		return nil, errors.New(fmt.Sprint("Cannot parse the Thrift API version number: ", version))
	}
	if majorVersion < LOWEST_COMPATIBLE_VERSION {
		return nil, errors.New(fmt.Sprint("Unsupported Thrift API version, lowest supported is ", LOWEST_COMPATIBLE_VERSION,
			", server reports ", majorVersion))
	}

	if len(authentication) > 0 {
		ar := cassandra.NewAuthenticationRequest()
		ar.Credentials = authentication
		err := c.client.Login(ar)
		if err != nil {
			c.close()
			switch err.(type) {
			case *cassandra.AuthenticationException:
				return nil, errors.New("Login error: cannot authenticate with the given credentials")
			case *cassandra.AuthorizationException:
				return nil, errors.New("Login error: the given credentials are not authorized to access the server")
			default:
				return nil, err
			}
		}
	}

	err = c.client.SetKeyspace(keyspace)
	if err != nil {
		c.close()
		switch err.(type) {
		case *cassandra.InvalidRequestException:
			err = errors.New("Cannot set the keyspace " + keyspace)
		}
		return nil, err
	}

	return c, nil
}