func (s *server) getInterceptor(method string) (Interceptor, string) {
	name := method[strings.LastIndex(method, "/")+1:]
	if s.chkBypassFn != nil && s.chkBypassFn() {
		return nil, name
	}
	if fn, ok := s.interceptors[name]; ok {
		return fn, name
	}
	if fn, ok := s.interceptors["*"]; ok {
		return fn, name
	}
	return nil, name
}
getInterceptor finds an interceptor for the given method.
package server
import (
	"context"
	"fmt"
	"net"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"google.golang.org/grpc"
	api "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/sockets"
	"github.com/intel/cri-resource-manager/pkg/dump"
	logger "github.com/intel/cri-resource-manager/pkg/log"
	"github.com/intel/cri-resource-manager/pkg/utils"
	"github.com/intel/cri-resource-manager/pkg/instrumentation"
	"go.opencensus.io/trace"
)
type Options struct {
	Socket string
	User int
	Group int
	Mode os.FileMode
	QualifyReqFn func(interface{}) string
}
type Handler grpc.UnaryHandler
type Interceptor func(context.Context, string, interface{}, Handler) (interface{}, error)
type Server interface {
	RegisterImageService(api.ImageServiceServer) error
	RegisterRuntimeService(api.RuntimeServiceServer) error
	RegisterInterceptors(map[string]Interceptor) error
	SetBypassCheckFn(func() bool)
	Start() error
	Stop()
	Chmod(mode os.FileMode) error
	Chown(uid, gid int) error
}
type server struct {
	logger.Logger
	listener     net.Listener               
	server       *grpc.Server               
	options      Options                    
	interceptors map[string]Interceptor     
	chkBypassFn  func() bool                
	runtime      *api.RuntimeServiceServer  
	image        *api.ImageServiceServer    
}
func NewServer(options Options) (Server, error) {
	if !filepath.IsAbs(options.Socket) {
		return nil, serverError("invalid socket '%s', expecting absolute path",
			options.Socket)
	}
	s := &server{
		Logger:  logger.NewLogger("cri/server"),
		options: options,
	}
	return s, nil
}
func (s *server) RegisterImageService(service api.ImageServiceServer) error {
	if s.image != nil {
		return serverError("can't register image service, already registered")
	}
	if err := s.createGrpcServer(); err != nil {
		return err
	}
	is := service
	s.image = &is
	api.RegisterImageServiceServer(s.server, s)
	return nil
}
func (s *server) RegisterRuntimeService(service api.RuntimeServiceServer) error {
	if s.runtime != nil {
		return serverError("can't register runtime server, already registered")
	}
	if err := s.createGrpcServer(); err != nil {
		return err
	}
	rs := service
	s.runtime = &rs
	api.RegisterRuntimeServiceServer(s.server, s)
	return nil
}
func (s *server) RegisterInterceptors(intercept map[string]Interceptor) error {
	if s.interceptors == nil {
		s.interceptors = make(map[string]Interceptor)
	}
	for method, i := range intercept {
		if _, ok := s.interceptors[method]; ok {
			return serverError("server already has a registered interceptor for '%s'", method)
		}
		s.interceptors[method] = i
	}
	return nil
}
func (s *server) SetBypassCheckFn(fn func() bool) {
	s.chkBypassFn = fn
}
func (s *server) Start() error {
	s.trainMessageDumper()
	s.Debug("starting server on socket %s...", s.options.Socket)
	go func() {
		s.server.Serve(s.listener)
	}()
	s.Debug("waiting for server to become ready...")
	if err := utils.WaitForServer(s.options.Socket, time.Second); err != nil {
		return serverError("starting CRI server failed: %v", err)
	}
	return nil
}
func (s *server) Stop() {
	s.Debug("stopping server on socket %s...", s.options.Socket)
	s.server.Stop()
}
func (s *server) createGrpcServer() error {
	if s.server != nil {
		return nil
	}
	if err := os.MkdirAll(filepath.Dir(s.options.Socket), sockets.DirPermissions); err != nil {
		return serverError("failed to create directory for socket %s: %v",
			s.options.Socket, err)
	}
	l, err := net.Listen("unix", s.options.Socket)
	if err != nil {
		if utils.ServerActiveAt(s.options.Socket) {
			return serverError("failed to create server: socket %s already in use",
				s.options.Socket)
		}
		s.Warn("removing abandoned socket '%s' in use...", s.options.Socket)
		os.Remove(s.options.Socket)
		l, err = net.Listen("unix", s.options.Socket)
		if err != nil {
			return serverError("failed to create server on socket %s: %v",
				s.options.Socket, err)
		}
	}
	s.listener = l
	if s.options.User >= 0 {
		if err := s.Chown(s.options.User, s.options.Group); err != nil {
			l.Close()
			s.listener = nil
			return err
		}
	}
	if s.options.Mode != 0 {
		if err := s.Chmod(s.options.Mode); err != nil {
			l.Close()
			s.listener = nil
			return err
		}
	}
	s.server = grpc.NewServer(instrumentation.InjectGrpcServerTrace()...)
	return nil
}
func (s *server) Chmod(mode os.FileMode) error {
	if s.listener != nil {
		if err := os.Chmod(s.options.Socket, mode); err != nil {
			return serverError("failed to change permissions of socket %q to %v: %v",
				s.options.Socket, mode, err)
		}
		s.Info("changed permissions of socket %q to %v", s.options.Socket, mode)
	}
	s.options.Mode = mode
	return nil
}
func (s *server) Chown(uid, gid int) error {
	if s.listener != nil {
		userName := strconv.FormatInt(int64(uid), 10)
		if u, err := user.LookupId(userName); u != nil && err == nil {
			userName = u.Name
		}
		groupName := strconv.FormatInt(int64(gid), 10)
		if g, err := user.LookupGroupId(groupName); g != nil && err == nil {
			groupName = g.Name
		}
		if err := os.Chown(s.options.Socket, uid, gid); err != nil {
			return serverError("failed to change ownership of socket %q to %s/%s: %v",
				s.options.Socket, userName, groupName, err)
		}
		s.Info("changed ownership of socket %q to %s/%s", s.options.Socket, userName, groupName)
	}
	s.options.User = uid
	s.options.Group = gid
	return nil
}