// ServeConn serves a single connection, driving the handshake process // and delegating to the appropriate connection type. func (s *Server) ServeConn(conn net.Conn) error { var draining bool { s.mu.Lock() draining = s.mu.draining s.mu.Unlock() } // If the Server is draining, we will use the connection only to send an // error, so we don't count it in the stats. This makes sense since // DrainClient() waits for that number to drop to zero, // so we don't want it to oscillate unnecessarily. if !draining { s.metrics.Conns.Inc(1) defer s.metrics.Conns.Dec(1) } var buf readBuffer n, err := buf.readUntypedMsg(conn) if err != nil { return err } s.metrics.BytesInCount.Inc(int64(n)) version, err := buf.getUint32() if err != nil { return err } errSSLRequired := false if version == versionSSL { if len(buf.msg) > 0 { return errors.Errorf("unexpected data after SSLRequest: %q", buf.msg) } if s.context.Insecure { if _, err := conn.Write(sslUnsupported); err != nil { return err } } else { if _, err := conn.Write(sslSupported); err != nil { return err } tlsConfig, err := s.context.GetServerTLSConfig() if err != nil { return err } conn = tls.Server(conn, tlsConfig) } n, err := buf.readUntypedMsg(conn) if err != nil { return err } s.metrics.BytesInCount.Inc(int64(n)) version, err = buf.getUint32() if err != nil { return err } } else if !s.context.Insecure { errSSLRequired = true } if version == version30 { sessionArgs, argsErr := parseOptions(buf.msg) // We make a connection regardless of argsErr. If there was an error parsing // the args, the connection will only be used to send a report of that // error. v3conn := makeV3Conn(conn, s.executor, s.metrics, sessionArgs) defer v3conn.finish() if argsErr != nil { return v3conn.sendInternalError(argsErr.Error()) } if errSSLRequired { return v3conn.sendInternalError(ErrSSLRequired) } if draining { // TODO(tschottdorf): Likely not handled gracefully by clients. // See #6295. return v3conn.sendInternalError(ErrDraining) } if tlsConn, ok := conn.(*tls.Conn); ok { tlsState := tlsConn.ConnectionState() authenticationHook, err := security.UserAuthHook(s.context.Insecure, &tlsState) if err != nil { return v3conn.sendInternalError(err.Error()) } return v3conn.serve(authenticationHook) } return v3conn.serve(nil) } return errors.Errorf("unknown protocol version %d", version) }
// serveConn serves a single connection, driving the handshake process // and delegating to the appropriate connection type. func (s *Server) serveConn(conn net.Conn) error { var buf readBuffer n, err := buf.readUntypedMsg(conn) if err != nil { return err } s.metrics.bytesInCount.Inc(int64(n)) version, err := buf.getInt32() if err != nil { return err } errSSLRequired := false if version == versionSSL { if len(buf.msg) > 0 { return util.Errorf("unexpected data after SSLRequest: %q", buf.msg) } if s.context.Insecure { if _, err := conn.Write(sslUnsupported); err != nil { return err } } else { if _, err := conn.Write(sslSupported); err != nil { return err } tlsConfig, err := s.context.GetServerTLSConfig() if err != nil { return err } conn = tls.Server(conn, tlsConfig) } n, err := buf.readUntypedMsg(conn) if err != nil { return err } s.metrics.bytesInCount.Inc(int64(n)) version, err = buf.getInt32() if err != nil { return err } } else if !s.context.Insecure { errSSLRequired = true } if version == version30 { v3conn := makeV3Conn(conn, s.context.Executor, s.metrics) // This is better than always flushing on error. defer func() { if err := v3conn.wr.Flush(); err != nil { log.Error(err) } }() if errSSLRequired { return v3conn.sendError(ErrSSLRequired) } if err := v3conn.parseOptions(buf.msg); err != nil { return v3conn.sendError(err.Error()) } if tlsConn, ok := conn.(*tls.Conn); ok { tlsState := tlsConn.ConnectionState() authenticationHook, err := security.UserAuthHook(s.context.Insecure, &tlsState) if err != nil { return v3conn.sendError(err.Error()) } return v3conn.serve(authenticationHook) } return v3conn.serve(nil) } return util.Errorf("unknown protocol version %d", version) }
// ServeConn serves a single connection, driving the handshake process // and delegating to the appropriate connection type. func (s *Server) ServeConn(conn net.Conn) error { s.metrics.conns.Inc(1) defer s.metrics.conns.Dec(1) var buf readBuffer n, err := buf.readUntypedMsg(conn) if err != nil { return err } s.metrics.bytesInCount.Inc(int64(n)) version, err := buf.getInt32() if err != nil { return err } errSSLRequired := false if version == versionSSL { if len(buf.msg) > 0 { return util.Errorf("unexpected data after SSLRequest: %q", buf.msg) } if s.context.Insecure { if _, err := conn.Write(sslUnsupported); err != nil { return err } } else { if _, err := conn.Write(sslSupported); err != nil { return err } tlsConfig, err := s.context.GetServerTLSConfig() if err != nil { return err } conn = tls.Server(conn, tlsConfig) } n, err := buf.readUntypedMsg(conn) if err != nil { return err } s.metrics.bytesInCount.Inc(int64(n)) version, err = buf.getInt32() if err != nil { return err } } else if !s.context.Insecure { errSSLRequired = true } if version == version30 { sessionArgs, argsErr := parseOptions(buf.msg) // We make a connection regardless of argsErr. If there was an error parsing // the args, the connection will only be used to send a report of that // error. v3conn := makeV3Conn(conn, s.executor, s.metrics, sessionArgs) defer v3conn.finish() if argsErr != nil { return v3conn.sendInternalError(err.Error()) } if errSSLRequired { return v3conn.sendInternalError(ErrSSLRequired) } if tlsConn, ok := conn.(*tls.Conn); ok { tlsState := tlsConn.ConnectionState() authenticationHook, err := security.UserAuthHook(s.context.Insecure, &tlsState) if err != nil { return v3conn.sendInternalError(err.Error()) } return v3conn.serve(authenticationHook) } return v3conn.serve(nil) } return util.Errorf("unknown protocol version %d", version) }