github.com/sagernet/sing-box@v1.2.7/transport/v2rayhttp/conn.go (about)

     1  package v2rayhttp
     2  
     3  import (
     4  	std_bufio "bufio"
     5  	"io"
     6  	"net"
     7  	"net/http"
     8  	"os"
     9  	"strings"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/sagernet/sing-box/common/baderror"
    14  	"github.com/sagernet/sing/common"
    15  	"github.com/sagernet/sing/common/buf"
    16  	"github.com/sagernet/sing/common/bufio"
    17  	E "github.com/sagernet/sing/common/exceptions"
    18  	F "github.com/sagernet/sing/common/format"
    19  	N "github.com/sagernet/sing/common/network"
    20  )
    21  
    22  type HTTPConn struct {
    23  	net.Conn
    24  	request        *http.Request
    25  	requestWritten bool
    26  	responseRead   bool
    27  	responseCache  *buf.Buffer
    28  }
    29  
    30  func NewHTTP1Conn(conn net.Conn, request *http.Request) *HTTPConn {
    31  	return &HTTPConn{
    32  		Conn:    conn,
    33  		request: request,
    34  	}
    35  }
    36  
    37  func (c *HTTPConn) Read(b []byte) (n int, err error) {
    38  	if !c.responseRead {
    39  		reader := std_bufio.NewReader(c.Conn)
    40  		response, err := http.ReadResponse(reader, c.request)
    41  		if err != nil {
    42  			return 0, E.Cause(err, "read response")
    43  		}
    44  		if response.StatusCode != 200 {
    45  			return 0, E.New("unexpected status: ", response.Status)
    46  		}
    47  		if cacheLen := reader.Buffered(); cacheLen > 0 {
    48  			c.responseCache = buf.NewSize(cacheLen)
    49  			_, err = c.responseCache.ReadFullFrom(reader, cacheLen)
    50  			if err != nil {
    51  				c.responseCache.Release()
    52  				return 0, E.Cause(err, "read cache")
    53  			}
    54  		}
    55  		c.responseRead = true
    56  	}
    57  	if c.responseCache != nil {
    58  		n, err = c.responseCache.Read(b)
    59  		if err == io.EOF {
    60  			c.responseCache.Release()
    61  			c.responseCache = nil
    62  		}
    63  		if n > 0 {
    64  			return n, nil
    65  		}
    66  	}
    67  	return c.Conn.Read(b)
    68  }
    69  
    70  func (c *HTTPConn) Write(b []byte) (int, error) {
    71  	if !c.requestWritten {
    72  		err := c.writeRequest(b)
    73  		if err != nil {
    74  			return 0, E.Cause(err, "write request")
    75  		}
    76  		c.requestWritten = true
    77  		return len(b), nil
    78  	}
    79  	return c.Conn.Write(b)
    80  }
    81  
    82  func (c *HTTPConn) writeRequest(payload []byte) error {
    83  	writer := bufio.NewBufferedWriter(c.Conn, buf.New())
    84  	const CRLF = "\r\n"
    85  	_, err := writer.Write([]byte(F.ToString(c.request.Method, " ", c.request.URL.RequestURI(), " HTTP/1.1", CRLF)))
    86  	if err != nil {
    87  		return err
    88  	}
    89  	if c.request.Header.Get("Host") == "" {
    90  		c.request.Header.Set("Host", c.request.Host)
    91  	}
    92  	for key, value := range c.request.Header {
    93  		_, err = writer.Write([]byte(F.ToString(key, ": ", strings.Join(value, ", "), CRLF)))
    94  		if err != nil {
    95  			return err
    96  		}
    97  	}
    98  	_, err = writer.Write([]byte(CRLF))
    99  	if err != nil {
   100  		return err
   101  	}
   102  	_, err = writer.Write(payload)
   103  	if err != nil {
   104  		return err
   105  	}
   106  	err = writer.Fallthrough()
   107  	if err != nil {
   108  		return err
   109  	}
   110  	return nil
   111  }
   112  
   113  func (c *HTTPConn) ReaderReplaceable() bool {
   114  	return c.responseRead
   115  }
   116  
   117  func (c *HTTPConn) WriterReplaceable() bool {
   118  	return c.requestWritten
   119  }
   120  
   121  func (c *HTTPConn) NeedHandshake() bool {
   122  	return !c.requestWritten
   123  }
   124  
   125  func (c *HTTPConn) Upstream() any {
   126  	return c.Conn
   127  }
   128  
   129  type HTTP2Conn struct {
   130  	reader io.Reader
   131  	writer io.Writer
   132  	create chan struct{}
   133  	err    error
   134  }
   135  
   136  func NewHTTPConn(reader io.Reader, writer io.Writer) HTTP2Conn {
   137  	return HTTP2Conn{
   138  		reader: reader,
   139  		writer: writer,
   140  	}
   141  }
   142  
   143  func NewLateHTTPConn(writer io.Writer) *HTTP2Conn {
   144  	return &HTTP2Conn{
   145  		create: make(chan struct{}),
   146  		writer: writer,
   147  	}
   148  }
   149  
   150  func (c *HTTP2Conn) Setup(reader io.Reader, err error) {
   151  	c.reader = reader
   152  	c.err = err
   153  	close(c.create)
   154  }
   155  
   156  func (c *HTTP2Conn) Read(b []byte) (n int, err error) {
   157  	if c.reader == nil {
   158  		<-c.create
   159  		if c.err != nil {
   160  			return 0, c.err
   161  		}
   162  	}
   163  	n, err = c.reader.Read(b)
   164  	return n, baderror.WrapH2(err)
   165  }
   166  
   167  func (c *HTTP2Conn) Write(b []byte) (n int, err error) {
   168  	n, err = c.writer.Write(b)
   169  	return n, baderror.WrapH2(err)
   170  }
   171  
   172  func (c *HTTP2Conn) Close() error {
   173  	return common.Close(c.reader, c.writer)
   174  }
   175  
   176  func (c *HTTP2Conn) LocalAddr() net.Addr {
   177  	return nil
   178  }
   179  
   180  func (c *HTTP2Conn) RemoteAddr() net.Addr {
   181  	return nil
   182  }
   183  
   184  func (c *HTTP2Conn) SetDeadline(t time.Time) error {
   185  	return os.ErrInvalid
   186  }
   187  
   188  func (c *HTTP2Conn) SetReadDeadline(t time.Time) error {
   189  	return os.ErrInvalid
   190  }
   191  
   192  func (c *HTTP2Conn) SetWriteDeadline(t time.Time) error {
   193  	return os.ErrInvalid
   194  }
   195  
   196  func (c *HTTP2Conn) NeedAdditionalReadDeadline() bool {
   197  	return true
   198  }
   199  
   200  type ServerHTTPConn struct {
   201  	HTTP2Conn
   202  	flusher http.Flusher
   203  }
   204  
   205  func (c *ServerHTTPConn) Write(b []byte) (n int, err error) {
   206  	n, err = c.writer.Write(b)
   207  	if err == nil {
   208  		c.flusher.Flush()
   209  	}
   210  	return
   211  }
   212  
   213  type HTTP2ConnWrapper struct {
   214  	N.ExtendedConn
   215  	access sync.Mutex
   216  	closed bool
   217  }
   218  
   219  func NewHTTP2Wrapper(conn net.Conn) *HTTP2ConnWrapper {
   220  	return &HTTP2ConnWrapper{
   221  		ExtendedConn: bufio.NewExtendedConn(conn),
   222  	}
   223  }
   224  
   225  func (w *HTTP2ConnWrapper) Write(p []byte) (n int, err error) {
   226  	w.access.Lock()
   227  	defer w.access.Unlock()
   228  	if w.closed {
   229  		return 0, net.ErrClosed
   230  	}
   231  	return w.ExtendedConn.Write(p)
   232  }
   233  
   234  func (w *HTTP2ConnWrapper) WriteBuffer(buffer *buf.Buffer) error {
   235  	w.access.Lock()
   236  	defer w.access.Unlock()
   237  	if w.closed {
   238  		return net.ErrClosed
   239  	}
   240  	return w.ExtendedConn.WriteBuffer(buffer)
   241  }
   242  
   243  func (w *HTTP2ConnWrapper) CloseWrapper() {
   244  	w.access.Lock()
   245  	defer w.access.Unlock()
   246  	w.closed = true
   247  }
   248  
   249  func (w *HTTP2ConnWrapper) Upstream() any {
   250  	return w.ExtendedConn
   251  }