Files
v2ray_simple/advLayer/grpcSimple/common.go
2022-05-01 09:32:00 +08:00

126 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package grpcSimple
import (
"bufio"
"bytes"
"encoding/binary"
"io"
"net"
"time"
"github.com/e1732a364fed/v2ray_simple/utils"
)
// Modified from: https://github.com/Dreamacro/clash/blob/master/transport/gun/gun.go
// License: MIT
func commonWrite(b []byte) *bytes.Buffer {
protobufHeader := [binary.MaxVarintLen64 + 1]byte{0x0A}
varuintSize := binary.PutUvarint(protobufHeader[1:], uint64(len(b)))
grpcHeader := make([]byte, 5)
grpcPayloadLen := uint32(varuintSize + 1 + len(b))
binary.BigEndian.PutUint32(grpcHeader[1:5], grpcPayloadLen)
buf := utils.GetBuf()
buf.Write(grpcHeader)
buf.Write(protobufHeader[:varuintSize+1])
buf.Write(b)
return buf
}
type commonPart struct {
remain int
br *bufio.Reader
la, ra net.Addr
}
func (c *commonPart) LocalAddr() net.Addr { return c.la }
func (c *commonPart) RemoteAddr() net.Addr { return c.ra }
func (c *commonPart) Read(b []byte) (n int, err error) {
if c.remain > 0 {
size := c.remain
if len(b) < size {
size = len(b)
}
n, err = io.ReadFull(c.br, b[:size])
c.remain -= n
return
}
_, err = c.br.Discard(6)
if err != nil {
return 0, err
}
protobufPayloadLen, err := binary.ReadUvarint(c.br)
if err != nil {
return 0, utils.ErrInErr{ErrDesc: "grpc Read, binary.ReadUvarint failed", ErrDetail: err, ExtraIs: []error{utils.ErrInvalidData}}
}
size := int(protobufPayloadLen)
if len(b) < size {
size = len(b)
}
n, err = io.ReadFull(c.br, b[:size])
if err != nil {
return
}
remain := int(protobufPayloadLen) - n
if remain > 0 {
c.remain = remain
}
return n, nil
}
//timeouter 修改自 clash的gun.go, 是一种简单且不完美的deadline实现。
// clash的代码没有考虑到 设置 time.Time{} 空结构时要stop timer我们加上了。
//
// timeouter一旦超时就会直接关闭连接这是无法恢复的。而且 读和写共用同一个deadline。
// 如果要求高的话,还是建议使用 netLayer.EasyDeadline.
// 但因为比较极简,所以我们保留了下来。
type timeouter struct {
deadline *time.Timer
closeFunc func()
}
func (g *timeouter) SetReadDeadline(t time.Time) error { return g.SetDeadline(t) }
func (g *timeouter) SetWriteDeadline(t time.Time) error { return g.SetDeadline(t) }
func (g *timeouter) SetDeadline(t time.Time) error {
var d time.Duration
if g.deadline != nil {
if t == (time.Time{}) {
g.deadline.Stop()
g.deadline = nil
return nil
}
d = time.Until(t)
g.deadline.Reset(d)
} else {
if t == (time.Time{}) {
return nil
}
d = time.Until(t)
g.deadline = time.AfterFunc(d, g.closeFunc)
}
return nil
}