github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/common/singbridge/pipe.go (about)

     1  package singbridge
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  
     8  	"github.com/sagernet/sing/common/bufio"
     9  	"github.com/xmplusdev/xmcore/common/buf"
    10  	"github.com/xmplusdev/xmcore/transport"
    11  )
    12  
    13  func CopyConn(ctx context.Context, inboundConn net.Conn, link *transport.Link, serverConn net.Conn) error {
    14  	conn := &PipeConnWrapper{
    15  		W:    link.Writer,
    16  		Conn: inboundConn,
    17  	}
    18  	if ir, ok := link.Reader.(io.Reader); ok {
    19  		conn.R = ir
    20  	} else {
    21  		conn.R = &buf.BufferedReader{Reader: link.Reader}
    22  	}
    23  	return ReturnError(bufio.CopyConn(ctx, conn, serverConn))
    24  }
    25  
    26  type PipeConnWrapper struct {
    27  	R io.Reader
    28  	W buf.Writer
    29  	net.Conn
    30  }
    31  
    32  func (w *PipeConnWrapper) Close() error {
    33  	return nil
    34  }
    35  
    36  func (w *PipeConnWrapper) Read(b []byte) (n int, err error) {
    37  	return w.R.Read(b)
    38  }
    39  
    40  func (w *PipeConnWrapper) Write(p []byte) (n int, err error) {
    41  	n = len(p)
    42  	var mb buf.MultiBuffer
    43  	pLen := len(p)
    44  	for pLen > 0 {
    45  		buffer := buf.New()
    46  		if pLen > buf.Size {
    47  			_, err = buffer.Write(p[:buf.Size])
    48  			p = p[buf.Size:]
    49  		} else {
    50  			buffer.Write(p)
    51  		}
    52  		pLen -= int(buffer.Len())
    53  		mb = append(mb, buffer)
    54  	}
    55  	err = w.W.WriteMultiBuffer(mb)
    56  	if err != nil {
    57  		n = 0
    58  		buf.ReleaseMulti(mb)
    59  	}
    60  	return
    61  }