github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/common/msgparser/msgparser.go (about)

     1  package msgparser
     2  
     3  import (
     4  	"errors"
     5  	"github.com/nyan233/littlerpc/core/common/inters"
     6  	"github.com/nyan233/littlerpc/core/protocol/message"
     7  	"io"
     8  	"syscall"
     9  )
    10  
    11  const (
    12  	_ScanInit      int = iota // 初始化状态, 扫描到数据包的第1个Byte时
    13  	_ScanMsgParse1            // 扫描基本信息状态, 扫描到描述数据包的基本信息, 这些信息可以确定数据包的长度/MsgId
    14  	_ScanMsgParse2            // 扫描完整数据状态, 扫描完整数据包
    15  )
    16  
    17  const (
    18  	DefaultBufferSize = 4096    // 4KB
    19  	MaxBufferSize     = 1 << 20 // 1MB
    20  	DefaultParser     = "lrpc-trait"
    21  )
    22  
    23  type ParserMessage struct {
    24  	Message *message.Message
    25  	// 没有Header特征的协议可以选定一个固定的虚拟值, 由Parser返回
    26  	// 再将这个固定的虚拟值注册到Writer中以找到对应的Writer
    27  	Header byte
    28  }
    29  
    30  type Factory func(msgAllocator AllocTor, bufSize uint32) Parser
    31  
    32  // Parser 解析器的所有接口的实现必须是线程安全/goroutine safe
    33  // 否则则会出现data race/race conditions
    34  type Parser interface {
    35  	// ParseOnReader 用于处理读事件可减少一次memcopy, reader返回的错误会停止解析, 所以
    36  	// reader是包装了非阻塞的syscall的话不应该返回(syscall.EWOULDBLOCK | syscall.EINTR)等相关的错误
    37  	ParseOnReader(reader func([]byte) (n int, err error)) (msgs []ParserMessage, err error)
    38  	// Parse 处理数据的接口必须能够正确处理half-package
    39  	// 也必须能处理有多个完整报文的数据, 在解析失败时返回对应的error
    40  	Parse(data []byte) (msgs []ParserMessage, err error)
    41  	// Free 用于释放Parse返回的数据, 在Parse返回error时这个过程
    42  	// 绝对不能被调用
    43  	Free(msg *message.Message)
    44  	inters.Reset
    45  }
    46  
    47  var (
    48  	parserFactoryCollections = make(map[string]Factory)
    49  )
    50  
    51  func Register(scheme string, pf Factory) {
    52  	if pf == nil {
    53  		panic("parser factory is nil")
    54  	}
    55  	if scheme == "" {
    56  		panic("parser scheme is empty")
    57  	}
    58  	parserFactoryCollections[scheme] = pf
    59  }
    60  
    61  func Get(scheme string) Factory {
    62  	return parserFactoryCollections[scheme]
    63  }
    64  
    65  func DefaultReader(reader io.Reader) func(p []byte) (n int, err error) {
    66  	// 非阻塞系统调用最多执行8次
    67  	const (
    68  		SyscallLimit = 8
    69  	)
    70  	var (
    71  		ErrLimit = errors.New("syscall limit out of range 16")
    72  	)
    73  	var count int
    74  	return func(p []byte) (n int, err error) {
    75  		if count > SyscallLimit {
    76  			return -1, ErrLimit
    77  		}
    78  		n, err = reader.Read(p)
    79  		count++
    80  		switch err {
    81  		case syscall.EINTR:
    82  			return n, nil
    83  		case syscall.EAGAIN:
    84  			return n, err
    85  		default:
    86  			return
    87  		}
    88  	}
    89  }
    90  
    91  func init() {
    92  	Register(DefaultParser, NewLRPCTrait)
    93  }