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 }