github.com/sagernet/sing-box@v1.2.7/transport/v2raygrpc/conn.go (about) 1 package v2raygrpc 2 3 import ( 4 "net" 5 "os" 6 "time" 7 8 "github.com/sagernet/sing-box/common/baderror" 9 "github.com/sagernet/sing/common" 10 "github.com/sagernet/sing/common/rw" 11 ) 12 13 var _ net.Conn = (*GRPCConn)(nil) 14 15 type GRPCConn struct { 16 GunService 17 cancel common.ContextCancelCauseFunc 18 cache []byte 19 } 20 21 func NewGRPCConn(service GunService, cancel common.ContextCancelCauseFunc) *GRPCConn { 22 if client, isClient := service.(GunService_TunClient); isClient { 23 service = &clientConnWrapper{client} 24 } 25 return &GRPCConn{ 26 GunService: service, 27 cancel: cancel, 28 } 29 } 30 31 func (c *GRPCConn) Read(b []byte) (n int, err error) { 32 if len(c.cache) > 0 { 33 n = copy(b, c.cache) 34 c.cache = c.cache[n:] 35 return 36 } 37 hunk, err := c.Recv() 38 err = baderror.WrapGRPC(err) 39 if err != nil { 40 c.cancel(err) 41 return 42 } 43 n = copy(b, hunk.Data) 44 if n < len(hunk.Data) { 45 c.cache = hunk.Data[n:] 46 } 47 return 48 } 49 50 func (c *GRPCConn) Write(b []byte) (n int, err error) { 51 err = baderror.WrapGRPC(c.Send(&Hunk{Data: b})) 52 if err != nil { 53 c.cancel(err) 54 return 55 } 56 return len(b), nil 57 } 58 59 func (c *GRPCConn) Close() error { 60 c.cancel(net.ErrClosed) 61 return nil 62 } 63 64 func (c *GRPCConn) LocalAddr() net.Addr { 65 return nil 66 } 67 68 func (c *GRPCConn) RemoteAddr() net.Addr { 69 return nil 70 } 71 72 func (c *GRPCConn) SetDeadline(t time.Time) error { 73 return os.ErrInvalid 74 } 75 76 func (c *GRPCConn) SetReadDeadline(t time.Time) error { 77 return os.ErrInvalid 78 } 79 80 func (c *GRPCConn) SetWriteDeadline(t time.Time) error { 81 return os.ErrInvalid 82 } 83 84 func (c *GRPCConn) NeedAdditionalReadDeadline() bool { 85 return true 86 } 87 88 func (c *GRPCConn) Upstream() any { 89 return c.GunService 90 } 91 92 var _ rw.WriteCloser = (*clientConnWrapper)(nil) 93 94 type clientConnWrapper struct { 95 GunService_TunClient 96 } 97 98 func (c *clientConnWrapper) CloseWrite() error { 99 return c.CloseSend() 100 }