2016-10-31 21:26:46 +00:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2016-11-03 22:14:27 +00:00
|
|
|
"io"
|
2016-11-02 21:26:21 +00:00
|
|
|
"net"
|
2016-11-06 12:38:32 +00:00
|
|
|
"net/http"
|
2016-12-06 10:03:42 +00:00
|
|
|
"strings"
|
2016-11-06 12:38:32 +00:00
|
|
|
"time"
|
2016-12-09 10:35:27 +00:00
|
|
|
"v2ray.com/core/common/buf"
|
2016-10-31 23:42:55 +00:00
|
|
|
"v2ray.com/core/common/loader"
|
2016-12-06 10:03:42 +00:00
|
|
|
"v2ray.com/core/common/serial"
|
2016-10-31 21:26:46 +00:00
|
|
|
"v2ray.com/core/transport/internet"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
CRLF = "\r\n"
|
|
|
|
ENDING = CRLF + CRLF
|
|
|
|
)
|
|
|
|
|
2016-12-06 10:03:42 +00:00
|
|
|
var (
|
|
|
|
writeCRLF = serial.WriteString(CRLF)
|
|
|
|
)
|
|
|
|
|
2016-11-05 00:50:51 +00:00
|
|
|
type Reader interface {
|
2016-12-09 10:35:27 +00:00
|
|
|
Read(io.Reader) (*buf.Buffer, error)
|
2016-11-05 00:50:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Writer interface {
|
|
|
|
Write(io.Writer) error
|
|
|
|
}
|
|
|
|
|
|
|
|
type NoOpReader struct{}
|
|
|
|
|
2016-12-09 10:35:27 +00:00
|
|
|
func (v *NoOpReader) Read(io.Reader) (*buf.Buffer, error) {
|
2016-11-05 00:50:51 +00:00
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type NoOpWriter struct{}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v *NoOpWriter) Write(io.Writer) error {
|
2016-11-05 00:50:51 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-11-03 22:14:27 +00:00
|
|
|
type HeaderReader struct {
|
|
|
|
}
|
|
|
|
|
2016-12-09 10:35:27 +00:00
|
|
|
func (*HeaderReader) Read(reader io.Reader) (*buf.Buffer, error) {
|
|
|
|
buffer := buf.NewSmallBuffer()
|
2016-11-03 22:14:27 +00:00
|
|
|
for {
|
|
|
|
_, err := buffer.FillFrom(reader)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-12-06 10:03:42 +00:00
|
|
|
if n := bytes.Index(buffer.Bytes(), []byte(ENDING)); n != -1 {
|
2016-11-03 22:14:27 +00:00
|
|
|
buffer.SliceFrom(n + len(ENDING))
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if buffer.Len() >= len(ENDING) {
|
2016-12-06 10:03:42 +00:00
|
|
|
copy(buffer.Bytes(), buffer.BytesFrom(buffer.Len()-len(ENDING)))
|
2016-11-03 22:14:27 +00:00
|
|
|
buffer.Slice(0, len(ENDING))
|
|
|
|
}
|
|
|
|
}
|
2016-11-05 00:50:51 +00:00
|
|
|
if buffer.IsEmpty() {
|
|
|
|
buffer.Release()
|
|
|
|
return nil, nil
|
|
|
|
}
|
2016-11-03 22:14:27 +00:00
|
|
|
return buffer, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type HeaderWriter struct {
|
2016-12-09 10:35:27 +00:00
|
|
|
header *buf.Buffer
|
2016-11-03 22:14:27 +00:00
|
|
|
}
|
|
|
|
|
2016-12-09 10:35:27 +00:00
|
|
|
func NewHeaderWriter(header *buf.Buffer) *HeaderWriter {
|
2016-11-04 20:59:19 +00:00
|
|
|
return &HeaderWriter{
|
|
|
|
header: header,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v *HeaderWriter) Write(writer io.Writer) error {
|
|
|
|
if v.header == nil {
|
2016-11-03 22:14:27 +00:00
|
|
|
return nil
|
|
|
|
}
|
2016-12-06 10:03:42 +00:00
|
|
|
_, err := writer.Write(v.header.Bytes())
|
2016-11-27 20:39:09 +00:00
|
|
|
v.header.Release()
|
|
|
|
v.header = nil
|
2016-11-03 22:14:27 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-11-02 21:26:21 +00:00
|
|
|
type HttpConn struct {
|
|
|
|
net.Conn
|
|
|
|
|
2016-12-09 10:35:27 +00:00
|
|
|
readBuffer *buf.Buffer
|
2016-11-05 00:50:51 +00:00
|
|
|
oneTimeReader Reader
|
|
|
|
oneTimeWriter Writer
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-05 00:50:51 +00:00
|
|
|
func NewHttpConn(conn net.Conn, reader Reader, writer Writer) *HttpConn {
|
2016-11-02 21:26:21 +00:00
|
|
|
return &HttpConn{
|
2016-11-03 22:14:27 +00:00
|
|
|
Conn: conn,
|
|
|
|
oneTimeReader: reader,
|
|
|
|
oneTimeWriter: writer,
|
2016-11-02 21:26:21 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-31 21:26:46 +00:00
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v *HttpConn) Read(b []byte) (int, error) {
|
|
|
|
if v.oneTimeReader != nil {
|
|
|
|
buffer, err := v.oneTimeReader.Read(v.Conn)
|
2016-11-03 22:14:27 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
2016-11-02 21:26:21 +00:00
|
|
|
}
|
2016-11-27 20:39:09 +00:00
|
|
|
v.readBuffer = buffer
|
|
|
|
v.oneTimeReader = nil
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
if v.readBuffer.Len() > 0 {
|
|
|
|
nBytes, err := v.readBuffer.Read(b)
|
|
|
|
if nBytes == v.readBuffer.Len() {
|
|
|
|
v.readBuffer.Release()
|
|
|
|
v.readBuffer = nil
|
2016-11-02 21:26:21 +00:00
|
|
|
}
|
|
|
|
return nBytes, err
|
|
|
|
}
|
2016-10-31 21:26:46 +00:00
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
return v.Conn.Read(b)
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v *HttpConn) Write(b []byte) (int, error) {
|
|
|
|
if v.oneTimeWriter != nil {
|
|
|
|
err := v.oneTimeWriter.Write(v.Conn)
|
|
|
|
v.oneTimeWriter = nil
|
2016-10-31 21:26:46 +00:00
|
|
|
if err != nil {
|
2016-11-02 21:26:21 +00:00
|
|
|
return 0, err
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
return v.Conn.Write(b)
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-02 21:26:21 +00:00
|
|
|
type HttpAuthenticator struct {
|
|
|
|
config *Config
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v HttpAuthenticator) GetClientWriter() *HeaderWriter {
|
2016-12-09 10:35:27 +00:00
|
|
|
header := buf.NewSmallBuffer()
|
2016-11-27 20:39:09 +00:00
|
|
|
config := v.config.Request
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(serial.WriteString(strings.Join([]string{config.Method.GetValue(), config.PickUri(), config.GetFullVersion()}, " ")))
|
|
|
|
header.AppendFunc(writeCRLF)
|
2016-10-31 21:26:46 +00:00
|
|
|
|
2016-11-02 21:26:21 +00:00
|
|
|
headers := config.PickHeaders()
|
|
|
|
for _, h := range headers {
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(serial.WriteString(h))
|
|
|
|
header.AppendFunc(writeCRLF)
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(writeCRLF)
|
2016-11-03 22:14:27 +00:00
|
|
|
return &HeaderWriter{
|
|
|
|
header: header,
|
|
|
|
}
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v HttpAuthenticator) GetServerWriter() *HeaderWriter {
|
2016-12-09 10:35:27 +00:00
|
|
|
header := buf.NewSmallBuffer()
|
2016-11-27 20:39:09 +00:00
|
|
|
config := v.config.Response
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(serial.WriteString(strings.Join([]string{config.GetFullVersion(), config.Status.GetCode(), config.Status.GetReason()}, " ")))
|
|
|
|
header.AppendFunc(writeCRLF)
|
2016-10-31 21:26:46 +00:00
|
|
|
|
2016-11-02 21:26:21 +00:00
|
|
|
headers := config.PickHeaders()
|
2016-10-31 21:26:46 +00:00
|
|
|
for _, h := range headers {
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(serial.WriteString(h))
|
|
|
|
header.AppendFunc(writeCRLF)
|
2016-11-06 12:38:32 +00:00
|
|
|
}
|
|
|
|
if !config.HasHeader("Date") {
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(serial.WriteString("Date: "))
|
|
|
|
header.AppendFunc(serial.WriteString(time.Now().Format(http.TimeFormat)))
|
|
|
|
header.AppendFunc(writeCRLF)
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
2016-12-06 10:03:42 +00:00
|
|
|
header.AppendFunc(writeCRLF)
|
2016-11-03 22:14:27 +00:00
|
|
|
return &HeaderWriter{
|
|
|
|
header: header,
|
|
|
|
}
|
2016-11-02 21:26:21 +00:00
|
|
|
}
|
2016-10-31 21:26:46 +00:00
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v HttpAuthenticator) Client(conn net.Conn) net.Conn {
|
|
|
|
if v.config.Request == nil && v.config.Response == nil {
|
2016-11-03 22:14:27 +00:00
|
|
|
return conn
|
|
|
|
}
|
2016-11-05 00:50:51 +00:00
|
|
|
var reader Reader = new(NoOpReader)
|
2016-11-27 20:39:09 +00:00
|
|
|
if v.config.Request != nil {
|
2016-11-05 00:50:51 +00:00
|
|
|
reader = new(HeaderReader)
|
|
|
|
}
|
|
|
|
|
|
|
|
var writer Writer = new(NoOpWriter)
|
2016-11-27 20:39:09 +00:00
|
|
|
if v.config.Response != nil {
|
|
|
|
writer = v.GetClientWriter()
|
2016-11-05 00:50:51 +00:00
|
|
|
}
|
|
|
|
return NewHttpConn(conn, reader, writer)
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
|
|
|
|
2016-11-27 20:39:09 +00:00
|
|
|
func (v HttpAuthenticator) Server(conn net.Conn) net.Conn {
|
|
|
|
if v.config.Request == nil && v.config.Response == nil {
|
2016-11-03 22:14:27 +00:00
|
|
|
return conn
|
|
|
|
}
|
2016-11-27 20:39:09 +00:00
|
|
|
return NewHttpConn(conn, new(HeaderReader), v.GetServerWriter())
|
2016-10-31 21:26:46 +00:00
|
|
|
}
|
2016-10-31 23:42:55 +00:00
|
|
|
|
2016-11-02 21:26:21 +00:00
|
|
|
type HttpAuthenticatorFactory struct{}
|
2016-10-31 23:42:55 +00:00
|
|
|
|
2016-11-02 21:26:21 +00:00
|
|
|
func (HttpAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
|
|
|
|
return HttpAuthenticator{
|
|
|
|
config: config.(*Config),
|
2016-10-31 23:42:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
2016-11-02 21:26:21 +00:00
|
|
|
internet.RegisterConnectionAuthenticator(loader.GetType(new(Config)), HttpAuthenticatorFactory{})
|
2016-10-31 23:42:55 +00:00
|
|
|
}
|