github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/access_contoller/crypto/sdf/sdf.go (about)

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