github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/headers/http/http.go (about)

     1  package http
     2  
     3  //go:generate go run v2ray.com/core/common/errors/errorgen
     4  
     5  import (
     6  	"bufio"
     7  	"bytes"
     8  	"context"
     9  	"io"
    10  	"net"
    11  	"net/http"
    12  	"strings"
    13  	"time"
    14  
    15  	"v2ray.com/core/common"
    16  	"v2ray.com/core/common/buf"
    17  )
    18  
    19  const (
    20  	// CRLF is the line ending in HTTP header
    21  	CRLF = "\r\n"
    22  
    23  	// ENDING is the double line ending between HTTP header and body.
    24  	ENDING = CRLF + CRLF
    25  
    26  	// max length of HTTP header. Safety precaution for DDoS attack.
    27  	maxHeaderLength = 8192
    28  )
    29  
    30  var (
    31  	ErrHeaderToLong = newError("Header too long.")
    32  
    33  	ErrHeaderMisMatch = newError("Header Mismatch.")
    34  )
    35  
    36  type Reader interface {
    37  	Read(io.Reader) (*buf.Buffer, error)
    38  }
    39  
    40  type Writer interface {
    41  	Write(io.Writer) error
    42  }
    43  
    44  type NoOpReader struct{}
    45  
    46  func (NoOpReader) Read(io.Reader) (*buf.Buffer, error) {
    47  	return nil, nil
    48  }
    49  
    50  type NoOpWriter struct{}
    51  
    52  func (NoOpWriter) Write(io.Writer) error {
    53  	return nil
    54  }
    55  
    56  type HeaderReader struct {
    57  	req            *http.Request
    58  	expectedHeader *RequestConfig
    59  }
    60  
    61  func (h *HeaderReader) ExpectThisRequest(expectedHeader *RequestConfig) *HeaderReader {
    62  	h.expectedHeader = expectedHeader
    63  	return h
    64  }
    65  
    66  func (h *HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
    67  	buffer := buf.New()
    68  	totalBytes := int32(0)
    69  	endingDetected := false
    70  
    71  	var headerBuf bytes.Buffer
    72  
    73  	for totalBytes < maxHeaderLength {
    74  		_, err := buffer.ReadFrom(reader)
    75  		if err != nil {
    76  			buffer.Release()
    77  			return nil, err
    78  		}
    79  		if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
    80  			headerBuf.Write(buffer.BytesRange(0, int32(n+len(ENDING))))
    81  			buffer.Advance(int32(n + len(ENDING)))
    82  			endingDetected = true
    83  			break
    84  		}
    85  		lenEnding := int32(len(ENDING))
    86  		if buffer.Len() >= lenEnding {
    87  			totalBytes += buffer.Len() - lenEnding
    88  			headerBuf.Write(buffer.BytesRange(0, buffer.Len()-lenEnding))
    89  			leftover := buffer.BytesFrom(-lenEnding)
    90  			buffer.Clear()
    91  			copy(buffer.Extend(lenEnding), leftover)
    92  
    93  			if _, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes())), false); err != io.ErrUnexpectedEOF {
    94  				return nil, err
    95  			}
    96  		}
    97  	}
    98  
    99  	if !endingDetected {
   100  		buffer.Release()
   101  		return nil, ErrHeaderToLong
   102  	}
   103  
   104  	if h.expectedHeader == nil {
   105  		if buffer.IsEmpty() {
   106  			buffer.Release()
   107  			return nil, nil
   108  		}
   109  		return buffer, nil
   110  	}
   111  
   112  	//Parse the request
   113  
   114  	if req, err := readRequest(bufio.NewReader(bytes.NewReader(headerBuf.Bytes())), false); err != nil {
   115  		return nil, err
   116  	} else {
   117  		h.req = req
   118  	}
   119  
   120  	//Check req
   121  	path := h.req.URL.Path
   122  	hasThisUri := false
   123  	for _, u := range h.expectedHeader.Uri {
   124  		if u == path {
   125  			hasThisUri = true
   126  		}
   127  	}
   128  
   129  	if !hasThisUri {
   130  		return nil, ErrHeaderMisMatch
   131  	}
   132  
   133  	if buffer.IsEmpty() {
   134  		buffer.Release()
   135  		return nil, nil
   136  	}
   137  
   138  	return buffer, nil
   139  }
   140  
   141  type HeaderWriter struct {
   142  	header *buf.Buffer
   143  }
   144  
   145  func NewHeaderWriter(header *buf.Buffer) *HeaderWriter {
   146  	return &HeaderWriter{
   147  		header: header,
   148  	}
   149  }
   150  
   151  func (w *HeaderWriter) Write(writer io.Writer) error {
   152  	if w.header == nil {
   153  		return nil
   154  	}
   155  	err := buf.WriteAllBytes(writer, w.header.Bytes())
   156  	w.header.Release()
   157  	w.header = nil
   158  	return err
   159  }
   160  
   161  type HttpConn struct {
   162  	net.Conn
   163  
   164  	readBuffer          *buf.Buffer
   165  	oneTimeReader       Reader
   166  	oneTimeWriter       Writer
   167  	errorWriter         Writer
   168  	errorMismatchWriter Writer
   169  	errorTooLongWriter  Writer
   170  
   171  	errReason error
   172  }
   173  
   174  func NewHttpConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer, errorMismatchWriter Writer, errorTooLongWriter Writer) *HttpConn {
   175  	return &HttpConn{
   176  		Conn:                conn,
   177  		oneTimeReader:       reader,
   178  		oneTimeWriter:       writer,
   179  		errorWriter:         errorWriter,
   180  		errorMismatchWriter: errorMismatchWriter,
   181  		errorTooLongWriter:  errorTooLongWriter,
   182  	}
   183  }
   184  
   185  func (c *HttpConn) Read(b []byte) (int, error) {
   186  	if c.oneTimeReader != nil {
   187  		buffer, err := c.oneTimeReader.Read(c.Conn)
   188  		if err != nil {
   189  			c.errReason = err
   190  			return 0, err
   191  		}
   192  		c.readBuffer = buffer
   193  		c.oneTimeReader = nil
   194  	}
   195  
   196  	if !c.readBuffer.IsEmpty() {
   197  		nBytes, _ := c.readBuffer.Read(b)
   198  		if c.readBuffer.IsEmpty() {
   199  			c.readBuffer.Release()
   200  			c.readBuffer = nil
   201  		}
   202  		return nBytes, nil
   203  	}
   204  
   205  	return c.Conn.Read(b)
   206  }
   207  
   208  // Write implements io.Writer.
   209  func (c *HttpConn) Write(b []byte) (int, error) {
   210  	if c.oneTimeWriter != nil {
   211  		err := c.oneTimeWriter.Write(c.Conn)
   212  		c.oneTimeWriter = nil
   213  		if err != nil {
   214  			return 0, err
   215  		}
   216  	}
   217  
   218  	return c.Conn.Write(b)
   219  }
   220  
   221  // Close implements net.Conn.Close().
   222  func (c *HttpConn) Close() error {
   223  	if c.oneTimeWriter != nil && c.errorWriter != nil {
   224  		// Connection is being closed but header wasn't sent. This means the client request
   225  		// is probably not valid. Sending back a server error header in this case.
   226  
   227  		//Write response based on error reason
   228  
   229  		if c.errReason == ErrHeaderMisMatch {
   230  			c.errorMismatchWriter.Write(c.Conn)
   231  		} else if c.errReason == ErrHeaderToLong {
   232  			c.errorTooLongWriter.Write(c.Conn)
   233  		} else {
   234  			c.errorWriter.Write(c.Conn)
   235  		}
   236  	}
   237  
   238  	return c.Conn.Close()
   239  }
   240  
   241  func formResponseHeader(config *ResponseConfig) *HeaderWriter {
   242  	header := buf.New()
   243  	common.Must2(header.WriteString(strings.Join([]string{config.GetFullVersion(), config.GetStatusValue().Code, config.GetStatusValue().Reason}, " ")))
   244  	common.Must2(header.WriteString(CRLF))
   245  
   246  	headers := config.PickHeaders()
   247  	for _, h := range headers {
   248  		common.Must2(header.WriteString(h))
   249  		common.Must2(header.WriteString(CRLF))
   250  	}
   251  	if !config.HasHeader("Date") {
   252  		common.Must2(header.WriteString("Date: "))
   253  		common.Must2(header.WriteString(time.Now().Format(http.TimeFormat)))
   254  		common.Must2(header.WriteString(CRLF))
   255  	}
   256  	common.Must2(header.WriteString(CRLF))
   257  	return &HeaderWriter{
   258  		header: header,
   259  	}
   260  }
   261  
   262  type HttpAuthenticator struct {
   263  	config *Config
   264  }
   265  
   266  func (a HttpAuthenticator) GetClientWriter() *HeaderWriter {
   267  	header := buf.New()
   268  	config := a.config.Request
   269  	common.Must2(header.WriteString(strings.Join([]string{config.GetMethodValue(), config.PickUri(), config.GetFullVersion()}, " ")))
   270  	common.Must2(header.WriteString(CRLF))
   271  
   272  	headers := config.PickHeaders()
   273  	for _, h := range headers {
   274  		common.Must2(header.WriteString(h))
   275  		common.Must2(header.WriteString(CRLF))
   276  	}
   277  	common.Must2(header.WriteString(CRLF))
   278  	return &HeaderWriter{
   279  		header: header,
   280  	}
   281  }
   282  
   283  func (a HttpAuthenticator) GetServerWriter() *HeaderWriter {
   284  	return formResponseHeader(a.config.Response)
   285  }
   286  
   287  func (a HttpAuthenticator) Client(conn net.Conn) net.Conn {
   288  	if a.config.Request == nil && a.config.Response == nil {
   289  		return conn
   290  	}
   291  	var reader Reader = NoOpReader{}
   292  	if a.config.Request != nil {
   293  		reader = new(HeaderReader)
   294  	}
   295  
   296  	var writer Writer = NoOpWriter{}
   297  	if a.config.Response != nil {
   298  		writer = a.GetClientWriter()
   299  	}
   300  	return NewHttpConn(conn, reader, writer, NoOpWriter{}, NoOpWriter{}, NoOpWriter{})
   301  }
   302  
   303  func (a HttpAuthenticator) Server(conn net.Conn) net.Conn {
   304  	if a.config.Request == nil && a.config.Response == nil {
   305  		return conn
   306  	}
   307  	return NewHttpConn(conn, new(HeaderReader).ExpectThisRequest(a.config.Request), a.GetServerWriter(),
   308  		formResponseHeader(resp400),
   309  		formResponseHeader(resp404),
   310  		formResponseHeader(resp400))
   311  }
   312  
   313  func NewHttpAuthenticator(ctx context.Context, config *Config) (HttpAuthenticator, error) {
   314  	return HttpAuthenticator{
   315  		config: config,
   316  	}, nil
   317  }
   318  
   319  func init() {
   320  	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
   321  		return NewHttpAuthenticator(ctx, config.(*Config))
   322  	}))
   323  }