package grpc import ( "errors" "io" "net" "time" "github.com/go-gost/core/logger" pb "github.com/go-gost/x/internal/util/grpc/proto" "google.golang.org/grpc/peer" ) type server struct { cqueue chan net.Conn localAddr net.Addr pb.UnimplementedGostTunelServer logger logger.Logger } func (s *server) Tunnel(srv pb.GostTunel_TunnelServer) error { c := &conn{ s: srv, localAddr: s.localAddr, remoteAddr: &net.TCPAddr{}, closed: make(chan struct{}), } if p, ok := peer.FromContext(srv.Context()); ok { c.remoteAddr = p.Addr } select { case s.cqueue <- c: default: c.Close() s.logger.Warnf("connection queue is full, client discarded") } <-c.closed return nil } type conn struct { s pb.GostTunel_TunnelServer rb []byte localAddr net.Addr remoteAddr net.Addr closed chan struct{} } func (c *conn) Read(b []byte) (n int, err error) { select { case <-c.s.Context().Done(): err = c.s.Context().Err() return case <-c.closed: err = io.ErrClosedPipe return default: } if len(c.rb) == 0 { chunk, err := c.s.Recv() if err != nil { return 0, err } c.rb = chunk.Data } n = copy(b, c.rb) c.rb = c.rb[n:] return } func (c *conn) Write(b []byte) (n int, err error) { select { case <-c.s.Context().Done(): err = c.s.Context().Err() return case <-c.closed: err = io.ErrClosedPipe return default: } if err = c.s.Send(&pb.Chunk{ Data: b, }); err != nil { return } n = len(b) return } func (c *conn) Close() error { select { case <-c.closed: default: close(c.closed) } return nil } func (c *conn) LocalAddr() net.Addr { return c.localAddr } func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr } func (c *conn) SetDeadline(t time.Time) error { return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} } func (c *conn) SetReadDeadline(t time.Time) error { return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} } func (c *conn) SetWriteDeadline(t time.Time) error { return &net.OpError{Op: "set", Net: "grpc", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} }