273 lines
5.9 KiB
Go
Raw Normal View History

2016-10-31 22:26:46 +01:00
package http
2017-04-09 01:43:25 +02:00
//go:generate go run $GOPATH/src/v2ray.com/core/tools/generrorgen/main.go -pkg http -path Transport,Internet,Headers,HTTP
2016-10-31 22:26:46 +01:00
import (
"bytes"
2017-01-12 22:47:10 +01:00
"context"
2016-11-03 23:14:27 +01:00
"io"
2016-11-02 22:26:21 +01:00
"net"
2016-11-06 13:38:32 +01:00
"net/http"
2016-12-06 11:03:42 +01:00
"strings"
2016-11-06 13:38:32 +01:00
"time"
2016-12-09 12:08:25 +01:00
2017-01-12 22:47:10 +01:00
"v2ray.com/core/common"
2016-12-09 11:35:27 +01:00
"v2ray.com/core/common/buf"
2016-12-06 11:03:42 +01:00
"v2ray.com/core/common/serial"
2016-10-31 22:26:46 +01:00
)
const (
CRLF = "\r\n"
ENDING = CRLF + CRLF
2016-12-16 17:01:47 +01:00
2016-12-19 12:16:57 +01:00
// max length of HTTP header. Safety precaution for DDoS attack.
2016-12-16 17:01:47 +01:00
maxHeaderLength = 8192
2016-10-31 22:26:46 +01:00
)
2016-12-06 11:03:42 +01:00
var (
2017-04-09 01:43:25 +02:00
ErrHeaderToLong = newError("Header too long.")
2016-12-19 12:16:57 +01:00
writeCRLF = serial.WriteString(CRLF)
2016-12-06 11:03:42 +01:00
)
2016-11-05 01:50:51 +01:00
type Reader interface {
2016-12-09 11:35:27 +01:00
Read(io.Reader) (*buf.Buffer, error)
2016-11-05 01:50:51 +01:00
}
type Writer interface {
Write(io.Writer) error
}
type NoOpReader struct{}
2016-12-09 11:35:27 +01:00
func (v *NoOpReader) Read(io.Reader) (*buf.Buffer, error) {
2016-11-05 01:50:51 +01:00
return nil, nil
}
type NoOpWriter struct{}
2016-11-27 21:39:09 +01:00
func (v *NoOpWriter) Write(io.Writer) error {
2016-11-05 01:50:51 +01:00
return nil
}
2016-11-03 23:14:27 +01:00
type HeaderReader struct {
}
2016-12-09 11:35:27 +01:00
func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
2017-04-15 21:19:21 +02:00
buffer := buf.New()
2016-12-16 17:01:47 +01:00
totalBytes := 0
2016-12-19 12:16:57 +01:00
endingDetected := false
2016-12-16 17:01:47 +01:00
for totalBytes < maxHeaderLength {
2016-12-09 12:08:25 +01:00
err := buffer.AppendSupplier(buf.ReadFrom(reader))
2016-11-03 23:14:27 +01:00
if err != nil {
return nil, err
}
2016-12-06 11:03:42 +01:00
if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
2016-11-03 23:14:27 +01:00
buffer.SliceFrom(n + len(ENDING))
2016-12-19 12:16:57 +01:00
endingDetected = true
2016-11-03 23:14:27 +01:00
break
}
if buffer.Len() >= len(ENDING) {
2016-12-16 17:01:47 +01:00
totalBytes += buffer.Len() - len(ENDING)
leftover := buffer.BytesFrom(-len(ENDING))
2016-12-11 21:43:16 +01:00
buffer.Reset(func(b []byte) (int, error) {
return copy(b, leftover), nil
})
2016-11-03 23:14:27 +01:00
}
}
2016-11-05 01:50:51 +01:00
if buffer.IsEmpty() {
buffer.Release()
return nil, nil
}
2016-12-19 12:16:57 +01:00
if !endingDetected {
buffer.Release()
return nil, ErrHeaderToLong
}
2016-11-03 23:14:27 +01:00
return buffer, nil
}
type HeaderWriter struct {
2016-12-09 11:35:27 +01:00
header *buf.Buffer
2016-11-03 23:14:27 +01:00
}
2016-12-09 11:35:27 +01:00
func NewHeaderWriter(header *buf.Buffer) *HeaderWriter {
2016-11-04 21:59:19 +01:00
return &HeaderWriter{
header: header,
}
}
2017-04-13 22:17:58 +02:00
func (w *HeaderWriter) Write(writer io.Writer) error {
if w.header == nil {
2016-11-03 23:14:27 +01:00
return nil
}
2017-04-13 22:17:58 +02:00
_, err := writer.Write(w.header.Bytes())
w.header.Release()
w.header = nil
2016-11-03 23:14:27 +01:00
return err
}
2016-11-02 22:26:21 +01:00
type HttpConn struct {
net.Conn
2016-12-09 11:35:27 +01:00
readBuffer *buf.Buffer
2016-11-05 01:50:51 +01:00
oneTimeReader Reader
oneTimeWriter Writer
2017-01-03 23:09:51 +01:00
errorWriter Writer
2016-10-31 22:26:46 +01:00
}
2017-01-03 23:09:51 +01:00
func NewHttpConn(conn net.Conn, reader Reader, writer Writer, errorWriter Writer) *HttpConn {
2016-11-02 22:26:21 +01:00
return &HttpConn{
2016-11-03 23:14:27 +01:00
Conn: conn,
oneTimeReader: reader,
oneTimeWriter: writer,
2017-01-03 23:09:51 +01:00
errorWriter: errorWriter,
2016-11-02 22:26:21 +01:00
}
}
2016-10-31 22:26:46 +01:00
2017-04-13 22:17:58 +02:00
func (c *HttpConn) Read(b []byte) (int, error) {
if c.oneTimeReader != nil {
buffer, err := c.oneTimeReader.Read(c.Conn)
2016-11-03 23:14:27 +01:00
if err != nil {
return 0, err
2016-11-02 22:26:21 +01:00
}
2017-04-13 22:17:58 +02:00
c.readBuffer = buffer
c.oneTimeReader = nil
2016-10-31 22:26:46 +01:00
}
2017-04-13 22:17:58 +02:00
if c.readBuffer.Len() > 0 {
nBytes, err := c.readBuffer.Read(b)
if nBytes == c.readBuffer.Len() {
c.readBuffer.Release()
c.readBuffer = nil
2016-11-02 22:26:21 +01:00
}
return nBytes, err
}
2016-10-31 22:26:46 +01:00
2017-04-13 22:17:58 +02:00
return c.Conn.Read(b)
2016-10-31 22:26:46 +01:00
}
2017-04-13 22:17:58 +02:00
func (c *HttpConn) Write(b []byte) (int, error) {
if c.oneTimeWriter != nil {
err := c.oneTimeWriter.Write(c.Conn)
c.oneTimeWriter = nil
2016-10-31 22:26:46 +01:00
if err != nil {
2016-11-02 22:26:21 +01:00
return 0, err
2016-10-31 22:26:46 +01:00
}
}
2017-04-13 22:17:58 +02:00
return c.Conn.Write(b)
2016-10-31 22:26:46 +01:00
}
2016-12-14 12:25:22 +01:00
// Close implements net.Conn.Close().
2017-04-13 22:17:58 +02:00
func (c *HttpConn) Close() error {
if c.oneTimeWriter != nil && c.errorWriter != nil {
2016-12-14 12:25:22 +01:00
// 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.
2017-04-13 22:17:58 +02:00
c.errorWriter.Write(c.Conn)
2016-12-14 12:25:22 +01:00
}
2017-04-13 22:17:58 +02:00
return c.Conn.Close()
2016-10-31 22:26:46 +01:00
}
2016-12-14 12:25:22 +01:00
func formResponseHeader(config *ResponseConfig) *HeaderWriter {
2017-04-15 21:19:21 +02:00
header := buf.New()
2016-12-23 12:42:25 +01:00
header.AppendSupplier(serial.WriteString(strings.Join([]string{config.GetFullVersion(), config.GetStatusValue().Code, config.GetStatusValue().Reason}, " ")))
2016-12-09 12:08:25 +01:00
header.AppendSupplier(writeCRLF)
2016-10-31 22:26:46 +01:00
2016-11-02 22:26:21 +01:00
headers := config.PickHeaders()
for _, h := range headers {
2016-12-09 12:08:25 +01:00
header.AppendSupplier(serial.WriteString(h))
header.AppendSupplier(writeCRLF)
2016-10-31 22:26:46 +01:00
}
2016-12-14 12:25:22 +01:00
if !config.HasHeader("Date") {
header.AppendSupplier(serial.WriteString("Date: "))
header.AppendSupplier(serial.WriteString(time.Now().Format(http.TimeFormat)))
header.AppendSupplier(writeCRLF)
}
2016-12-09 12:08:25 +01:00
header.AppendSupplier(writeCRLF)
2016-11-03 23:14:27 +01:00
return &HeaderWriter{
header: header,
}
2016-10-31 22:26:46 +01:00
}
2016-12-14 12:25:22 +01:00
type HttpAuthenticator struct {
config *Config
}
2017-04-13 22:17:58 +02:00
func (a HttpAuthenticator) GetClientWriter() *HeaderWriter {
2017-04-15 21:19:21 +02:00
header := buf.New()
2017-04-13 22:17:58 +02:00
config := a.config.Request
2016-12-23 12:42:25 +01:00
header.AppendSupplier(serial.WriteString(strings.Join([]string{config.GetMethodValue(), config.PickUri(), config.GetFullVersion()}, " ")))
2016-12-09 12:08:25 +01:00
header.AppendSupplier(writeCRLF)
2016-10-31 22:26:46 +01:00
2016-11-02 22:26:21 +01:00
headers := config.PickHeaders()
2016-10-31 22:26:46 +01:00
for _, h := range headers {
2016-12-09 12:08:25 +01:00
header.AppendSupplier(serial.WriteString(h))
header.AppendSupplier(writeCRLF)
2016-11-06 13:38:32 +01:00
}
2016-12-09 12:08:25 +01:00
header.AppendSupplier(writeCRLF)
2016-11-03 23:14:27 +01:00
return &HeaderWriter{
header: header,
}
2016-11-02 22:26:21 +01:00
}
2016-10-31 22:26:46 +01:00
2017-04-13 22:17:58 +02:00
func (a HttpAuthenticator) GetServerWriter() *HeaderWriter {
return formResponseHeader(a.config.Response)
2016-12-14 12:25:22 +01:00
}
2017-04-13 22:17:58 +02:00
func (a HttpAuthenticator) Client(conn net.Conn) net.Conn {
if a.config.Request == nil && a.config.Response == nil {
2016-11-03 23:14:27 +01:00
return conn
}
2016-11-05 01:50:51 +01:00
var reader Reader = new(NoOpReader)
2017-04-13 22:17:58 +02:00
if a.config.Request != nil {
2016-11-05 01:50:51 +01:00
reader = new(HeaderReader)
}
var writer Writer = new(NoOpWriter)
2017-04-13 22:17:58 +02:00
if a.config.Response != nil {
writer = a.GetClientWriter()
2016-11-05 01:50:51 +01:00
}
2017-01-03 23:09:51 +01:00
return NewHttpConn(conn, reader, writer, new(NoOpWriter))
2016-10-31 22:26:46 +01:00
}
2017-04-13 22:17:58 +02:00
func (a HttpAuthenticator) Server(conn net.Conn) net.Conn {
if a.config.Request == nil && a.config.Response == nil {
2016-11-03 23:14:27 +01:00
return conn
}
2017-04-13 22:17:58 +02:00
return NewHttpConn(conn, new(HeaderReader), a.GetServerWriter(), formResponseHeader(&ResponseConfig{
2017-01-03 23:09:51 +01:00
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"},
},
},
}))
2016-10-31 22:26:46 +01:00
}
2016-11-01 00:42:55 +01:00
2017-01-13 13:47:44 +01:00
func NewHttpAuthenticator(ctx context.Context, config *Config) (HttpAuthenticator, error) {
2017-01-12 22:47:10 +01:00
return HttpAuthenticator{
2017-01-13 13:47:44 +01:00
config: config,
2017-01-12 22:47:10 +01:00
}, nil
}
2016-11-01 00:42:55 +01:00
func init() {
2017-01-13 13:47:44 +01:00
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
return NewHttpAuthenticator(ctx, config.(*Config))
}))
2016-11-01 00:42:55 +01:00
}