github.com/v2fly/v2ray-core/v4@v4.45.2/transport/internet/grpc/encoding/conn.go (about) 1 //go:build !confonly 2 // +build !confonly 3 4 package encoding 5 6 import ( 7 "bytes" 8 "context" 9 "io" 10 "net" 11 "time" 12 13 "google.golang.org/grpc/peer" 14 ) 15 16 // GunService is the abstract interface of GunService_TunClient and GunService_TunServer 17 type GunService interface { 18 Context() context.Context 19 Send(*Hunk) error 20 Recv() (*Hunk, error) 21 } 22 23 // GunConn implements net.Conn for gun tunnel 24 type GunConn struct { 25 service GunService 26 reader io.Reader 27 over context.CancelFunc 28 local net.Addr 29 remote net.Addr 30 } 31 32 // Read implements net.Conn.Read() 33 func (c *GunConn) Read(b []byte) (n int, err error) { 34 if c.reader == nil { 35 h, err := c.service.Recv() 36 if err != nil { 37 return 0, newError("unable to read from gun tunnel").Base(err) 38 } 39 c.reader = bytes.NewReader(h.Data) 40 } 41 n, err = c.reader.Read(b) 42 if err == io.EOF { 43 c.reader = nil 44 return n, nil 45 } 46 return n, err 47 } 48 49 // Write implements net.Conn.Write() 50 func (c *GunConn) Write(b []byte) (n int, err error) { 51 err = c.service.Send(&Hunk{Data: b}) 52 if err != nil { 53 return 0, newError("Unable to send data over gun").Base(err) 54 } 55 return len(b), nil 56 } 57 58 // Close implements net.Conn.Close() 59 func (c *GunConn) Close() error { 60 if c.over != nil { 61 c.over() 62 } 63 return nil 64 } 65 66 // LocalAddr implements net.Conn.LocalAddr() 67 func (c *GunConn) LocalAddr() net.Addr { 68 return c.local 69 } 70 71 // RemoteAddr implements net.Conn.RemoteAddr() 72 func (c *GunConn) RemoteAddr() net.Addr { 73 return c.remote 74 } 75 76 // SetDeadline implements net.Conn.SetDeadline() 77 func (*GunConn) SetDeadline(time.Time) error { 78 return nil 79 } 80 81 // SetReadDeadline implements net.Conn.SetReadDeadline() 82 func (*GunConn) SetReadDeadline(time.Time) error { 83 return nil 84 } 85 86 // SetWriteDeadline implements net.Conn.SetWriteDeadline() 87 func (*GunConn) SetWriteDeadline(time.Time) error { 88 return nil 89 } 90 91 // NewGunConn creates GunConn which handles gun tunnel 92 func NewGunConn(service GunService, over context.CancelFunc) *GunConn { 93 conn := &GunConn{ 94 service: service, 95 reader: nil, 96 over: over, 97 } 98 99 conn.local = &net.TCPAddr{ 100 IP: []byte{0, 0, 0, 0}, 101 Port: 0, 102 } 103 pr, ok := peer.FromContext(service.Context()) 104 if ok { 105 conn.remote = pr.Addr 106 } else { 107 conn.remote = &net.TCPAddr{ 108 IP: []byte{0, 0, 0, 0}, 109 Port: 0, 110 } 111 } 112 113 return conn 114 }