// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2018 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

package mysql

import (
	
	
	
)

type connector struct {
	cfg *Config // immutable private copy.
}

// Connect implements driver.Connector interface.
// Connect returns a connection to the database.
func ( *connector) ( context.Context) (driver.Conn, error) {
	var  error

	// New mysqlConn
	 := &mysqlConn{
		maxAllowedPacket: maxPacketSize,
		maxWriteSize:     maxPacketSize - 1,
		closech:          make(chan struct{}),
		cfg:              .cfg,
	}
	.parseTime = .cfg.ParseTime

	// Connect to Server
	dialsLock.RLock()
	,  := dials[.cfg.Net]
	dialsLock.RUnlock()
	if  {
		 := 
		if .cfg.Timeout > 0 {
			var  context.CancelFunc
			,  = context.WithTimeout(, .cfg.Timeout)
			defer ()
		}
		.netConn,  = (, .cfg.Addr)
	} else {
		 := net.Dialer{Timeout: .cfg.Timeout}
		.netConn,  = .DialContext(, .cfg.Net, .cfg.Addr)
	}

	if  != nil {
		return nil, 
	}

	// Enable TCP Keepalives on TCP connections
	if ,  := .netConn.(*net.TCPConn);  {
		if  := .SetKeepAlive(true);  != nil {
			// Don't send COM_QUIT before handshake.
			.netConn.Close()
			.netConn = nil
			return nil, 
		}
	}

	// Call startWatcher for context support (From Go 1.8)
	.startWatcher()
	if  := .watchCancel();  != nil {
		.cleanup()
		return nil, 
	}
	defer .finish()

	.buf = newBuffer(.netConn)

	// Set I/O timeouts
	.buf.timeout = .cfg.ReadTimeout
	.writeTimeout = .cfg.WriteTimeout

	// Reading Handshake Initialization Packet
	, ,  := .readHandshakePacket()
	if  != nil {
		.cleanup()
		return nil, 
	}

	if  == "" {
		 = defaultAuthPlugin
	}

	// Send Client Authentication Packet
	,  := .auth(, )
	if  != nil {
		// try the default auth plugin, if using the requested plugin failed
		errLog.Print("could not use requested auth plugin '"++"': ", .Error())
		 = defaultAuthPlugin
		,  = .auth(, )
		if  != nil {
			.cleanup()
			return nil, 
		}
	}
	if  = .writeHandshakeResponsePacket(, );  != nil {
		.cleanup()
		return nil, 
	}

	// Handle response to auth packet, switch methods if possible
	if  = .handleAuthResult(, );  != nil {
		// Authentication failed and MySQL has already closed the connection
		// (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
		// Do not send COM_QUIT, just cleanup and return the error.
		.cleanup()
		return nil, 
	}

	if .cfg.MaxAllowedPacket > 0 {
		.maxAllowedPacket = .cfg.MaxAllowedPacket
	} else {
		// Get max allowed packet size
		,  := .getSystemVar("max_allowed_packet")
		if  != nil {
			.Close()
			return nil, 
		}
		.maxAllowedPacket = stringToInt() - 1
	}
	if .maxAllowedPacket < maxPacketSize {
		.maxWriteSize = .maxAllowedPacket
	}

	// Handle DSN Params
	 = .handleParams()
	if  != nil {
		.Close()
		return nil, 
	}

	return , nil
}

// Driver implements driver.Connector interface.
// Driver returns &MySQLDriver{}.
func ( *connector) () driver.Driver {
	return &MySQLDriver{}
}