gitee.com/lh-her-team/common@v1.5.1/crypto/sdf/sdf.go (about)

     1  package sdf
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"strconv"
     8  	"time"
     9  
    10  	"gitee.com/lh-her-team/common/crypto/sdf/base"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  const (
    15  	defaultSessionSize = 10
    16  )
    17  
    18  type SDFHandle struct {
    19  	ctx              *base.Ctx
    20  	deviceHandle     base.SessionHandle
    21  	sessions         chan base.SessionHandle
    22  	sessionCacheSize int
    23  }
    24  
    25  // New returns a HSM SDFHandle to provide go-sdf functionalities.
    26  func New(lib string, sessionCacheSize int) (*SDFHandle, error) {
    27  	ctx := base.New(lib)
    28  	if ctx == nil {
    29  		libEnv := os.Getenv("HSM_LIB")
    30  		log.Printf("lib[%s] invalid, use HSM_LIB[%s] from env\n", lib, libEnv)
    31  		ctx = base.New(libEnv)
    32  		if ctx == nil {
    33  			return nil, fmt.Errorf("[SDF] error: fail to initialize [%s]", libEnv)
    34  		}
    35  	}
    36  	if sessionCacheSize <= 0 {
    37  		sessionSizeStr := os.Getenv("HSM_SESSION_CACHE_SIZE")
    38  		sessionSize, err := strconv.Atoi(sessionSizeStr)
    39  		if err == nil && sessionSize > 0 {
    40  			log.Printf("sessionCacheSize[%d] invalid, use HSM_SESSION_CACHE_SIZE[%s] from env\n",
    41  				sessionCacheSize, sessionSizeStr)
    42  			sessionCacheSize = sessionSize
    43  		} else {
    44  			log.Printf("sessionCacheSize[%d] and HSM_SESSION_CACHE_SIZE[%s] invalid, use default size[%d]\n",
    45  				sessionCacheSize, sessionSizeStr, defaultSessionSize)
    46  			sessionCacheSize = defaultSessionSize
    47  		}
    48  	}
    49  	var err error
    50  	var deviceHandle base.SessionHandle
    51  	for i := 0; i < 3; i++ {
    52  		deviceHandle, err = ctx.SDFOpenDevice()
    53  		if err != nil {
    54  			continue
    55  		}
    56  		break
    57  	}
    58  	if err != nil {
    59  		return nil, fmt.Errorf("[SDF] error: fail to open device after 3 times [%v]", err)
    60  	}
    61  	sessions := make(chan base.SessionHandle, sessionCacheSize)
    62  	handle := &SDFHandle{
    63  		ctx:              ctx,
    64  		deviceHandle:     deviceHandle,
    65  		sessions:         sessions,
    66  		sessionCacheSize: sessionCacheSize,
    67  	}
    68  	return handle, nil
    69  }
    70  
    71  func (h *SDFHandle) getSession() (base.SessionHandle, error) {
    72  	var session base.SessionHandle
    73  	select {
    74  	case session = <-h.sessions:
    75  		return session, nil
    76  	default:
    77  		var err error
    78  		for i := 0; i < 3; i++ {
    79  			session, err = h.ctx.SDFOpenSession(h.deviceHandle)
    80  			if err == nil {
    81  				return session, nil
    82  			}
    83  			time.Sleep(time.Millisecond * 100)
    84  		}
    85  		return nil, errors.WithMessage(err, "failed to create new session after 3 times attempt")
    86  	}
    87  }
    88  
    89  func (h *SDFHandle) returnSession(err error, session base.SessionHandle) {
    90  	if err != nil {
    91  		_ = h.ctx.SDFCloseSession(session)
    92  	}
    93  	select {
    94  	case h.sessions <- session:
    95  		return
    96  	default:
    97  		_ = h.ctx.SDFCloseSession(session)
    98  		return
    99  	}
   100  }
   101  
   102  func (h *SDFHandle) Close() error {
   103  	//close channel to avoid creating new session
   104  	close(h.sessions)
   105  	//close all sessions
   106  	for session := range h.sessions {
   107  		err := h.ctx.SDFCloseSession(session)
   108  		if err != nil {
   109  			return err
   110  		}
   111  	}
   112  	//close device
   113  	return h.ctx.SDFCloseDevice(h.deviceHandle)
   114  }