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  }