refine http header

pull/314/head
Darien Raymond 2016-11-02 22:26:21 +01:00
parent 1600a59254
commit 0747203132
No known key found for this signature in database
GPG Key ID: 7251FFA14BB18169
12 changed files with 336 additions and 201 deletions

1
all.go
View File

@ -20,6 +20,7 @@ import (
_ "v2ray.com/core/transport/internet/udp" _ "v2ray.com/core/transport/internet/udp"
_ "v2ray.com/core/transport/internet/ws" _ "v2ray.com/core/transport/internet/ws"
_ "v2ray.com/core/transport/internet/authenticators/http"
_ "v2ray.com/core/transport/internet/authenticators/noop" _ "v2ray.com/core/transport/internet/authenticators/noop"
_ "v2ray.com/core/transport/internet/authenticators/srtp" _ "v2ray.com/core/transport/internet/authenticators/srtp"
_ "v2ray.com/core/transport/internet/authenticators/utp" _ "v2ray.com/core/transport/internet/authenticators/utp"

View File

@ -4,6 +4,34 @@ import (
"v2ray.com/core/common/dice" "v2ray.com/core/common/dice"
) )
func (this *Version) GetValue() string {
if this == nil {
return "1.1"
}
return this.Value
}
func (this *Method) GetValue() string {
if this == nil {
return "GET"
}
return this.Value
}
func (this *Status) GetCode() string {
if this == nil {
return "200"
}
return this.Code
}
func (this *Status) GetReason() string {
if this == nil {
return "OK"
}
return this.Reason
}
func pickString(arr []string) string { func pickString(arr []string) string {
n := len(arr) n := len(arr)
if n == 0 { if n == 0 {
@ -30,8 +58,8 @@ func (this *RequestConfig) PickHeaders() []string {
return headers return headers
} }
func (this *RequestConfig) GetVersion() string { func (this *RequestConfig) GetFullVersion() string {
return "HTTP/" + this.Version return "HTTP/" + this.Version.GetValue()
} }
func (this *ResponseConfig) PickHeaders() []string { func (this *ResponseConfig) PickHeaders() []string {
@ -48,6 +76,6 @@ func (this *ResponseConfig) PickHeaders() []string {
return headers return headers
} }
func (this *ResponseConfig) GetVersion() string { func (this *ResponseConfig) GetFullVersion() string {
return "HTTP/" + this.Version return "HTTP/" + this.Version.GetValue()
} }

View File

@ -10,9 +10,12 @@ It is generated from these files:
It has these top-level messages: It has these top-level messages:
Header Header
HeaderEnding Version
Method
RequestConfig RequestConfig
Status
ResponseConfig ResponseConfig
Config
*/ */
package http package http
@ -43,20 +46,31 @@ func (m *Header) String() string { return proto.CompactTextString(m)
func (*Header) ProtoMessage() {} func (*Header) ProtoMessage() {}
func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } func (*Header) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type HeaderEnding struct { // HTTP version. Default value "1.1".
type Version struct {
Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"` Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
} }
func (m *HeaderEnding) Reset() { *m = HeaderEnding{} } func (m *Version) Reset() { *m = Version{} }
func (m *HeaderEnding) String() string { return proto.CompactTextString(m) } func (m *Version) String() string { return proto.CompactTextString(m) }
func (*HeaderEnding) ProtoMessage() {} func (*Version) ProtoMessage() {}
func (*HeaderEnding) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
// HTTP method. Default value "GET".
type Method struct {
Value string `protobuf:"bytes,1,opt,name=value" json:"value,omitempty"`
}
func (m *Method) Reset() { *m = Method{} }
func (m *Method) String() string { return proto.CompactTextString(m) }
func (*Method) ProtoMessage() {}
func (*Method) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
type RequestConfig struct { type RequestConfig struct {
// Full HTTP version like "1.1". // Full HTTP version like "1.1".
Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
// GET, POST, CONNECT etc // GET, POST, CONNECT etc
Method string `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"` Method *Method `protobuf:"bytes,2,opt,name=method" json:"method,omitempty"`
// URI like "/login.php" // URI like "/login.php"
Uri []string `protobuf:"bytes,3,rep,name=uri" json:"uri,omitempty"` Uri []string `protobuf:"bytes,3,rep,name=uri" json:"uri,omitempty"`
Header []*Header `protobuf:"bytes,4,rep,name=header" json:"header,omitempty"` Header []*Header `protobuf:"bytes,4,rep,name=header" json:"header,omitempty"`
@ -65,7 +79,21 @@ type RequestConfig struct {
func (m *RequestConfig) Reset() { *m = RequestConfig{} } func (m *RequestConfig) Reset() { *m = RequestConfig{} }
func (m *RequestConfig) String() string { return proto.CompactTextString(m) } func (m *RequestConfig) String() string { return proto.CompactTextString(m) }
func (*RequestConfig) ProtoMessage() {} func (*RequestConfig) ProtoMessage() {}
func (*RequestConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (*RequestConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *RequestConfig) GetVersion() *Version {
if m != nil {
return m.Version
}
return nil
}
func (m *RequestConfig) GetMethod() *Method {
if m != nil {
return m.Method
}
return nil
}
func (m *RequestConfig) GetHeader() []*Header { func (m *RequestConfig) GetHeader() []*Header {
if m != nil { if m != nil {
@ -74,17 +102,42 @@ func (m *RequestConfig) GetHeader() []*Header {
return nil return nil
} }
type Status struct {
// Status code. Default "200".
Code string `protobuf:"bytes,1,opt,name=code" json:"code,omitempty"`
// Statue reason. Default "OK".
Reason string `protobuf:"bytes,2,opt,name=reason" json:"reason,omitempty"`
}
func (m *Status) Reset() { *m = Status{} }
func (m *Status) String() string { return proto.CompactTextString(m) }
func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
type ResponseConfig struct { type ResponseConfig struct {
Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` Version *Version `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"`
Status string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"` Status *Status `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
Reason string `protobuf:"bytes,3,opt,name=reason" json:"reason,omitempty"` Header []*Header `protobuf:"bytes,3,rep,name=header" json:"header,omitempty"`
Header []*Header `protobuf:"bytes,4,rep,name=header" json:"header,omitempty"`
} }
func (m *ResponseConfig) Reset() { *m = ResponseConfig{} } func (m *ResponseConfig) Reset() { *m = ResponseConfig{} }
func (m *ResponseConfig) String() string { return proto.CompactTextString(m) } func (m *ResponseConfig) String() string { return proto.CompactTextString(m) }
func (*ResponseConfig) ProtoMessage() {} func (*ResponseConfig) ProtoMessage() {}
func (*ResponseConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (*ResponseConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *ResponseConfig) GetVersion() *Version {
if m != nil {
return m.Version
}
return nil
}
func (m *ResponseConfig) GetStatus() *Status {
if m != nil {
return m.Status
}
return nil
}
func (m *ResponseConfig) GetHeader() []*Header { func (m *ResponseConfig) GetHeader() []*Header {
if m != nil { if m != nil {
@ -93,11 +146,38 @@ func (m *ResponseConfig) GetHeader() []*Header {
return nil return nil
} }
type Config struct {
Request *RequestConfig `protobuf:"bytes,1,opt,name=request" json:"request,omitempty"`
Response *ResponseConfig `protobuf:"bytes,2,opt,name=response" json:"response,omitempty"`
}
func (m *Config) Reset() { *m = Config{} }
func (m *Config) String() string { return proto.CompactTextString(m) }
func (*Config) ProtoMessage() {}
func (*Config) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *Config) GetRequest() *RequestConfig {
if m != nil {
return m.Request
}
return nil
}
func (m *Config) GetResponse() *ResponseConfig {
if m != nil {
return m.Response
}
return nil
}
func init() { func init() {
proto.RegisterType((*Header)(nil), "v2ray.core.transport.internet.authenticators.http.Header") proto.RegisterType((*Header)(nil), "v2ray.core.transport.internet.authenticators.http.Header")
proto.RegisterType((*HeaderEnding)(nil), "v2ray.core.transport.internet.authenticators.http.HeaderEnding") proto.RegisterType((*Version)(nil), "v2ray.core.transport.internet.authenticators.http.Version")
proto.RegisterType((*Method)(nil), "v2ray.core.transport.internet.authenticators.http.Method")
proto.RegisterType((*RequestConfig)(nil), "v2ray.core.transport.internet.authenticators.http.RequestConfig") proto.RegisterType((*RequestConfig)(nil), "v2ray.core.transport.internet.authenticators.http.RequestConfig")
proto.RegisterType((*Status)(nil), "v2ray.core.transport.internet.authenticators.http.Status")
proto.RegisterType((*ResponseConfig)(nil), "v2ray.core.transport.internet.authenticators.http.ResponseConfig") proto.RegisterType((*ResponseConfig)(nil), "v2ray.core.transport.internet.authenticators.http.ResponseConfig")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.authenticators.http.Config")
} }
func init() { func init() {
@ -105,24 +185,30 @@ func init() {
} }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 303 bytes of a gzipped FileDescriptorProto // 389 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x92, 0x31, 0x4b, 0xfc, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x94, 0xc1, 0x4e, 0xe3, 0x30,
0x10, 0xc5, 0xc9, 0xe5, 0xfe, 0xf9, 0x73, 0x73, 0x2a, 0xb2, 0x88, 0x6c, 0x79, 0x1c, 0x16, 0x57, 0x10, 0x40, 0xd5, 0xa4, 0x9b, 0x6e, 0xa7, 0xda, 0xd5, 0xca, 0x5a, 0xad, 0x72, 0xda, 0xad, 0x72,
0x6d, 0xf0, 0xc4, 0xc2, 0xf6, 0x44, 0x10, 0x2b, 0x4d, 0x69, 0xb7, 0xe6, 0xc6, 0x4b, 0xc0, 0xec, 0xea, 0xc9, 0xd1, 0x76, 0x97, 0x03, 0x9c, 0xa0, 0x5c, 0x10, 0x12, 0x12, 0x18, 0xc4, 0xa1, 0x12,
0xc4, 0xd9, 0x49, 0xc0, 0x2f, 0x64, 0xe7, 0x77, 0x94, 0x64, 0x13, 0xc5, 0xce, 0x2b, 0xec, 0xf6, 0x07, 0x93, 0x0e, 0x24, 0x12, 0xb1, 0x83, 0xed, 0x54, 0xe2, 0x1f, 0xf8, 0x05, 0xbe, 0x86, 0x1f,
0xcd, 0xce, 0xef, 0xcd, 0x1b, 0x18, 0xd8, 0xb4, 0x6b, 0xb6, 0x6f, 0x26, 0xa7, 0x2a, 0xcd, 0x89, 0x43, 0xb1, 0x9d, 0xd2, 0x1e, 0x38, 0x34, 0xc0, 0xcd, 0x4e, 0x66, 0x9e, 0x67, 0xde, 0x58, 0x86,
0x31, 0x15, 0xb6, 0xce, 0xd7, 0xc4, 0x92, 0x96, 0x4e, 0x90, 0x1d, 0x4a, 0x6a, 0x1b, 0x29, 0xd0, 0xd9, 0x72, 0xaa, 0xf8, 0x03, 0xcd, 0x64, 0x99, 0x66, 0x52, 0x61, 0x6a, 0x14, 0x17, 0xba, 0x92,
0x49, 0x99, 0x5b, 0x21, 0xf6, 0x69, 0x21, 0x52, 0xa7, 0x39, 0xb9, 0xe7, 0x72, 0x67, 0x6a, 0x26, 0xca, 0xa4, 0x85, 0x30, 0xa8, 0x04, 0x9a, 0x94, 0xd7, 0x26, 0x47, 0x61, 0x8a, 0x8c, 0x1b, 0xa9,
0x21, 0x75, 0x3e, 0x7a, 0x30, 0x9a, 0x2f, 0xde, 0x8c, 0xbc, 0xf9, 0xc9, 0x9b, 0x8e, 0x5f, 0xae, 0x74, 0x9a, 0x1b, 0x53, 0xa5, 0x99, 0x14, 0x37, 0xc5, 0x2d, 0xad, 0x94, 0x34, 0x92, 0xfc, 0x6d,
0x21, 0xb9, 0x45, 0xbb, 0x45, 0x56, 0x0a, 0xa6, 0xce, 0x56, 0xa8, 0xa3, 0x45, 0xb4, 0x9a, 0x65, 0x19, 0x0a, 0xe9, 0x2a, 0x9f, 0xb6, 0xf9, 0x74, 0x33, 0x9f, 0x36, 0xf9, 0xc9, 0x14, 0xa2, 0x23,
0xfd, 0x5b, 0x9d, 0xc0, 0xbf, 0xd6, 0xbe, 0x34, 0xa8, 0x27, 0x8b, 0x78, 0x35, 0xcb, 0x82, 0x58, 0xe4, 0x0b, 0x54, 0x84, 0x40, 0x5f, 0xf0, 0x12, 0xe3, 0xde, 0xb8, 0x37, 0x19, 0x32, 0xbb, 0x26,
0x9e, 0xc1, 0x41, 0x60, 0x6e, 0xdc, 0xb6, 0x74, 0xbb, 0xef, 0xae, 0x80, 0x0e, 0x5d, 0xef, 0x11, 0x3f, 0xe1, 0xcb, 0x92, 0xdf, 0xd5, 0x18, 0x07, 0xe3, 0x70, 0x32, 0x64, 0x6e, 0x93, 0xfc, 0x81,
0x1c, 0x66, 0xf8, 0xda, 0xa0, 0x97, 0xeb, 0x3e, 0xa4, 0xd2, 0xf0, 0xbf, 0x45, 0xf6, 0x25, 0xb9, 0xc1, 0x25, 0x2a, 0x5d, 0x48, 0xf1, 0x1a, 0xe0, 0xb2, 0x7c, 0xc0, 0x6f, 0x88, 0x4e, 0xd0, 0xe4,
0xa1, 0x73, 0x94, 0xea, 0x14, 0x92, 0x0a, 0xa5, 0xa0, 0xad, 0x9e, 0xf4, 0x1f, 0x83, 0x52, 0xc7, 0x72, 0xf1, 0xc6, 0xff, 0xa7, 0x00, 0xbe, 0x31, 0xbc, 0xaf, 0x51, 0x9b, 0x43, 0x5b, 0x3f, 0xb9,
0x10, 0x37, 0x5c, 0xea, 0xb8, 0x9f, 0xde, 0x3d, 0xd5, 0x03, 0x24, 0x45, 0x3f, 0x5b, 0x4f, 0x17, 0x80, 0xc1, 0xd2, 0x21, 0x6d, 0xe4, 0x68, 0xba, 0x47, 0xb7, 0xee, 0x85, 0xfa, 0xa2, 0x58, 0x8b,
0xf1, 0x6a, 0xbe, 0xbe, 0x32, 0x7b, 0xef, 0x6c, 0x42, 0xf8, 0x6c, 0x30, 0x5a, 0x7e, 0x44, 0x70, 0x22, 0x67, 0x10, 0x95, 0xb6, 0x8e, 0x38, 0xb0, 0xd0, 0xdd, 0x0e, 0x50, 0xd7, 0x08, 0xf3, 0x20,
0x94, 0xa1, 0xaf, 0xc9, 0x79, 0xfc, 0x4d, 0x52, 0x2f, 0x56, 0x1a, 0x3f, 0x26, 0x0d, 0xaa, 0xab, 0xf2, 0x03, 0xc2, 0x5a, 0x15, 0x71, 0x68, 0x7d, 0x34, 0xcb, 0xe6, 0x90, 0xdc, 0x1a, 0x8c, 0xfb,
0x33, 0x5a, 0x4f, 0x4e, 0xc7, 0xa1, 0x1e, 0xd4, 0x1f, 0xe4, 0xdd, 0xdc, 0xc1, 0x65, 0x4e, 0xd5, 0xe3, 0xb0, 0xe3, 0x21, 0x6e, 0x04, 0xcc, 0x83, 0x92, 0xff, 0x10, 0x9d, 0x1b, 0x6e, 0x6a, 0xdd,
0xfe, 0x3e, 0x9b, 0x79, 0xd8, 0xee, 0xbe, 0xbb, 0x95, 0xc7, 0x69, 0x57, 0x7a, 0x4a, 0xfa, 0xc3, 0x0c, 0x25, 0x93, 0x8b, 0xd5, 0x50, 0x9a, 0x35, 0xf9, 0x05, 0x91, 0x42, 0xae, 0xa5, 0xb0, 0x5d,
0xb9, 0xf8, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x78, 0x8c, 0xa7, 0x40, 0x7e, 0x02, 0x00, 0x00, 0x0d, 0x99, 0xdf, 0x25, 0x8f, 0x01, 0x7c, 0x67, 0xa8, 0x2b, 0x29, 0x34, 0x7e, 0xb6, 0x56, 0x6d,
0xcb, 0x7b, 0x87, 0x56, 0xd7, 0x1f, 0xf3, 0xa0, 0x35, 0x89, 0xe1, 0x47, 0x49, 0x7c, 0xee, 0x41,
0xe4, 0x35, 0xcc, 0x61, 0xa0, 0xdc, 0x75, 0xf3, 0x1a, 0xf6, 0x3b, 0xe0, 0x37, 0x2e, 0x2c, 0x6b,
0x81, 0xe4, 0x0a, 0xbe, 0x2a, 0x2f, 0xdd, 0xeb, 0x38, 0xe8, 0x04, 0x5f, 0x9f, 0x1b, 0x5b, 0x21,
0x67, 0xc7, 0xb0, 0x93, 0xc9, 0x72, 0x7b, 0xe2, 0x6c, 0xe4, 0x50, 0xa7, 0xcd, 0xc3, 0x30, 0xef,
0x37, 0x9f, 0xae, 0x23, 0xfb, 0x4a, 0xfc, 0x7b, 0x09, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x1d, 0x02,
0x42, 0x6b, 0x04, 0x00, 0x00,
} }

View File

@ -13,16 +13,22 @@ message Header {
repeated string value = 2; repeated string value = 2;
} }
message HeaderEnding { // HTTP version. Default value "1.1".
message Version {
string value = 1;
}
// HTTP method. Default value "GET".
message Method {
string value = 1; string value = 1;
} }
message RequestConfig { message RequestConfig {
// Full HTTP version like "1.1". // Full HTTP version like "1.1".
string version = 1; Version version = 1;
// GET, POST, CONNECT etc // GET, POST, CONNECT etc
string method = 2; Method method = 2;
// URI like "/login.php" // URI like "/login.php"
repeated string uri = 3; repeated string uri = 3;
@ -30,12 +36,23 @@ message RequestConfig {
repeated Header header = 4; repeated Header header = 4;
} }
message ResponseConfig { message Status {
string version = 1; // Status code. Default "200".
string code = 1;
string status = 2; // Statue reason. Default "OK".
string reason = 2;
string reason = 3; }
repeated Header header = 4; message ResponseConfig {
Version version = 1;
Status status = 2;
repeated Header header = 3;
}
message Config {
RequestConfig request = 1;
ResponseConfig response = 2;
} }

View File

@ -2,7 +2,8 @@ package http
import ( import (
"bytes" "bytes"
"io" "net"
"v2ray.com/core/common/alloc" "v2ray.com/core/common/alloc"
"v2ray.com/core/common/loader" "v2ray.com/core/common/loader"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
@ -13,122 +14,117 @@ const (
ENDING = CRLF + CRLF ENDING = CRLF + CRLF
) )
type RequestAuthenticator struct { type HttpConn struct {
config *RequestConfig net.Conn
buffer *alloc.Buffer
readHeader bool
writeHeaderContent *alloc.Buffer
writeHeader bool
} }
func (this *RequestAuthenticator) Seal(writer io.Writer) io.Writer { func NewHttpConn(conn net.Conn, writeHeaderContent *alloc.Buffer) *HttpConn {
header := alloc.NewLocalBuffer(2048) return &HttpConn{
header.AppendString(this.config.Method).AppendString(" ").AppendString(this.config.PickUri()).AppendString(" ").AppendString(this.config.GetVersion()).AppendString(CRLF) Conn: conn,
readHeader: true,
headers := this.config.PickHeaders() writeHeader: true,
for _, h := range headers { writeHeaderContent: writeHeaderContent,
header.AppendString(h).AppendString(CRLF)
} }
header.AppendString(CRLF)
writer.Write(header.Value)
header.Release()
return writer
} }
func (this *RequestAuthenticator) Open(reader io.Reader) (io.Reader, error) { func (this *HttpConn) Read(b []byte) (int, error) {
if this.readHeader {
buffer := alloc.NewLocalBuffer(2048) buffer := alloc.NewLocalBuffer(2048)
for { for {
_, err := buffer.FillFrom(reader) _, err := buffer.FillFrom(this.Conn)
if err != nil { if err != nil {
return nil, err return 0, err
} }
if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 { if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 {
buffer.SliceFrom(n + len(ENDING)) buffer.SliceFrom(n + len(ENDING))
return &BufferAndReader{ break
buffer: buffer,
reader: reader,
}, nil
} }
if buffer.Len() >= len(ENDING) { if buffer.Len() >= len(ENDING) {
copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):]) copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):])
buffer.Slice(0, len(ENDING)) buffer.Slice(0, len(ENDING))
} }
} }
} this.buffer = buffer
this.readHeader = false
type BufferAndReader struct {
buffer *alloc.Buffer
reader io.Reader
}
func (this *BufferAndReader) Read(b []byte) (int, error) {
if this.buffer.Len() == 0 {
return this.reader.Read(b)
} }
n, err := this.buffer.Read(b)
if n == this.buffer.Len() { if this.buffer.Len() > 0 {
nBytes, err := this.buffer.Read(b)
if nBytes == this.buffer.Len() {
this.buffer.Release() this.buffer.Release()
this.buffer = nil this.buffer = nil
} }
return n, err return nBytes, err
}
type RequestAuthenticatorFactory struct{}
func (RequestAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
return &RequestAuthenticator{
config: config.(*RequestConfig),
} }
return this.Conn.Read(b)
} }
type ResponseAuthenticator struct { func (this *HttpConn) Write(b []byte) (int, error) {
config *ResponseConfig if this.writeHeader {
_, err := this.Conn.Write(this.writeHeaderContent.Value)
this.writeHeaderContent.Release()
if err != nil {
return 0, err
}
this.writeHeader = false
}
return this.Conn.Write(b)
} }
func (this *ResponseAuthenticator) Seal(writer io.Writer) io.Writer { type HttpAuthenticator struct {
config *Config
}
func (this HttpAuthenticator) GetClientWriteHeader() *alloc.Buffer {
header := alloc.NewLocalBuffer(2048) header := alloc.NewLocalBuffer(2048)
header.AppendString(this.config.GetVersion()).AppendString(" ").AppendString(this.config.Status).AppendString(" ").AppendString(this.config.Reason).AppendString(CRLF) config := this.config.Request
header.AppendString(config.Method.GetValue()).AppendString(" ").AppendString(config.PickUri()).AppendString(" ").AppendString(config.GetFullVersion()).AppendString(CRLF)
headers := this.config.PickHeaders() headers := config.PickHeaders()
for _, h := range headers { for _, h := range headers {
header.AppendString(h).AppendString(CRLF) header.AppendString(h).AppendString(CRLF)
} }
header.AppendString(CRLF) header.AppendString(CRLF)
return header
writer.Write(header.Value)
header.Release()
return writer
} }
func (this *ResponseAuthenticator) Open(reader io.Reader) (io.Reader, error) { func (this HttpAuthenticator) GetServerWriteHeader() *alloc.Buffer {
buffer := alloc.NewLocalBuffer(2048) header := alloc.NewLocalBuffer(2048)
for { config := this.config.Response
_, err := buffer.FillFrom(reader) header.AppendString(config.GetFullVersion()).AppendString(" ").AppendString(config.Status.GetCode()).AppendString(" ").AppendString(config.Status.GetReason()).AppendString(CRLF)
if err != nil {
return nil, err headers := config.PickHeaders()
} for _, h := range headers {
if n := bytes.Index(buffer.Value, []byte(ENDING)); n != -1 { header.AppendString(h).AppendString(CRLF)
buffer.SliceFrom(n + len(ENDING))
return &BufferAndReader{
buffer: buffer,
reader: reader,
}, nil
}
if buffer.Len() >= len(ENDING) {
copy(buffer.Value, buffer.Value[buffer.Len()-len(ENDING):])
buffer.Slice(0, len(ENDING))
}
} }
header.AppendString(CRLF)
return header
} }
type ResponseAuthenticatorFactory struct{} func (this HttpAuthenticator) Client(conn net.Conn) net.Conn {
return NewHttpConn(conn, this.GetClientWriteHeader())
}
func (ResponseAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator { func (this HttpAuthenticator) Server(conn net.Conn) net.Conn {
return &ResponseAuthenticator{ return NewHttpConn(conn, this.GetServerWriteHeader())
config: config.(*ResponseConfig), }
type HttpAuthenticatorFactory struct{}
func (HttpAuthenticatorFactory) Create(config interface{}) internet.ConnectionAuthenticator {
return HttpAuthenticator{
config: config.(*Config),
} }
} }
func init() { func init() {
internet.RegisterConnectionAuthenticator(loader.GetType(new(RequestConfig)), RequestAuthenticatorFactory{}) internet.RegisterConnectionAuthenticator(loader.GetType(new(Config)), HttpAuthenticatorFactory{})
internet.RegisterConnectionAuthenticator(loader.GetType(new(ResponseConfig)), ResponseAuthenticatorFactory{})
} }

View File

@ -1,38 +0,0 @@
package http_test
import (
"testing"
"v2ray.com/core/common/alloc"
"v2ray.com/core/testing/assert"
. "v2ray.com/core/transport/internet/authenticators/http"
)
func TestRequestOpenSeal(t *testing.T) {
assert := assert.On(t)
content := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g'}
cache := alloc.NewLargeBuffer()
http := (RequestAuthenticatorFactory{}).Create(&RequestConfig{
Method: "GET",
Uri: []string{"/"},
Version: "1.1",
Header: []*Header{
{
Name: "Content-Length",
Value: []string{"123"},
},
},
})
http.Seal(cache).Write(content)
actualContent := make([]byte, 256)
reader, err := http.Open(cache)
assert.Error(err).IsNil()
n, err := reader.Read(actualContent)
assert.Error(err).IsNil()
assert.Bytes(content).Equals(actualContent[:n])
}

View File

@ -1,7 +1,8 @@
package noop package noop
import ( import (
"io" "net"
"v2ray.com/core/common/alloc" "v2ray.com/core/common/alloc"
"v2ray.com/core/common/loader" "v2ray.com/core/common/loader"
"v2ray.com/core/transport/internet" "v2ray.com/core/transport/internet"
@ -25,12 +26,12 @@ func (this NoOpAuthenticatorFactory) Create(config interface{}) internet.Authent
type NoOpConnectionAuthenticator struct{} type NoOpConnectionAuthenticator struct{}
func (NoOpConnectionAuthenticator) Open(reader io.Reader) (io.Reader, error) { func (NoOpConnectionAuthenticator) Client(conn net.Conn) net.Conn {
return reader, nil return conn
} }
func (NoOpConnectionAuthenticator) Seal(writer io.Writer) io.Writer { func (NoOpConnectionAuthenticator) Server(conn net.Conn) net.Conn {
return writer return conn
} }
type NoOpConnectionAuthenticatorFactory struct{} type NoOpConnectionAuthenticatorFactory struct{}

View File

@ -1,13 +1,14 @@
package internet package internet
import ( import (
"io" "net"
"v2ray.com/core/common" "v2ray.com/core/common"
) )
type ConnectionAuthenticator interface { type ConnectionAuthenticator interface {
Seal(io.Writer) io.Writer Client(net.Conn) net.Conn
Open(io.Reader) (io.Reader, error) Server(net.Conn) net.Conn
} }
type ConnectionAuthenticatorFactory interface { type ConnectionAuthenticatorFactory interface {

View File

@ -17,6 +17,7 @@ package tcp
import proto "github.com/golang/protobuf/proto" import proto "github.com/golang/protobuf/proto"
import fmt "fmt" import fmt "fmt"
import math "math" import math "math"
import v2ray_core_common_loader "v2ray.com/core/common/loader"
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal var _ = proto.Marshal
@ -40,6 +41,7 @@ func (*ConnectionReuse) Descriptor() ([]byte, []int) { return fileDescriptor0, [
type Config struct { type Config struct {
ConnectionReuse *ConnectionReuse `protobuf:"bytes,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"` ConnectionReuse *ConnectionReuse `protobuf:"bytes,1,opt,name=connection_reuse,json=connectionReuse" json:"connection_reuse,omitempty"`
HeaderSettings *v2ray_core_common_loader.TypedSettings `protobuf:"bytes,2,opt,name=header_settings,json=headerSettings" json:"header_settings,omitempty"`
} }
func (m *Config) Reset() { *m = Config{} } func (m *Config) Reset() { *m = Config{} }
@ -54,6 +56,13 @@ func (m *Config) GetConnectionReuse() *ConnectionReuse {
return nil return nil
} }
func (m *Config) GetHeaderSettings() *v2ray_core_common_loader.TypedSettings {
if m != nil {
return m.HeaderSettings
}
return nil
}
func init() { func init() {
proto.RegisterType((*ConnectionReuse)(nil), "v2ray.core.transport.internet.tcp.ConnectionReuse") proto.RegisterType((*ConnectionReuse)(nil), "v2ray.core.transport.internet.tcp.ConnectionReuse")
proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.tcp.Config") proto.RegisterType((*Config)(nil), "v2ray.core.transport.internet.tcp.Config")
@ -62,17 +71,21 @@ func init() {
func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tcp/config.proto", fileDescriptor0) } func init() { proto.RegisterFile("v2ray.com/core/transport/internet/tcp/config.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{ var fileDescriptor0 = []byte{
// 191 bytes of a gzipped FileDescriptorProto // 249 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x8f, 0x41, 0x6b, 0x83, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x90, 0xc1, 0x4a, 0xc3, 0x60,
0x10, 0x85, 0x91, 0x82, 0x94, 0xf5, 0x60, 0xf1, 0x50, 0x7a, 0x6c, 0x85, 0x42, 0x7b, 0xd9, 0x85, 0x10, 0x84, 0x89, 0x42, 0x90, 0xbf, 0x60, 0x24, 0x07, 0x29, 0x9e, 0xb4, 0x20, 0xd5, 0xcb, 0xfe,
0xed, 0xa9, 0x57, 0xfd, 0x03, 0xc1, 0x63, 0x20, 0x04, 0x1d, 0x26, 0x22, 0xc4, 0x99, 0x65, 0x9c, 0x10, 0x4f, 0x5e, 0xdb, 0x17, 0x28, 0xd1, 0x93, 0x20, 0x25, 0xdd, 0xae, 0x35, 0xd0, 0xec, 0xfe,
0x04, 0xf2, 0xef, 0x83, 0x26, 0x0a, 0xc9, 0xc5, 0xe3, 0x2e, 0xdf, 0xf7, 0xde, 0x3c, 0xe3, 0xcf, 0x6c, 0x56, 0x21, 0x8f, 0xe6, 0xdb, 0x49, 0x92, 0xa6, 0x94, 0x5c, 0x7a, 0x5c, 0x98, 0x99, 0xfd,
0x5e, 0xea, 0x8b, 0x05, 0xee, 0x1d, 0xb0, 0xa0, 0x53, 0xa9, 0x69, 0x08, 0x2c, 0xea, 0x3a, 0x52, 0x66, 0x5c, 0xf6, 0x9b, 0x69, 0xd1, 0x00, 0x4a, 0xe5, 0x51, 0x94, 0xbc, 0x69, 0xc1, 0x75, 0x10,
0x14, 0x42, 0x75, 0x0a, 0xc1, 0x01, 0xd3, 0xa1, 0x6b, 0x6d, 0x10, 0x56, 0xce, 0xbe, 0x66, 0x47, 0x35, 0x5f, 0xb2, 0x91, 0x32, 0x99, 0x37, 0x0c, 0x1e, 0x85, 0xbf, 0xca, 0x1d, 0x04, 0x15, 0x93,
0xd0, 0x2e, 0xbc, 0x9d, 0x79, 0xab, 0x10, 0xf2, 0x5f, 0x93, 0x96, 0x4c, 0x84, 0xa0, 0x1d, 0x53, 0xf4, 0x61, 0xf0, 0x28, 0xc1, 0x51, 0x0f, 0x83, 0x1e, 0x0c, 0xc3, 0xdd, 0x7c, 0x14, 0x8b, 0x52,
0x85, 0xa7, 0x01, 0xb3, 0x77, 0x13, 0x23, 0xd5, 0xcd, 0x11, 0x3f, 0xa2, 0xcf, 0xe8, 0xe7, 0xb5, 0x55, 0xc2, 0x7e, 0x2f, 0xc5, 0x96, 0xd4, 0x5b, 0x13, 0xa8, 0xcf, 0x9a, 0x3d, 0xbb, 0x64, 0x29,
0xba, 0xbf, 0xf2, 0xd6, 0xc4, 0xe5, 0x94, 0x9e, 0xed, 0xcc, 0x1b, 0x2c, 0xd2, 0x5e, 0x46, 0x6b, 0xcc, 0x84, 0x56, 0x0a, 0xe7, 0xf4, 0x53, 0x53, 0x7a, 0xeb, 0x62, 0xe2, 0x62, 0xb3, 0xa7, 0x69,
0x62, 0x13, 0xef, 0xed, 0x6a, 0xa5, 0x7d, 0xea, 0xab, 0x52, 0x78, 0xfc, 0x28, 0xfe, 0xcd, 0x37, 0x74, 0x1f, 0x3d, 0x5d, 0xe5, 0x87, 0x6b, 0xf6, 0x17, 0xb9, 0x78, 0xd9, 0x71, 0xa4, 0x9f, 0xee,
0x70, 0xbf, 0x9e, 0x54, 0x24, 0xb7, 0x7b, 0x36, 0xe3, 0xd8, 0xed, 0x8b, 0x42, 0x68, 0xe2, 0x69, 0x06, 0x8f, 0xae, 0xb5, 0xb6, 0xb6, 0x4e, 0x3c, 0xc9, 0x32, 0x38, 0x0b, 0x07, 0xa3, 0x87, 0x79,
0xf8, 0xdf, 0x35, 0x00, 0x00, 0xff, 0xff, 0xc1, 0x16, 0x42, 0x0b, 0x2e, 0x01, 0x00, 0x00, 0x82, 0x23, 0x82, 0x95, 0x4b, 0xbe, 0xa9, 0x25, 0x5d, 0xd7, 0x64, 0x56, 0xf2, 0xae, 0x9e, 0x5e,
0x74, 0xe9, 0xf3, 0xd3, 0xf4, 0xbe, 0x13, 0xf4, 0x9d, 0xe0, 0xbd, 0x09, 0xb4, 0x7d, 0x3b, 0xc8,
0xf3, 0xeb, 0xde, 0x3f, 0xdc, 0x8b, 0x57, 0xf7, 0x88, 0x52, 0x9d, 0x67, 0x5b, 0x4c, 0xfa, 0x86,
0xab, 0x76, 0x9c, 0x8f, 0x4b, 0xc3, 0xb0, 0x89, 0xbb, 0xa1, 0x5e, 0xfe, 0x03, 0x00, 0x00, 0xff,
0xff, 0xdf, 0xaf, 0x5e, 0x9f, 0xaa, 0x01, 0x00, 0x00,
} }

View File

@ -5,9 +5,12 @@ option go_package = "tcp";
option java_package = "com.v2ray.core.transport.internet.tcp"; option java_package = "com.v2ray.core.transport.internet.tcp";
option java_outer_classname = "ConfigProto"; option java_outer_classname = "ConfigProto";
import "v2ray.com/core/common/loader/type.proto";
message ConnectionReuse { message ConnectionReuse {
bool enable = 1; bool enable = 1;
} }
message Config { message Config {
ConnectionReuse connection_reuse = 1; ConnectionReuse connection_reuse = 1;
v2ray.core.common.loader.TypedSettings header_settings = 2;
} }

View File

@ -1,6 +1,7 @@
package tcp package tcp
import ( import (
"errors"
"net" "net"
"crypto/tls" "crypto/tls"
@ -51,6 +52,17 @@ func Dial(src v2net.Address, dest v2net.Destination, options internet.DialerOpti
conn = tls.Client(conn, config) conn = tls.Client(conn, config)
} }
} }
if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil {
return nil, errors.New("TCP: Failed to get header settings: " + err.Error())
}
auth, err := internet.CreateConnectionAuthenticator(tcpSettings.HeaderSettings.Type, headerConfig)
if err != nil {
return nil, errors.New("TCP: Failed to create header authenticator: " + err.Error())
}
conn = auth.Client(conn)
}
} }
return NewConnection(id, conn, globalCache, tcpSettings), nil return NewConnection(id, conn, globalCache, tcpSettings), nil
} }

View File

@ -28,6 +28,7 @@ type TCPListener struct {
listener *net.TCPListener listener *net.TCPListener
awaitingConns chan *ConnectionWithError awaitingConns chan *ConnectionWithError
tlsConfig *tls.Config tlsConfig *tls.Config
authConfig internet.ConnectionAuthenticator
config *Config config *Config
} }
@ -62,6 +63,17 @@ func ListenTCP(address v2net.Address, port v2net.Port, options internet.ListenOp
l.tlsConfig = tlsConfig.GetTLSConfig() l.tlsConfig = tlsConfig.GetTLSConfig()
} }
} }
if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil {
return nil, errors.New("TCP: Failed to get header settings: " + err.Error())
}
auth, err := internet.CreateConnectionAuthenticator(tcpSettings.HeaderSettings.Type, headerConfig)
if err != nil {
return nil, errors.New("TCP: Failed to create header authenticator: " + err.Error())
}
l.authConfig = auth
}
go l.KeepAccepting() go l.KeepAccepting()
return l, nil return l, nil
} }
@ -95,6 +107,9 @@ func (this *TCPListener) KeepAccepting() {
if this.tlsConfig != nil { if this.tlsConfig != nil {
conn = tls.Server(conn, this.tlsConfig) conn = tls.Server(conn, this.tlsConfig)
} }
if this.authConfig != nil {
conn = this.authConfig.Server(conn)
}
select { select {
case this.awaitingConns <- &ConnectionWithError{ case this.awaitingConns <- &ConnectionWithError{
conn: conn, conn: conn,