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 }