| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- package http
- import (
- "bytes"
- "errors"
- "io"
- "net"
- "net/http"
- "strings"
- "time"
- "v2ray.com/core/common/buf"
- "v2ray.com/core/common/serial"
- "v2ray.com/core/transport/internet"
- )
- const (
- CRLF = "\r\n"
- ENDING = CRLF + CRLF
- // max length of HTTP header. Safety precaution for DDoS attack.
- maxHeaderLength = 8192
- )
- var (
- ErrHeaderToLong = errors.New("Header too long.")
- writeCRLF = serial.WriteString(CRLF)
- )
- type Reader interface {
- Read(io.Reader) (*buf.Buffer, error)
- }
- type Writer interface {
- Write(io.Writer) error
- }
- type NoOpReader struct{}
- func (v *NoOpReader) Read(io.Reader) (*buf.Buffer, error) {
- return nil, nil
- }
- type NoOpWriter struct{}
- func (v *NoOpWriter) Write(io.Writer) error {
- return nil
- }
- type HeaderReader struct {
- }
- func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
- buffer := buf.NewSmall()
- totalBytes := 0
- endingDetected := false
- for totalBytes < maxHeaderLength {
- err := buffer.AppendSupplier(buf.ReadFrom(reader))
- if err != nil {
- return nil, err
- }
- if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
- buffer.SliceFrom(n + len(ENDING))
- endingDetected = true
- break
- }
- if buffer.Len() >= len(ENDING) {
- totalBytes += buffer.Len() - len(ENDING)
- leftover := buffer.BytesFrom(-len(ENDING))
- buffer.Reset(func(b []byte) (int, error) {
- return copy(b, leftover), nil
- })
- }
- }
- if buffer.IsEmpty() {
- buffer.Release()
- return nil, nil
- }
- if !endingDetected {
- buffer.Release()
- return nil, ErrHeaderToLong
- }
- return buffer, nil
- }
- type HeaderWriter struct {
- header *buf.Buffer
- }
- func NewHeaderWriter(header *buf.Buffer) *HeaderWriter {
- return &HeaderWriter{
- header: header,
- }
- }
- func (v *HeaderWriter) Write(writer io.Writer) error {
- if v.header == nil {
- return nil
- }
- _, err := writer.Write(v.header.Bytes())
- v.header.Release()
- v.header = nil
- return err
- }
- type HttpConn struct {
- net.Conn
- readBuffer *buf.Buffer
- oneTimeReader Reader
- oneTimeWriter Writer
- isServer bool
- }
- func NewHttpConn(conn net.Conn, reader Reader, writer Writer, isServer bool) *HttpConn {
- return &HttpConn{
- Conn: conn,
- oneTimeReader: reader,
- oneTimeWriter: writer,
- isServer: isServer,
- }
- }
- func (v *HttpConn) Read(b []byte) (int, error) {
- if v.oneTimeReader != nil {
- buffer, err := v.oneTimeReader.Read(v.Conn)
- if err != nil {
- return 0, err
- }
- v.readBuffer = buffer
- v.oneTimeReader = nil
- }
- if v.readBuffer.Len() > 0 {
- nBytes, err := v.readBuffer.Read(b)
- if nBytes == v.readBuffer.Len() {
- v.readBuffer.Release()
- v.readBuffer = nil
- }
- return nBytes, err
- }
- return v.Conn.Read(b)
- }
- func (v *HttpConn) Write(b []byte) (int, error) {
- if v.oneTimeWriter != nil {
- err := v.oneTimeWriter.Write(v.Conn)
- v.oneTimeWriter = nil
- if err != nil {
- return 0, err
- }
- }
- return v.Conn.Write(b)
- }
- // Close implements net.Conn.Close().
- func (v *HttpConn) Close() error {
- if v.isServer && v.oneTimeWriter != nil {
- // Connection is being closed but header wasn't sent. This means the client request
- // is probably not valid. Sending back a server error header in this case.
- writer := formResponseHeader(&ResponseConfig{
- Version: &Version{
- Value: "1.1",
- },
- Status: &Status{
- Code: "500",
- Reason: "Internal Server Error",
- },
- Header: []*Header{
- {
- Name: "Connection",
- Value: []string{"close"},
- },
- {
- Name: "Cache-Control",
- Value: []string{"private"},
- },
- {
- Name: "Content-Length",
- Value: []string{"0"},
- },
- },
- })
- writer.Write(v.Conn)
- }
- return v.Conn.Close()
- }
- func formResponseHeader(config *ResponseConfig) *HeaderWriter {
- header := buf.NewSmall()
- header.AppendSupplier(serial.WriteString(strings.Join([]string{config.GetFullVersion(), config.Status.GetCode(), config.Status.GetReason()}, " ")))
- header.AppendSupplier(writeCRLF)
- headers := config.PickHeaders()
- for _, h := range headers {
- header.AppendSupplier(serial.WriteString(h))
- header.AppendSupplier(writeCRLF)
- }
- if !config.HasHeader("Date") {
- header.AppendSupplier(serial.WriteString("Date: "))
- header.AppendSupplier(serial.WriteString(time.Now().Format(http.TimeFormat)))
- header.AppendSupplier(writeCRLF)
- }
- header.AppendSupplier(writeCRLF)
- return &HeaderWriter{
- header: header,
- }
- }
- type HttpAuthenticator struct {
- config *Config
- }
- func (v HttpAuthenticator) GetClientWriter() *HeaderWriter {
- header := buf.NewSmall()
- config := v.config.Request
- header.AppendSupplier(serial.WriteString(strings.Join([]string{config.Method.GetValue(), config.PickUri(), config.GetFullVersion()}, " ")))
- header.AppendSupplier(writeCRLF)
- headers := config.PickHeaders()
- for _, h := range headers {
- header.AppendSupplier(serial.WriteString(h))
- header.AppendSupplier(writeCRLF)
- }
- header.AppendSupplier(writeCRLF)
- return &HeaderWriter{
- header: header,
- }
- }
- func (v HttpAuthenticator) GetServerWriter() *HeaderWriter {
- return formResponseHeader(v.config.Response)
- }
- func (v HttpAuthenticator) Client(conn net.Conn) net.Conn {
- if v.config.Request == nil && v.config.Response == nil {
- return conn
- }
- var reader Reader = new(NoOpReader)
- if v.config.Request != nil {
- reader = new(HeaderReader)
- }
- var writer Writer = new(NoOpWriter)
- if v.config.Response != nil {
- writer = v.GetClientWriter()
- }
- return NewHttpConn(conn, reader, writer, false)
- }
- func (v HttpAuthenticator) Server(conn net.Conn) net.Conn {
- if v.config.Request == nil && v.config.Response == nil {
- return conn
- }
- return NewHttpConn(conn, new(HeaderReader), v.GetServerWriter(), true)
- }
- type HttpAuthenticatorFactory struct{}
- func (HttpAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
- return HttpAuthenticator{
- config: config.(*Config),
- }
- }
- func init() {
- internet.RegisterConnectionAuthenticator(serial.GetMessageType(new(Config)), HttpAuthenticatorFactory{})
- }
|